[augeas-devel] [PATCH] Flatten the tree of lenses

David Lutterkort dlutter at redhat.com
Thu Jul 24 17:19:11 UTC 2008


3 files changed, 109 insertions(+), 13 deletions(-)
src/lens.c   |   74 +++++++++++++++++++++++++++++++++++++++++++++++-----------
src/regexp.c |   42 ++++++++++++++++++++++++++++++++
src/syntax.h |    6 ++++


# HG changeset patch
# User David Lutterkort <dlutter at redhat.com>
# Date 1216919484 25200
# Node ID 27f24cafe6ec2a075a75ef5e89d06831c4554924
# Parent  57f0a0894bf42dcaa1f5b90b5378cbd614ad07d9
Flatten the tree of lenses

For union and concat, we used to store multiple unions/concats in a binary
tree. Now, the tree is flattened and a string of concats is stored as one
lens.

diff -r 57f0a0894bf4 -r 27f24cafe6ec src/lens.c
--- a/src/lens.c	Thu Jul 24 10:08:26 2008 -0700
+++ b/src/lens.c	Thu Jul 24 10:11:24 2008 -0700
@@ -59,16 +59,68 @@
     return lens;
 }
 
+typedef struct regexp *regexp_combinator(struct info *, int, struct regexp **);
+
 static struct lens *make_lens_binop(enum lens_tag tag, struct info *info,
-                                    struct lens *l1, struct lens *l2) {
+                                    struct lens *l1, struct lens *l2,
+                                    regexp_combinator *combinator) {
     struct lens *lens = make_lens(tag, info);
-    CALLOC(lens->children, 2);
-    lens->nchildren = 2;
-    lens->children[0] = l1;
-    lens->children[1] = l2;
-    lens->value = l1->value || l2->value;
-    lens->key = l1->key || l2->key;
+    int n1 = (l1->tag == tag) ? l1->nchildren : 1;
+    struct regexp **types = NULL;
+
+    if (lens == NULL)
+        goto error;
+
+    lens->nchildren = n1;
+    lens->nchildren += (l2->tag == tag) ? l2->nchildren : 1;
+
+    if (ALLOC_N(lens->children, lens->nchildren) < 0) {
+        lens->nchildren = 0;
+        goto error;
+    }
+
+    if (l1->tag == tag) {
+        for (int i=0; i < l1->nchildren; i++)
+            lens->children[i] = ref(l1->children[i]);
+        unref(l1, lens);
+    } else {
+        lens->children[0] = l1;
+    }
+
+    if (l2->tag == tag) {
+        for (int i=0; i < l2->nchildren; i++)
+            lens->children[n1 + i] = ref(l2->children[i]);
+        unref(l2, lens);
+    } else {
+        lens->children[n1] = l2;
+    }
+
+    for (int i=0; i < lens->nchildren; i++) {
+        lens->value = lens->value || lens->children[i]->value;
+        lens->key = lens->key || lens->children[i]->key;
+    }
+
+    if (ALLOC_N(types, lens->nchildren) < 0)
+        goto error;
+
+    for (int i=0; i < lens->nchildren; i++)
+        types[i] = lens->children[i]->ctype;
+    lens->ctype = (*combinator)(info, lens->nchildren, types);
+
+    for (int i=0; i < lens->nchildren; i++)
+        types[i] = lens->children[i]->atype;
+    lens->atype = (*combinator)(info, lens->nchildren, types);
+
+    FREE(types);
+
+    for (int i=0; i < lens->nchildren; i++)
+        assert(tag != lens->children[i]->tag);
+
     return lens;
+ error:
+    unref(lens, lens);
+    FREE(types);
+    return NULL;
 }
 
 static struct value *make_lens_value(struct lens *lens) {
@@ -88,9 +140,7 @@
             return exn;
     }
 
-    lens = make_lens_binop(L_UNION, info, l1, l2);
-    lens->ctype = regexp_union(info, l1->ctype, l2->ctype);
-    lens->atype = regexp_union(info, l1->atype, l2->atype);
+    lens = make_lens_binop(L_UNION, info, l1, l2, regexp_union_n);
     return make_lens_value(lens);
 }
 
@@ -111,9 +161,7 @@
         return make_exn_value(info, "Multiple keys/labels in concat");
     }
 
-    lens = make_lens_binop(L_CONCAT, info, l1, l2);
-    lens->ctype = regexp_concat(info, l1->ctype, l2->ctype);
-    lens->atype = regexp_concat(info, l1->atype, l2->atype);
+    lens = make_lens_binop(L_CONCAT, info, l1, l2, regexp_concat_n);
     return make_lens_value(lens);
 }
 
diff -r 57f0a0894bf4 -r 27f24cafe6ec src/regexp.c
--- a/src/regexp.c	Thu Jul 24 10:08:26 2008 -0700
+++ b/src/regexp.c	Thu Jul 24 10:11:24 2008 -0700
@@ -102,6 +102,28 @@
 }
 
 struct regexp *
+regexp_union_n(struct info *info, int n, struct regexp **r) {
+    size_t len = 0;
+    char *pat, *p;
+
+    for (int i=0; i < n; i++)
+        len += strlen(r[i]->pattern->str) + 2;
+
+    if (ALLOC_N(pat, len + (n-1) + 1) < 0)
+        return NULL;
+
+    p = pat;
+    for (int i=0; i < n; i++) {
+        if (i > 0)
+            *p++ = '|';
+        *p++ = '(';
+        p = stpcpy(p, r[i]->pattern->str);
+        *p++ = ')';
+    }
+    return make_regexp(info, pat);
+}
+
+struct regexp *
 regexp_concat(struct info *info, struct regexp *r1, struct regexp *r2) {
     const char *p1 = r1->pattern->str;
     const char *p2 = r2->pattern->str;
@@ -110,6 +132,26 @@
     if (asprintf(&s, "(%s)(%s)", p1, p2) == -1)
         return NULL;
     return make_regexp(info, s);
+}
+
+struct regexp *
+regexp_concat_n(struct info *info, int n, struct regexp **r) {
+    size_t len = 0;
+    char *pat, *p;
+
+    for (int i=0; i < n; i++)
+        len += strlen(r[i]->pattern->str) + 2;
+
+    if (ALLOC_N(pat, len+1) < 0)
+        return NULL;
+
+    p = pat;
+    for (int i=0; i < n; i++) {
+        *p++ = '(';
+        p = stpcpy(p, r[i]->pattern->str);
+        *p++ = ')';
+    }
+    return make_regexp(info, pat);
 }
 
 struct regexp *
diff -r 57f0a0894bf4 -r 27f24cafe6ec src/syntax.h
--- a/src/syntax.h	Thu Jul 24 10:08:26 2008 -0700
+++ b/src/syntax.h	Thu Jul 24 10:11:24 2008 -0700
@@ -178,6 +178,12 @@
 
 struct regexp *
 regexp_concat(struct info *, struct regexp *r1, struct regexp *r2);
+
+struct regexp *
+regexp_union_n(struct info *, int n, struct regexp **r);
+
+struct regexp *
+regexp_concat_n(struct info *, int n, struct regexp **r);
 
 struct regexp *
 regexp_iter(struct info *info, struct regexp *r, int min, int max);




More information about the augeas-devel mailing list