Commit 6b45cb8a89cd3b133183a093719a144a402450e9

Carlos Martín Nieto 2011-04-06T18:27:31

config: use and implement list macros Use list macros instead of manually changing the head and/or tail of the variable list.

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);