summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNico von Geyso <Nico.Geyso@FU-Berlin.de>2013-03-18 21:02:36 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2013-08-08 11:14:53 +0200
commita603c191578f7b33720e36e95421fcd58bc7abe4 (patch)
tree4de06cb51a580e85e5be38c91bbdfe980b4a55b5 /src
parent6385fc5ff5d669d3ec99d89f19c5860cf53011ba (diff)
downloadlibgit2-a603c191578f7b33720e36e95421fcd58bc7abe4.tar.gz
replaced foreach() with non callback based iterations in git_config_backend
new functions in struct git_config_backend: * iterator_new(...) * iterator_free(...) * next(...) The old callback based foreach style can still be used with `git_config_backend_foreach_match`
Diffstat (limited to 'src')
-rw-r--r--src/config.c46
-rw-r--r--src/config_file.c90
-rw-r--r--src/config_file.h4
3 files changed, 100 insertions, 40 deletions
diff --git a/src/config.c b/src/config.c
index 2a058549f..b421b3be1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -321,6 +321,50 @@ int git_config_foreach(
return git_config_foreach_match(cfg, NULL, cb, payload);
}
+int git_config_backend_foreach_match(
+ git_config_backend *backend,
+ const char *regexp,
+ int (*fn)(const git_config_entry *, void *),
+ void *data)
+{
+ git_config_entry entry;
+ git_config_backend_iter iter;
+ regex_t regex;
+ int result = 0;
+
+ if (regexp != NULL) {
+ if ((result = regcomp(&regex, regexp, REG_EXTENDED)) < 0) {
+ giterr_set_regex(&regex, result);
+ regfree(&regex);
+ return -1;
+ }
+ }
+
+ if (backend->iterator_new(&iter, backend) < 0)
+ return 0;
+
+ while(!(backend->next(&iter, &entry, backend) < 0)) {
+ /* skip non-matching keys if regexp was provided */
+ if (regexp && regexec(&regex, entry.name, 0, NULL, 0) != 0)
+ continue;
+
+ /* abort iterator on non-zero return value */
+ if (fn(&entry, data)) {
+ giterr_clear();
+ result = GIT_EUSER;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (regexp != NULL)
+ regfree(&regex);
+
+ backend->iterator_free(iter);
+
+ return result;
+}
+
int git_config_foreach_match(
const git_config *cfg,
const char *regexp,
@@ -335,7 +379,7 @@ int git_config_foreach_match(
for (i = 0; i < cfg->files.length && ret == 0; ++i) {
internal = git_vector_get(&cfg->files, i);
file = internal->file;
- ret = file->foreach(file, regexp, cb, payload);
+ ret = git_config_backend_foreach_match(file, regexp, cb, payload);
}
return ret;
diff --git a/src/config_file.c b/src/config_file.c
index 088f6190d..ff8f8fc15 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -27,6 +27,12 @@ typedef struct cvar_t {
git_config_entry *entry;
} cvar_t;
+typedef struct git_config_file_iter {
+ git_strmap_iter iter;
+ cvar_t* next;
+} git_config_file_iter;
+
+
#define CVAR_LIST_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail)
@@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend)
git__free(backend);
}
-static int file_foreach(
- git_config_backend *backend,
- const char *regexp,
- int (*fn)(const git_config_entry *, void *),
- void *data)
+static int config_iterator_new(
+ git_config_backend_iter *iter,
+ struct git_config_backend* backend)
{
diskfile_backend *b = (diskfile_backend *)backend;
- cvar_t *var, *next_var;
- const char *key;
- regex_t regex;
- int result = 0;
+ git_config_file_iter **it= ((git_config_file_iter**) iter);
- if (!b->values)
- return 0;
+ if (!b->values || git_strmap_num_entries(b->values) < 1)
+ return -1;
- if (regexp != NULL) {
- if ((result = regcomp(&regex, regexp, REG_EXTENDED)) < 0) {
- giterr_set_regex(&regex, result);
- regfree(&regex);
- return -1;
- }
- }
+ *it = git__calloc(1, sizeof(git_config_file_iter));
+ GITERR_CHECK_ALLOC(it);
- git_strmap_iter iter = git_strmap_begin(b->values);
- while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) {
- for (; var != NULL; var = next_var) {
- next_var = CVAR_LIST_NEXT(var);
+ (*it)->iter = git_strmap_begin(b->values);
+ (*it)->next = NULL;
- /* skip non-matching keys if regexp was provided */
- if (regexp && regexec(&regex, key, 0, NULL, 0) != 0)
- continue;
+ return 0;
+}
- /* abort iterator on non-zero return value */
- if (fn(var->entry, data)) {
- giterr_clear();
- result = GIT_EUSER;
- goto cleanup;
- }
- }
+static void config_iterator_free(
+ git_config_backend_iter iter)
+{
+ git__free(iter);
+}
+
+static int config_next(
+ git_config_backend_iter *iter,
+ git_config_entry* entry,
+ struct git_config_backend* backend)
+{
+ diskfile_backend *b = (diskfile_backend *)backend;
+ git_config_file_iter *it = *((git_config_file_iter**) iter);
+ int err;
+ cvar_t * var;
+ const char* key;
+
+ if (it->next == NULL) {
+ err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values);
+ } else {
+ key = it->next->entry->name;
+ var = it->next;
}
-cleanup:
- if (regexp != NULL)
- regfree(&regex);
+ if (err < 0) {
+ it->next = NULL;
+ return -1;
+ }
- return result;
+ entry->name = key;
+ entry->value = var->entry->value;
+ entry->level = var->entry->level;
+ it->next = CVAR_LIST_NEXT(var);
+
+ return 0;
}
static int config_set(git_config_backend *cfg, const char *name, const char *value)
@@ -595,7 +609,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend->parent.set = config_set;
backend->parent.set_multivar = config_set_multivar;
backend->parent.del = config_delete;
- backend->parent.foreach = file_foreach;
+ backend->parent.iterator_new = config_iterator_new;
+ backend->parent.iterator_free = config_iterator_free;
+ backend->parent.next = config_next;
backend->parent.refresh = config_refresh;
backend->parent.free = backend_free;
diff --git a/src/config_file.h b/src/config_file.h
index 7445859c4..d4a1a4061 100644
--- a/src/config_file.h
+++ b/src/config_file.h
@@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach(
int (*fn)(const git_config_entry *entry, void *data),
void *data)
{
- return cfg->foreach(cfg, NULL, fn, data);
+ return git_config_backend_foreach_match(cfg, NULL, fn, data);
}
GIT_INLINE(int) git_config_file_foreach_match(
@@ -51,7 +51,7 @@ GIT_INLINE(int) git_config_file_foreach_match(
int (*fn)(const git_config_entry *entry, void *data),
void *data)
{
- return cfg->foreach(cfg, regexp, fn, data);
+ return git_config_backend_foreach_match(cfg, regexp, fn, data);
}
extern int git_config_file_normalize_section(char *start, char *end);