diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-27 14:33:15 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-27 14:58:55 +0300 |
commit | 784cb941000f13799545e1bb257c899c7da20064 (patch) | |
tree | 544512af54e18c0e0fdb8c7a0b011644f93e9539 /src/lookup.c | |
parent | 1e658c33ad766e23dffff9125aacef8baebdc30a (diff) | |
download | grecs-784cb941000f13799545e1bb257c899c7da20064.tar.gz grecs-784cb941000f13799545e1bb257c899c7da20064.tar.bz2 |
Fix matches in subtrees.
This commit makes it possible to run wildcard matches in
subtrees, e.g. like this:
grecs_match_first(grecs_find_node(tree, root_path), path, &match_buf);
Another effect is that it is possible to use grecs_match_next after
a successful recursion using the grecs_node_exact_match. In other words,
grecs_match_next works well for both exact and wildcard matches, whatever
was the originating node in the tree. (This is used in eclat.)
* src/grecs.h (grecs_match_buf_get_root): New proto.
(grecs_match_buf_set_root): New proto.
* src/lookup.c (grecs_match_buf) <root>: New member.
(grecs_match_buf_get_root)
(grecs_match_buf_set_root): New functions.
(grecs_match): Use root member of struct grecs_match_buf
to determine whether we hit root.
(grecs_match_buf_first): Initialize root.
* src/tree.c (grecs_tree_first_node): Allow for non-root
node as argument (no-op in this case).
* tests/glob04.at: new testcase.
* tests/glob05.at: new testcase.
* tests/Makefile.am: Add new files.
* tests/testsuite.at: Include new files.
* tests/gcfpeek.c: New option "-root", for testing
matches in subtrees.
Diffstat (limited to 'src/lookup.c')
-rw-r--r-- | src/lookup.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/lookup.c b/src/lookup.c index 68fd5cf..1758104 100644 --- a/src/lookup.c +++ b/src/lookup.c @@ -150,11 +150,12 @@ grecs_value_match(struct grecs_value *pat, struct grecs_value *b, int flags) struct grecs_match_buf { - int argc; - char **argv; - int argi; - struct grecs_value **labelv; - struct grecs_node *node; + int argc; /* number of path components */ + char **argv; /* array of path components */ + int argi; /* Index of the current component */ + struct grecs_value **labelv; /* Component labels */ + struct grecs_node *root; /* Root node */ + struct grecs_node *node; /* Last found node */ }; #define ISWC(c,w) ((c)[0] == (w) && (c)[1] == 0) @@ -209,6 +210,18 @@ grecs_match_buf_get_node(grecs_match_buf_t buf) return buf->node; } +struct grecs_node * +grecs_match_buf_get_root(grecs_match_buf_t buf) +{ + return buf->root; +} + +void +grecs_match_buf_set_root(grecs_match_buf_t buf, struct grecs_node *root) +{ + buf->root = root; +} + static void grecs_match_buf_free_contents(struct grecs_match_buf *buf) { @@ -488,6 +501,12 @@ grecs_node_from_path(const char *path, const char *value) static int +is_root(struct grecs_match_buf *buf, struct grecs_node *node) +{ + return (buf->root == node || node->type == grecs_node_root); +} + +static int grecs_match(struct grecs_match_buf *buf) { struct grecs_node *node; @@ -513,13 +532,12 @@ grecs_match(struct grecs_match_buf *buf) wcard = 0; node = node->up; if (buf->argi-- == 0) - return !node || - node->type == grecs_node_root; + return is_root(buf, node); } else if (!wcard) return 0; else node = node->up; - if (!node || node->type == grecs_node_root) + if (is_root(buf, node)) return ISWC(buf->argv[buf->argi], '*'); } return 0; @@ -543,6 +561,7 @@ grecs_match_buf_first(struct grecs_match_buf *buf, struct grecs_node *tree) struct grecs_node *node; buf->argi = 0; + buf->root = tree; buf->node = grecs_tree_first_node(tree); if (grecs_match(buf)) node = buf->node; @@ -558,11 +577,6 @@ grecs_match_first(struct grecs_node *tree, const char *pattern, struct grecs_node *node; struct grecs_match_buf *buf; - if (tree->type != grecs_node_root) { - errno = EINVAL; - return NULL; - } - errno = 0; if (strcmp(pattern, ".") == 0) { *pbuf = NULL; return tree; |