Browse Source

tal: make tal_next() only return immediate children.

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>
Rusty Russell 9 years ago
parent
commit
e81b527384

+ 1 - 1
ccan/tal/path/test/run-basename.c

@@ -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));

+ 1 - 1
ccan/tal/path/test/run-canon.c

@@ -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));
 

+ 1 - 1
ccan/tal/path/test/run-dirname.c

@@ -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));

+ 6 - 6
ccan/tal/path/test/run-join.c

@@ -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");

+ 1 - 1
ccan/tal/path/test/run-readlink.c

@@ -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");
 

+ 1 - 1
ccan/tal/path/test/run-split.c

@@ -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();

+ 1 - 1
ccan/tal/str/test/helper.h

@@ -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

+ 8 - 23
ccan/tal/tal.c

@@ -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)

+ 5 - 7
ccan/tal/tal.h

@@ -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.

+ 1 - 1
ccan/tal/test/run-expand.c

@@ -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);
 

+ 29 - 10
ccan/tal/test/run-iter.c

@@ -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();
 }

+ 1 - 1
ccan/tal/test/run-overflow.c

@@ -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. */

+ 1 - 1
ccan/tal/test/run.c

@@ -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++;
 	}