tal: make tal_next() only return immediate children.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 7 Sep 2016 04:27:01 +0000 (13:57 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 7 Sep 2016 04:32:38 +0000 (14:02 +0930)
I tried to use it and got this wrong: moreover, I wanted to control
topology, which requires nested iteration, and skip children
of a node which I knew was changing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
13 files changed:
ccan/tal/path/test/run-basename.c
ccan/tal/path/test/run-canon.c
ccan/tal/path/test/run-dirname.c
ccan/tal/path/test/run-join.c
ccan/tal/path/test/run-readlink.c
ccan/tal/path/test/run-split.c
ccan/tal/str/test/helper.h
ccan/tal/tal.c
ccan/tal/tal.h
ccan/tal/test/run-expand.c
ccan/tal/test/run-iter.c
ccan/tal/test/run-overflow.c
ccan/tal/test/run.c

index c99353a48efab1df4ac66c2733913287ab6151f5..23188481f85008dfea23935fbd5ab1b9d636b0c6 100644 (file)
@@ -47,7 +47,7 @@ int main(void)
        path = path_basename(ctx, take(tal_strdup(ctx, "..")));
        ok1(streq(path, ".."));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && !tal_next(ctx, path));
+       ok1(tal_first(ctx) == path && !tal_next(path));
        tal_free(path);
        ok1(path_basename(ctx, take(NULL)) == NULL);
        ok1(!tal_first(ctx));
index e01567bf5ab106be99d1cb7842af37ea4d98c7cb..c6e3a8b04b67696a272d87d70a503f44b1b909d9 100644 (file)
@@ -36,7 +36,7 @@ int main(void)
        ok1(strstarts(path, cwd));
        ok1(path[strlen(cwd)] == PATH_SEP);
        ok1(strlen(path) == strlen(cwd) + 1 + strlen("run-canon-foo"));
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL);
        path2 = path_canon(ctx, "run-canon-link");
        ok1(streq(path2, path));
 
index 46589aefd80c9ba92b4abe3f6c24c897e708cbdd..a0bc2cbe397e114eaf9212aa4a435ce495129a6d 100644 (file)
@@ -47,7 +47,7 @@ int main(void)
        path = path_dirname(ctx, take(tal_strdup(ctx, "..")));
        ok1(streq(path, "."));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && !tal_next(ctx, path));
+       ok1(tal_first(ctx) == path && !tal_next(path));
        tal_free(path);
        ok1(path_dirname(ctx, take(NULL)) == NULL);
        ok1(!tal_first(ctx));
index a4f63b317f4a6881885100b433cb5f266a82dade..3961cbb132401bd6a68f5ae4d5c4df5fb3922e12 100644 (file)
@@ -32,39 +32,39 @@ int main(void)
        path = path_join(ctx, "foo", take(tal_strdup(ctx, "bar")));
        ok1(streq(path, "foo/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, "foo", take(tal_strdup(ctx, "/bar")));
        ok1(streq(path, "/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, take(tal_strdup(ctx, "foo")), "bar");
        ok1(streq(path, "foo/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, take(tal_strdup(ctx, "foo")), "/bar");
        ok1(streq(path, "/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, take(tal_strdup(ctx, "foo")),
                         take(tal_strdup(ctx, "bar")));
        ok1(streq(path, "foo/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, take(tal_strdup(ctx, "foo")),
                         take(tal_strdup(ctx, "/bar")));
        ok1(streq(path, "/bar"));
        ok1(tal_parent(path) == ctx);
-       ok1(tal_first(ctx) == path && tal_next(ctx, path) == NULL);
+       ok1(tal_first(ctx) == path && tal_next(path) == NULL && tal_first(path) == NULL);
        tal_free(path);
 
        path = path_join(ctx, take(NULL), "bar");
index 28dcf87e53d6469ae72e59168564586ff359c414..bab041708370dcc34763017aeb78fe17151cc61c 100644 (file)
@@ -30,7 +30,7 @@ int main(void)
        link = path_readlink(ctx, take(tal_strdup(ctx, "run-readlink-link")));
        ok1(tal_parent(link) == ctx);
        ok1(streq(link, "/tmp"));
-       ok1(tal_first(ctx) == link && tal_next(ctx, link) == NULL);
+       ok1(tal_first(ctx) == link && tal_next(link) == NULL && tal_first(link) == NULL);
 
        unlink("run-readlink-link");
 
index 732333c39e9283616b52a23b3650253f2fc8f847..1083cc88cbb488989ed1d83f0b9b05bdc7377b31 100644 (file)
@@ -98,7 +98,7 @@ int main(void)
        ok1(!split);
        ok1(tal_first(ctx) == NULL);
 
-       ok1(tal_first(NULL) == ctx && tal_next(NULL, ctx) == NULL);
+       ok1(tal_first(NULL) == ctx && tal_next(ctx) == NULL && tal_first(ctx) == NULL);
        tal_free(ctx);
 
        return exit_status();
index c1bc9ccf70ee0a7c101f8e5f6a97964e3c7a1b3f..5f0b68f5dca769ad33c03c6e2c6c6bde2ba2c3f5 100644 (file)
@@ -17,6 +17,6 @@ static inline bool no_children(const void *ctx)
 
 static inline bool single_child(const void *ctx, const void *child)
 {
-       return tal_first(ctx) == child && !tal_next(ctx, child);
+       return tal_first(ctx) == child && !tal_next(child) && !tal_first(child);
 }
 #endif
index 1eaa5749476aa3abd23992c16167b031c47175f6..8360b2520690c31a594da58a4cef8cb57889d87e 100644 (file)
@@ -630,31 +630,16 @@ tal_t *tal_first(const tal_t *root)
        return from_tal_hdr(c);
 }
 
-tal_t *tal_next(const tal_t *root, const tal_t *prev)
+tal_t *tal_next(const tal_t *prev)
 {
-        struct tal_hdr *c, *t = debug_tal(to_tal_hdr(prev)), *top;
+        struct tal_hdr *next, *prevhdr = debug_tal(to_tal_hdr(prev));
+       struct list_head *head;
 
-        /* Children? */
-       c = first_child(t);
-       if (c)
-               return from_tal_hdr(c);
-
-        top = to_tal_hdr_or_null(root);
-        do {
-               struct tal_hdr *next;
-               struct list_node *end;
-
-               end = &ignore_destroying_bit(t->parent_child)->children.n;
-
-               next = list_entry(t->list.next, struct tal_hdr, list);
-               if (&next->list != end)
-                       return from_tal_hdr(next);
-
-                /* OK, go back to parent. */
-                t = ignore_destroying_bit(t->parent_child)->parent;
-        } while (t != top);
-
-        return NULL;
+       head = &ignore_destroying_bit(prevhdr->parent_child)->children;
+       next = list_next(head, prevhdr, list);
+       if (!next)
+               return NULL;
+       return from_tal_hdr(next);
 }
 
 tal_t *tal_parent(const tal_t *ctx)
index f360a9611a8730838b6af1a9b23a2381b3bbc294..548b9274f700c0b9978b9126fd0c8261dbf2b5a3 100644 (file)
@@ -262,7 +262,7 @@ const char *tal_name(const tal_t *ptr);
 size_t tal_count(const tal_t *ptr);
 
 /**
- * tal_first - get the first tal object child.
+ * tal_first - get the first immediate tal object child.
  * @root: The tal allocated object to start with, or NULL.
  *
  * Returns NULL if there are no children.
@@ -270,15 +270,13 @@ size_t tal_count(const tal_t *ptr);
 tal_t *tal_first(const tal_t *root);
 
 /**
- * tal_next - get the next tal object child.
- * @root: The tal allocated object to start with, or NULL.
+ * tal_next - get the next immediate tal object child.
  * @prev: The return value from tal_first or tal_next.
  *
- * Returns NULL if there are no more children.  This should be safe to
- * call on an altering tree unless @prev is no longer a descendent of
- * @root.
+ * Returns NULL if there are no more immediate children.  This should be safe to
+ * call on an altering tree unless @prev is no longer valid.
  */
-tal_t *tal_next(const tal_t *root, const tal_t *prev);
+tal_t *tal_next(const const tal_t *prev);
 
 /**
  * tal_parent - get the parent of a tal object.
index 607947bea70fe477dfdae3fe9f35388a3f52045a..841735fb5fa61f38ca692fa37e2857c2f5eca375 100644 (file)
@@ -24,7 +24,7 @@ int main(void)
        ok1(a[1] == 1);
        ok1(a[2] == 2);
        ok1(a[3] == 0);
-       ok1(tal_first(NULL) == a && !tal_next(NULL, a));
+       ok1(tal_first(NULL) == a && !tal_next(a) && !tal_first(a));
 
        tal_free(a);
 
index 561e09cc2e697af14d25b7127388e35543c75106..5992172a51bad4736e55fdba83dd778a252eab4d 100644 (file)
@@ -4,9 +4,33 @@
 
 #define NUM 1000
 
+static int set_children(const tal_t *parent, char val)
+{
+       char *iter;
+       int num = 0;
+
+       for (iter = tal_first(parent); iter; iter = tal_next(iter)) {
+               ok1(*iter == '0');
+               *iter = val;
+               num++;
+               num += set_children(iter, val);
+       }
+       return num;
+}
+
+static void check_children(const tal_t *parent, char val)
+{
+       const char *iter;
+
+       for (iter = tal_first(parent); iter; iter = tal_next(iter)) {
+               ok1(*iter == val);
+               check_children(iter, val);
+       }
+}
+
 int main(void)
 {
-       char *p[NUM] = { NULL }, *iter;
+       char *p[NUM] = { NULL };
        int i;
 
        plan_tests(NUM + 1 + NUM);
@@ -17,18 +41,13 @@ int main(void)
                *p[i] = '0';
        }
 
-       i = 0;
-       for (iter = tal_first(NULL); iter; iter = tal_next(NULL, iter)) {
-               i++;
-               ok1(*iter == '0');
-               *iter = '1';
-       }
+       i = set_children(NULL, '1');
        ok1(i == NUM);
 
-       for (i = NUM-1; i >= 0; i--) {
-               ok1(*p[i] == '1');
+       check_children(NULL, '1');
+       for (i = NUM-1; i >= 0; i--)
                tal_free(p[i]);
-       }
+
        tal_cleanup();
        return exit_status();
 }
index e68c0471b9d7e4c49ee7568786be9dc726354586..d975398b4ba39b9e55ef35a57b18537aa514bbc8 100644 (file)
@@ -48,7 +48,7 @@ int main(void)
                     (size_t)-1UL / sizeof(int) / 2);
        ok1(!pi);
        ok1(error_count == 4);
-       ok1(tal_first(NULL) == origpi && !tal_next(NULL, origpi));
+       ok1(tal_first(NULL) == origpi && !tal_next(origpi) && !tal_first(origpi));
        tal_free(origpi);
 
        /* Now, check that with taltk() we free old one on failure. */
index 984865125deca6538ea531b714a077dce3a05b87..4931099e79049e3fa74ce316444f08a325633b3f 100644 (file)
@@ -25,7 +25,7 @@ int main(void)
 
        /* Iteration test. */
        i = 0;
-       for (p = tal_first(parent); p; p = tal_next(parent, p)) {
+       for (p = tal_first(parent); p; p = tal_next(p)) {
                *p = '1';
                i++;
        }