[augeas-devel] [PATCH] path expressions: add a function 'int'

lutter at redhat.com lutter at redhat.com
Wed Oct 5 16:56:14 UTC 2011


From: David Lutterkort <lutter at redhat.com>

This makes it possible to do numerical comparisons of node values, for
example, 'match /files/etc/group/*[int(gid) < 3]'
---
 src/pathx.c       |   43 ++++++++++++++++++++++++++++++++++++++++++-
 tests/xpath.tests |   13 +++++++++++++
 2 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/src/pathx.c b/src/pathx.c
index 1dd7992..6a9c377 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -279,9 +279,11 @@ static void func_count(struct state *state);
 static void func_label(struct state *state);
 static void func_regexp(struct state *state);
 static void func_glob(struct state *state);
+static void func_int(struct state *state);
 
 static const enum type const arg_types_nodeset[] = { T_NODESET };
 static const enum type const arg_types_string[] = { T_STRING };
+static const enum type const arg_types_bool[] = { T_BOOLEAN };
 
 static const struct func builtin_funcs[] = {
     { .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL,
@@ -304,7 +306,13 @@ static const struct func builtin_funcs[] = {
       .impl = func_glob },
     { .name = "glob", .arity = 1, .type = T_REGEXP,
       .arg_types = arg_types_nodeset,
-      .impl = func_glob }
+      .impl = func_glob },
+    { .name = "int", .arity = 1, .type = T_NUMBER,
+      .arg_types = arg_types_string, .impl = func_int },
+    { .name = "int", .arity = 1, .type = T_NUMBER,
+      .arg_types = arg_types_nodeset, .impl = func_int },
+    { .name = "int", .arity = 1, .type = T_NUMBER,
+      .arg_types = arg_types_bool, .impl = func_int }
 };
 
 #define RET_ON_ERROR                                                    \
@@ -642,6 +650,39 @@ static void func_label(struct state *state) {
     push_value(vind, state);
 }
 
+static void func_int(struct state *state) {
+    value_ind_t vind = make_value(T_NUMBER, state);
+    int64_t i = -1;
+    RET_ON_ERROR;
+
+    struct value *v = pop_value(state);
+    if (v->tag == T_BOOLEAN) {
+        i = v->boolval;
+    } else {
+        const char *s = NULL;
+        if (v->tag == T_STRING) {
+            s = v->string;
+        } else {
+            /* T_NODESET */
+            if (v->nodeset->used != 1) {
+                STATE_ERROR(state, PATHX_EMMATCH);
+                return;
+            }
+            s = v->nodeset->nodes[0]->value;
+        }
+        if (s != NULL) {
+            int r;
+            r = xstrtoint64(s, 10, &i);
+            if (r < 0) {
+                STATE_ERROR(state, PATHX_ENUMBER);
+                return;
+            }
+        }
+    }
+    state->value_pool[vind].number = i;
+    push_value(vind, state);
+}
+
 static struct regexp *
 nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) {
     struct regexp *result = NULL;
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 2a74e8f..e327062 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -287,3 +287,16 @@ test php5 $php/mail\ function
 test expr-or /files/etc/group/root/*[self::gid or self::user]
      /files/etc/group/root/gid = 0
      /files/etc/group/root/user = root
+
+test int-ns-eq /files/etc/group/*[int(gid) = 30]
+     /files/etc/group/gopher
+
+test int-ns-lt /files/etc/group/*[int(gid) < 3]
+    /files/etc/group/root
+    /files/etc/group/bin
+    /files/etc/group/daemon
+
+test int-bool-f /files[int(1 = 0) > 0]
+
+test int-bool-t /files[int(1 = 1) > 0]
+     /files
-- 
1.7.6.2




More information about the augeas-devel mailing list