config: use and implement list macros Use list macros instead of manually changing the head and/or tail of the variable list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
diff --git a/src/config.c b/src/config.c
index 41db3c5..d537fd8 100644
--- a/src/config.c
+++ b/src/config.c
@@ -48,11 +48,15 @@ static git_cvar *cvar_free(git_cvar *var)
return next;
}
-static void cvar_list_free(git_cvar *start)
+static void cvar_list_free(git_cvar_list *list)
{
- git_cvar *iter = start;
+ git_cvar *cur;
- while ((iter = cvar_free(iter)) != NULL);
+ while (!CVAR_LIST_EMPTY(list)) {
+ cur = CVAR_LIST_HEAD(list);
+ CVAR_LIST_REMOVE_HEAD(list);
+ cvar_free(cur);
+ }
}
/*
@@ -112,11 +116,11 @@ static int cvar_name_match(const char *local, const char *input)
return !strcasecmp(input_dot, local_dot);
}
-static git_cvar *cvar_list_find(git_cvar *start, const char *name)
+static git_cvar *cvar_list_find(git_cvar_list *list, const char *name)
{
git_cvar *iter;
- CVAR_LIST_FOREACH (start, iter) {
+ CVAR_LIST_FOREACH (list, iter) {
if (cvar_name_match(iter->name, name))
return iter;
}
@@ -205,8 +209,7 @@ int git_config_open(git_config **cfg_out, const char *path)
return error;
cleanup:
- if (cfg->vars)
- cvar_list_free(cfg->vars);
+ cvar_list_free(&cfg->var_list);
if (cfg->file_path)
free(cfg->file_path);
gitfo_free_buf(&cfg->reader.buffer);
@@ -221,7 +224,7 @@ void git_config_free(git_config *cfg)
return;
free(cfg->file_path);
- cvar_list_free(cfg->vars);
+ cvar_list_free(&cfg->var_list);
free(cfg);
}
@@ -236,7 +239,7 @@ int git_config_foreach(git_config *cfg, int (*fn)(const char *, void *), void *d
git_cvar *var;
char *normalized;
- CVAR_LIST_FOREACH(cfg->vars, var) {
+ CVAR_LIST_FOREACH(&cfg->var_list, var) {
ret = cvar_name_normalize(var->name, &normalized);
if (ret < GIT_SUCCESS)
return ret;
@@ -266,7 +269,7 @@ static int config_set(git_config *cfg, const char *name, const char *value)
/*
* If it already exists, we just need to update its value.
*/
- existing = cvar_list_find(cfg->vars, name);
+ existing = cvar_list_find(&cfg->var_list, name);
if (existing != NULL) {
char *tmp = value ? git__strdup(value) : NULL;
if (tmp == NULL && value != NULL)
@@ -304,13 +307,7 @@ static int config_set(git_config *cfg, const char *name, const char *value)
var->next = NULL;
- if (cfg->vars_tail == NULL) {
- cfg->vars = cfg->vars_tail = var;
- }
- else {
- cfg->vars_tail->next = var;
- cfg->vars_tail = var;
- }
+ CVAR_LIST_APPEND(&cfg->var_list, var);
out:
if (error < GIT_SUCCESS)
@@ -369,7 +366,7 @@ static int config_get(git_config *cfg, const char *name, const char **out)
git_cvar *var;
int error = GIT_SUCCESS;
- var = cvar_list_find(cfg->vars, name);
+ var = cvar_list_find(&cfg->var_list, name);
if (var == NULL)
return GIT_ENOTFOUND;
diff --git a/src/config.h b/src/config.h
index 1e954ff..e54933d 100644
--- a/src/config.h
+++ b/src/config.h
@@ -3,9 +3,13 @@
#include "git2/config.h"
+typedef struct {
+ git_cvar *head;
+ git_cvar *tail;
+} git_cvar_list;
+
struct git_config {
- git_cvar *vars;
- git_cvar *vars_tail;
+ git_cvar_list var_list;
struct {
gitfo_buf buffer;
@@ -23,12 +27,44 @@ struct git_cvar {
char *value;
};
+#define CVAR_LIST_HEAD(list) ((list)->head)
+
+#define CVAR_LIST_TAIL(list) ((list)->tail)
+
+#define CVAR_LIST_NEXT(var) ((var)->next)
+
+#define CVAR_LIST_EMPTY(list) ((list)->head == NULL)
+
+#define CVAR_LIST_APPEND(list, var) do {\
+ if (CVAR_LIST_EMPTY(list)) {\
+ CVAR_LIST_HEAD(list) = CVAR_LIST_TAIL(list) = var;\
+ } else {\
+ CVAR_LIST_NEXT(CVAR_LIST_TAIL(list)) = var;\
+ CVAR_LIST_TAIL(list) = var;\
+ }\
+} while(0)
+
+#define CVAR_LIST_REMOVE_HEAD(list) do {\
+ CVAR_LIST_HEAD(list) = CVAR_LIST_NEXT(CVAR_LIST_HEAD(list));\
+} while(0)
+
+#define CVAR_LIST_REMOVE_AFTER(var) do {\
+ CVAR_LIST_NEXT(var) = CVAR_LIST_NEXT(CVAR_LIST_NEXT(var));\
+} while(0)
+
+#define CVAR_LIST_FOREACH(list, iter)\
+ for ((iter) = CVAR_LIST_HEAD(list);\
+ (iter) != NULL;\
+ (iter) = CVAR_LIST_NEXT(iter))
+
/*
- * If you're going to delete something inside this loop, it's such a
- * hassle that you should use the for-loop directly.
+ * Inspired by the FreeBSD functions
*/
-#define CVAR_LIST_FOREACH(start, iter) \
- for ((iter) = (start); (iter) != NULL; (iter) = (iter)->next)
+#define CVAR_LIST_FOREACH_SAFE(start, iter, tmp)\
+ for ((iter) = CVAR_LIST_HEAD(vars);\
+ (iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\
+ (iter) = (tmp))
+
void git__strtolower(char *str);
void git__strntolower(char *str, int len);