aboutsummaryrefslogtreecommitdiff
path: root/src/lookup.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-09-27 14:33:15 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-09-27 14:58:55 +0300
commit784cb941000f13799545e1bb257c899c7da20064 (patch)
tree544512af54e18c0e0fdb8c7a0b011644f93e9539 /src/lookup.c
parent1e658c33ad766e23dffff9125aacef8baebdc30a (diff)
downloadgrecs-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.c40
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;

Return to:

Send suggestions and report system problems to the System administrator.