Commit a603c191 by Nico von Geyso Committed by Carlos Martín Nieto

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`
parent 6385fc5f
...@@ -61,6 +61,7 @@ typedef struct { ...@@ -61,6 +61,7 @@ typedef struct {
} git_config_entry; } git_config_entry;
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
typedef struct git_config_backend_iter* git_config_backend_iter;
typedef enum { typedef enum {
GIT_CVAR_FALSE = 0, GIT_CVAR_FALSE = 0,
...@@ -535,6 +536,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value); ...@@ -535,6 +536,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value); GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
/**
* Perform an operation on each config variable in given config backend
* matching a regular expression.
*
* This behaviors like `git_config_foreach_match` except instead of all config
* entries it just enumerates through the given backend entry.
*
* @param backend where to get the variables from
* @param regexp regular expression to match against config names (can be NULL)
* @param callback the function to call on each variable
* @param payload the data to pass to the callback
*/
GIT_EXTERN(int) git_config_backend_foreach_match(
git_config_backend *backend,
const char *regexp,
int (*fn)(const git_config_entry *, void *),
void *data);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -35,7 +35,9 @@ struct git_config_backend { ...@@ -35,7 +35,9 @@ struct git_config_backend {
int (*set)(struct git_config_backend *, const char *key, const char *value); 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 (*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 (*del)(struct git_config_backend *, const char *key);
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload); int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *);
void (*iterator_free)(git_config_backend_iter *);
int (*next)(git_config_backend_iter *, git_config_entry *, struct git_config_backend *);
int (*refresh)(struct git_config_backend *); int (*refresh)(struct git_config_backend *);
void (*free)(struct git_config_backend *); void (*free)(struct git_config_backend *);
}; };
......
...@@ -321,6 +321,50 @@ int git_config_foreach( ...@@ -321,6 +321,50 @@ int git_config_foreach(
return git_config_foreach_match(cfg, NULL, cb, payload); 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( int git_config_foreach_match(
const git_config *cfg, const git_config *cfg,
const char *regexp, const char *regexp,
...@@ -335,7 +379,7 @@ int git_config_foreach_match( ...@@ -335,7 +379,7 @@ int git_config_foreach_match(
for (i = 0; i < cfg->files.length && ret == 0; ++i) { for (i = 0; i < cfg->files.length && ret == 0; ++i) {
internal = git_vector_get(&cfg->files, i); internal = git_vector_get(&cfg->files, i);
file = internal->file; file = internal->file;
ret = file->foreach(file, regexp, cb, payload); ret = git_config_backend_foreach_match(file, regexp, cb, payload);
} }
return ret; return ret;
......
...@@ -27,6 +27,12 @@ typedef struct cvar_t { ...@@ -27,6 +27,12 @@ typedef struct cvar_t {
git_config_entry *entry; git_config_entry *entry;
} cvar_t; } 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_HEAD(list) ((list)->head)
#define CVAR_LIST_TAIL(list) ((list)->tail) #define CVAR_LIST_TAIL(list) ((list)->tail)
...@@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend) ...@@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend)
git__free(backend); git__free(backend);
} }
static int file_foreach( static int config_iterator_new(
git_config_backend *backend, git_config_backend_iter *iter,
const char *regexp, struct git_config_backend* backend)
int (*fn)(const git_config_entry *, void *),
void *data)
{ {
diskfile_backend *b = (diskfile_backend *)backend; diskfile_backend *b = (diskfile_backend *)backend;
cvar_t *var, *next_var; git_config_file_iter **it= ((git_config_file_iter**) iter);
const char *key;
regex_t regex;
int result = 0;
if (!b->values) if (!b->values || git_strmap_num_entries(b->values) < 1)
return 0; return -1;
if (regexp != NULL) { *it = git__calloc(1, sizeof(git_config_file_iter));
if ((result = regcomp(&regex, regexp, REG_EXTENDED)) < 0) { GITERR_CHECK_ALLOC(it);
giterr_set_regex(&regex, result);
regfree(&regex);
return -1;
}
}
git_strmap_iter iter = git_strmap_begin(b->values); (*it)->iter = git_strmap_begin(b->values);
while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) { (*it)->next = NULL;
for (; var != NULL; var = next_var) {
next_var = CVAR_LIST_NEXT(var);
/* skip non-matching keys if regexp was provided */ return 0;
if (regexp && regexec(&regex, key, 0, NULL, 0) != 0) }
continue;
/* abort iterator on non-zero return value */ static void config_iterator_free(
if (fn(var->entry, data)) { git_config_backend_iter iter)
giterr_clear(); {
result = GIT_EUSER; git__free(iter);
goto cleanup; }
}
} 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 (err < 0) {
if (regexp != NULL) it->next = NULL;
regfree(&regex); 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) 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) ...@@ -595,7 +609,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
backend->parent.set = config_set; backend->parent.set = config_set;
backend->parent.set_multivar = config_set_multivar; backend->parent.set_multivar = config_set_multivar;
backend->parent.del = config_delete; 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.refresh = config_refresh;
backend->parent.free = backend_free; backend->parent.free = backend_free;
......
...@@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach( ...@@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach(
int (*fn)(const git_config_entry *entry, void *data), int (*fn)(const git_config_entry *entry, void *data),
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( GIT_INLINE(int) git_config_file_foreach_match(
...@@ -51,7 +51,7 @@ 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), int (*fn)(const git_config_entry *entry, void *data),
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); extern int git_config_file_normalize_section(char *start, char *end);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment