[augeas-devel] [PATCH 3/8] path expressions: allow passing a nodeset to function regexp
lutter at redhat.com
lutter at redhat.com
Sat May 7 01:12:51 UTC 2011
From: David Lutterkort <lutter at redhat.com>
---
src/pathx.c | 68 ++++++++++++++++++++++++++++++++++++++++++-----------
tests/xpath.tests | 7 +++++
2 files changed, 61 insertions(+), 14 deletions(-)
diff --git a/src/pathx.c b/src/pathx.c
index a73a83d..a2371f8 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -277,8 +277,8 @@ static void func_count(struct state *state);
static void func_label(struct state *state);
static void func_regexp(struct state *state);
-static const enum type const count_arg_types[] = { T_NODESET };
-static const enum type const regexp_arg_types[] = { T_STRING };
+static const enum type const arg_types_nodeset[] = { T_NODESET };
+static const enum type const arg_types_string[] = { T_STRING };
static const struct func builtin_funcs[] = {
{ .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL,
@@ -288,11 +288,14 @@ static const struct func builtin_funcs[] = {
{ .name = "label", .arity = 0, .type = T_STRING, .arg_types = NULL,
.impl = func_label },
{ .name = "count", .arity = 1, .type = T_NUMBER,
- .arg_types = count_arg_types,
+ .arg_types = arg_types_nodeset,
.impl = func_count },
{ .name = "regexp", .arity = 1, .type = T_REGEXP,
- .arg_types = regexp_arg_types,
- .impl =func_regexp }
+ .arg_types = arg_types_string,
+ .impl = func_regexp },
+ { .name = "regexp", .arity = 1, .type = T_REGEXP,
+ .arg_types = arg_types_nodeset,
+ .impl = func_regexp }
};
#define CHECK_ERROR \
@@ -629,28 +632,65 @@ static void func_label(struct state *state) {
push_value(vind, state);
}
+static struct regexp *
+nodeset_as_regexp(struct info *info, struct nodeset *ns) {
+ struct regexp *result = NULL;
+ struct regexp **rx = NULL;
+ int used = 0;
+
+ for (int i = 0; i < ns->used; i++) {
+ if (ns->nodes[i]->value != NULL)
+ used += 1;
+ }
+
+ if (used == 0) {
+ result = regexp_make_empty(info);
+ } else {
+ if (ALLOC_N(rx, ns->used) < 0)
+ goto error;
+ for (int i=0; i < ns->used; i++) {
+ if (ns->nodes[i]->value == NULL)
+ continue;
+
+ rx[i] = make_regexp_dup(info, ns->nodes[i]->value, 0);
+ if (rx[i] == NULL)
+ goto error;
+ }
+ result = regexp_union_n(info, ns->used, rx);
+ }
+
+ error:
+ if (rx != NULL) {
+ for (int i=0; i < ns->used; i++)
+ unref(rx[i], regexp);
+ free(rx);
+ }
+ return result;
+}
+
static void func_regexp(struct state *state) {
value_ind_t vind = make_value(T_REGEXP, state);
int r;
CHECK_ERROR;
- struct value *str = pop_value(state);
- assert(str->tag == T_STRING);
+ struct value *v = pop_value(state);
+ struct regexp *rx = NULL;
- char *pat = strdup(str->string);
- if (pat == NULL) {
- STATE_ENOMEM;
- return;
+ if (v->tag == T_STRING) {
+ rx = make_regexp_dup(state->error->info, v->string, 0);
+ } else if (v->tag == T_NODESET) {
+ rx = nodeset_as_regexp(state->error->info, v->nodeset);
+ } else {
+ assert(0);
}
- struct regexp *rx = make_regexp(NULL, pat, 0);
- state->value_pool[vind].regexp = rx;
if (rx == NULL) {
- FREE(pat);
STATE_ENOMEM;
return;
}
+
+ state->value_pool[vind].regexp = rx;
r = regexp_compile(rx);
if (r < 0) {
const char *msg;
diff --git a/tests/xpath.tests b/tests/xpath.tests
index cd1909c..6f5e090 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -226,6 +226,13 @@ test regexp1 /files/etc/sysconfig/network-scripts/*[label() =~ regexp('.*-eth0')
test regexp2 /files/etc/hosts/*[* =~ regexp('127\..*')]
/files/etc/hosts/1
+test regexp3 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*/ipaddr)]
+ /files/etc/hosts/1
+ /files/etc/hosts/2
+
+# Check that we don't crash when the nodeset contains all NULL's
+test regexp4 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*[ipaddr])]
+
# Union of nodesets
test union (/files/etc/yum.conf | /files/etc/yum.repos.d/*)/*/gpgcheck
/files/etc/yum.conf/main/gpgcheck = 1
--
1.7.4.4
More information about the augeas-devel
mailing list