diff --git a/include/git2/config.h b/include/git2/config.h index a0dc11bb1..950312548 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -61,7 +61,7 @@ typedef struct { } git_config_entry; typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); -typedef struct git_config_backend_iter git_config_backend_iter; +typedef struct git_config_iterator git_config_iterator; typedef enum { GIT_CVAR_FALSE = 0, diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 09c79638a..45599dc69 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -20,6 +20,32 @@ */ GIT_BEGIN_DECL +/** + * Every iterator must have this struct as its first element, so the + * API can talk to it. You'd define your iterator as + * + * struct my_iterator { + * git_config_iterator parent; + * ... + * } + * + * and assign `iter->parent.backend` to your `git_config_backend`. + */ +struct git_config_iterator { + git_config_backend *backend; + unsigned int flags; + + /** + * Return the current entry and advance the iterator + */ + int (*next)(git_config_entry *entry, git_config_iterator *iter); + + /** + * Free the iterator + */ + void (*free)(git_config_iterator *iter); +}; + /** * Generic backend that implements the interface to * access a configuration file @@ -35,9 +61,7 @@ struct git_config_backend { int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); - int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *); - void (*iterator_free)(git_config_backend_iter *); - int (*next)(git_config_entry *, git_config_backend_iter *); + int (*iterator)(git_config_iterator **, struct git_config_backend *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); }; diff --git a/src/config.c b/src/config.c index a4627c9ad..5bec0f040 100644 --- a/src/config.c +++ b/src/config.c @@ -328,7 +328,7 @@ int git_config_backend_foreach_match( void *data) { git_config_entry entry; - git_config_backend_iter* iter; + git_config_iterator* iter; regex_t regex; int result = 0; @@ -340,12 +340,12 @@ int git_config_backend_foreach_match( } } - if ((result = backend->iterator_new(&iter, backend)) < 0) { + if ((result = backend->iterator(&iter, backend)) < 0) { iter = NULL; return -1; } - while(!(backend->next(&entry, iter) < 0)) { + while(!(iter->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0) continue; @@ -362,7 +362,7 @@ cleanup: if (regexp != NULL) regfree(®ex); - backend->iterator_free(iter); + iter->free(iter); return result; } diff --git a/src/config.h b/src/config.h index 2f7c96d7f..c5c11ae14 100644 --- a/src/config.h +++ b/src/config.h @@ -24,11 +24,6 @@ struct git_config { git_vector files; }; -struct git_config_backend_iter { - git_config_backend *backend; - unsigned int flags; -}; - extern int git_config_find_global_r(git_buf *global_config_path); extern int git_config_find_xdg_r(git_buf *system_config_path); extern int git_config_find_system_r(git_buf *system_config_path); diff --git a/src/config_file.c b/src/config_file.c index ed79624eb..3e0c6cc0b 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -28,9 +28,9 @@ typedef struct cvar_t { } cvar_t; typedef struct git_config_file_iter { - git_config_backend_iter parent; + git_config_iterator parent; git_strmap_iter iter; - cvar_t* next; + cvar_t* next_var; } git_config_file_iter; @@ -254,8 +254,44 @@ static void backend_free(git_config_backend *_backend) git__free(backend); } +static void config_iterator_free( + git_config_iterator* iter) +{ + git__free(iter); +} + +static int config_iterator_next( + git_config_entry *entry, + git_config_iterator *iter) +{ + git_config_file_iter *it = (git_config_file_iter *) iter; + diskfile_backend *b = (diskfile_backend *) it->parent.backend; + int err = 0; + cvar_t * var; + const char* key; + + if (it->next_var == NULL) { + err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values); + } else { + key = it->next_var->entry->name; + var = it->next_var; + } + + if (err < 0) { + it->next_var = NULL; + return -1; + } + + entry->name = key; + entry->value = var->entry->value; + entry->level = var->entry->level; + it->next_var = CVAR_LIST_NEXT(var); + + return 0; +} + static int config_iterator_new( - git_config_backend_iter **iter, + git_config_iterator **iter, struct git_config_backend* backend) { diskfile_backend *b = (diskfile_backend *)backend; @@ -265,44 +301,11 @@ static int config_iterator_new( it->parent.backend = backend; it->iter = git_strmap_begin(b->values); - it->next = NULL; - *iter = (git_config_backend_iter *) it; + it->next_var = NULL; - return 0; -} - -static void config_iterator_free( - git_config_backend_iter* iter) -{ - git__free(iter); -} - -static int config_iterator_next( - git_config_entry *entry, - git_config_backend_iter *iter) -{ - git_config_file_iter *it = (git_config_file_iter *) iter; - diskfile_backend *b = (diskfile_backend *) it->parent.backend; - int err = 0; - 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; - } - - if (err < 0) { - it->next = NULL; - return -1; - } - - entry->name = key; - entry->value = var->entry->value; - entry->level = var->entry->level; - it->next = CVAR_LIST_NEXT(var); + it->parent.next = config_iterator_next; + it->parent.free = config_iterator_free; + *iter = (git_config_iterator *) it; return 0; } @@ -607,9 +610,7 @@ 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.iterator_new = config_iterator_new; - backend->parent.iterator_free = config_iterator_free; - backend->parent.next = config_iterator_next; + backend->parent.iterator = config_iterator_new; backend->parent.refresh = config_refresh; backend->parent.free = backend_free;