From 3482cb4f6eba7f49489e5987bc2721007624d49e Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 21 Mar 2019 20:22:43 +0100 Subject: [PATCH] parse: attempt to enhance api --- examples/parse-yaml/parse-yaml.c | 2 +- include/ecoli_parse.h | 32 ++++++++++++++++++++----- src/ecoli_node_dynamic.c | 7 +++--- src/ecoli_parse.c | 41 ++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 23 deletions(-) diff --git a/examples/parse-yaml/parse-yaml.c b/examples/parse-yaml/parse-yaml.c index 218fe78..fbe4065 100644 --- a/examples/parse-yaml/parse-yaml.c +++ b/examples/parse-yaml/parse-yaml.c @@ -143,7 +143,7 @@ __dump_as_shell(FILE *f, const struct ec_parse *parse, size_t *seq) __dump_as_shell(f, child, seq); } - if (ec_parse_get_next(parse) != NULL) { + if (ec_parse_next(parse) != NULL) { fprintf(f, "ec_node%zu_next='ec_node%zu'\n", cur_seq, *seq + 1); } diff --git a/include/ecoli_parse.h b/include/ecoli_parse.h index a431ba2..9048808 100644 --- a/include/ecoli_parse.h +++ b/include/ecoli_parse.h @@ -159,7 +159,7 @@ struct ec_parse *ec_parse_get_last_child(const struct ec_parse *parse); * * */ -struct ec_parse *ec_parse_get_next(const struct ec_parse *parse); +struct ec_parse *ec_parse_next(const struct ec_parse *parse); /** * @@ -168,8 +168,8 @@ struct ec_parse *ec_parse_get_next(const struct ec_parse *parse); */ #define EC_PARSE_FOREACH_CHILD(child, parse) \ for (child = ec_parse_get_first_child(parse); \ - child != NULL; \ - child = ec_parse_get_next(child)) \ + child != NULL; \ + child = ec_parse_next(child)) \ /** * @@ -211,16 +211,36 @@ void ec_parse_dump(FILE *out, const struct ec_parse *parse); * * */ -struct ec_parse *ec_parse_find_first(struct ec_parse *parse, +struct ec_parse *ec_parse_find(struct ec_parse *parse, const char *id); +/** + * + * + * + */ +struct ec_parse *ec_parse_find_next(struct ec_parse *root, + struct ec_parse *start, + const char *id, bool iter_children); + /** * Iterate among parse tree * * Use it with: - * for (iter = state; iter != NULL; iter = ec_parse_iter_next(iter)) + * for (iter = state; iter != NULL; iter = EC_PARSE_ITER_NEXT(state, iter, 1)) */ -struct ec_parse *ec_parse_iter_next(struct ec_parse *parse); +struct ec_parse *__ec_parse_iter_next(const struct ec_parse *root, + struct ec_parse *parse, bool iter_children); + +/* keep the const if any */ +#define EC_PARSE_ITER_NEXT(root, parse, iter_children) ({ \ + const struct ec_parse *p_ = parse; /* check type */ \ + struct ec_parse *parse_ = (struct ec_parse *)parse; \ + typeof(parse) res_; \ + (void)p_; \ + res_ = __ec_parse_iter_next(root, parse_, iter_children); \ + res_; \ +}) /** * diff --git a/src/ecoli_node_dynamic.c b/src/ecoli_node_dynamic.c index 8a3edf3..7c73b65 100644 --- a/src/ecoli_node_dynamic.c +++ b/src/ecoli_node_dynamic.c @@ -135,13 +135,14 @@ static struct ec_node * build_counter(struct ec_parse *parse, void *opaque) { const struct ec_node *node; - struct ec_parse *iter; + struct ec_parse *root, *iter; unsigned int count = 0; char buf[32]; (void)opaque; - for (iter = ec_parse_get_root(parse); iter != NULL; - iter = ec_parse_iter_next(iter)) { + root = ec_parse_get_root(parse); + for (iter = root; iter != NULL; + iter = EC_PARSE_ITER_NEXT(root, iter, 1)) { node = ec_parse_get_node(iter); if (node->id && !strcmp(node->id, "my-id")) count++; diff --git a/src/ecoli_parse.c b/src/ecoli_parse.c index 3b27070..f224fda 100644 --- a/src/ecoli_parse.c +++ b/src/ecoli_parse.c @@ -319,7 +319,7 @@ ec_parse_get_last_child(const struct ec_parse *parse) return TAILQ_LAST(&parse->children, ec_parse_list); } -struct ec_parse *ec_parse_get_next(const struct ec_parse *parse) +struct ec_parse *ec_parse_next(const struct ec_parse *parse) { return TAILQ_NEXT(parse, next); } @@ -365,15 +365,18 @@ struct ec_parse *ec_parse_get_parent(const struct ec_parse *parse) return parse->parent; } -struct ec_parse *ec_parse_iter_next(struct ec_parse *parse) +struct ec_parse *__ec_parse_iter_next(const struct ec_parse *root, + struct ec_parse *parse, bool iter_children) { struct ec_parse *child, *parent, *next; - child = TAILQ_FIRST(&parse->children); - if (child != NULL) - return child; + if (iter_children) { + child = TAILQ_FIRST(&parse->children); + if (child != NULL) + return child; + } parent = parse->parent; - while (parent != NULL) { + while (parent != NULL && parse != root) { next = TAILQ_NEXT(parse, next); if (next != NULL) return next; @@ -383,15 +386,21 @@ struct ec_parse *ec_parse_iter_next(struct ec_parse *parse) return NULL; } -struct ec_parse *ec_parse_find_first(struct ec_parse *parse, - const char *id) +struct ec_parse * +ec_parse_find_next(struct ec_parse *root, struct ec_parse *start, + const char *id, bool iter_children) { struct ec_parse *iter; - if (parse == NULL) + if (root == NULL) return NULL; + if (start == NULL) + start = root; + else + start = EC_PARSE_ITER_NEXT(root, start, iter_children); - for (iter = parse; iter != NULL; iter = ec_parse_iter_next(iter)) { + for (iter = start; iter != NULL; + iter = EC_PARSE_ITER_NEXT(root, iter, 1)) { if (iter->node != NULL && iter->node->id != NULL && !strcmp(iter->node->id, id)) @@ -401,6 +410,12 @@ struct ec_parse *ec_parse_find_first(struct ec_parse *parse, return NULL; } +struct ec_parse *ec_parse_find(struct ec_parse *parse, + const char *id) +{ + return ec_parse_find_next(parse, NULL, id, 1); +} + struct ec_keyval * ec_parse_get_attrs(struct ec_parse *parse) { @@ -493,16 +508,16 @@ static int ec_parse_testcase(void) ec_parse_free(p2); p2 = NULL; - pc = ec_parse_find_first(p, "id_x"); + pc = ec_parse_find(p, "id_x"); testres |= EC_TEST_CHECK(pc != NULL, "cannot find id_x"); testres |= EC_TEST_CHECK(pc != NULL && ec_parse_get_parent(pc) != NULL && ec_parse_get_parent(ec_parse_get_parent(pc)) == p, "invalid parent\n"); - pc = ec_parse_find_first(p, "id_y"); + pc = ec_parse_find(p, "id_y"); testres |= EC_TEST_CHECK(pc != NULL, "cannot find id_y"); - pc = ec_parse_find_first(p, "id_dezdezdez"); + pc = ec_parse_find(p, "id_dezdezdez"); testres |= EC_TEST_CHECK(pc == NULL, "should not find bad id"); -- 2.20.1