From 22ffb884ca6a5f16517e49e051d8fb5a22e5049d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 1 Jan 2011 17:08:58 +1030 Subject: [PATCH] list: implement list_check_node to check list from node rather than head --- ccan/list/list.c | 34 +++++++++++++++++++++------------- ccan/list/list.h | 23 ++++++++++++++++++++++- ccan/list/test/run.c | 7 ++++++- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/ccan/list/list.c b/ccan/list/list.c index 3d581101..fad40cb8 100644 --- a/ccan/list/list.c +++ b/ccan/list/list.c @@ -2,32 +2,40 @@ #include #include "list.h" -struct list_head *list_check(const struct list_head *h, const char *abortstr) +struct list_node *list_check_node(const struct list_node *node, + const char *abortstr) { - const struct list_node *n, *p; + const struct list_node *p, *n; int count = 0; - if (h->n.next == &h->n) { - if (h->n.prev != &h->n) { + for (p = node, n = node->next; n != node; p = n, n = n->next) { + count++; + if (n->prev != p) { if (!abortstr) return NULL; - fprintf(stderr, "%s: prev corrupt in empty %p\n", - abortstr, h); + fprintf(stderr, + "%s: prev corrupt in node %p (%u) of %p\n", + abortstr, n, count, node); abort(); } - return (struct list_head *)h; } + return (struct list_node *)node; +} - for (p = &h->n, n = h->n.next; n != &h->n; p = n, n = n->next) { - count++; - if (n->prev != p) { +struct list_head *list_check(const struct list_head *h, const char *abortstr) +{ + if (h->n.next == &h->n) { + if (h->n.prev != &h->n) { if (!abortstr) return NULL; - fprintf(stderr, - "%s: prev corrupt in node %p (%u) of %p\n", - abortstr, n, count, h); + fprintf(stderr, "%s: prev corrupt in empty %p\n", + abortstr, h); abort(); } + return (struct list_head *)h; } + + if (!list_check_node(&h->n, abortstr)) + return NULL; return (struct list_head *)h; } diff --git a/ccan/list/list.h b/ccan/list/list.h index 3496294b..c4956a0d 100644 --- a/ccan/list/list.h +++ b/ccan/list/list.h @@ -39,7 +39,7 @@ struct list_head }; /** - * list_check - check a list for consistency + * list_check - check head of a list for consistency * @h: the list_head * @abortstr: the location to print on aborting, or NULL. * @@ -51,6 +51,8 @@ struct list_head * Returns the list head if the list is consistent, NULL if not (it * can never return NULL if @abortstr is set). * + * See also: list_check_node() + * * Example: * static void dump_parent(struct parent *p) * { @@ -64,6 +66,25 @@ struct list_head */ struct list_head *list_check(const struct list_head *h, const char *abortstr); +/** + * list_check_node - check node of a list for consistency + * @n: the list_node + * @abortstr: the location to print on aborting, or NULL. + * + * Check consistency of the list node is in (it must be in one). + * + * See also: list_check() + * + * Example: + * static void dump_child(const struct child *c) + * { + * list_check_node(&c->list, "bad child list"); + * printf("%s\n", c->name); + * } + */ +struct list_node *list_check_node(const struct list_node *n, + const char *abortstr); + #ifdef CCAN_LIST_DEBUG #define debug_list(h) list_check((h), __func__) #else diff --git a/ccan/list/test/run.c b/ccan/list/test/run.c index 1a5f0934..7c71e396 100644 --- a/ccan/list/test/run.c +++ b/ccan/list/test/run.c @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) struct child c1, c2, c3, *c, *n; unsigned int i; - plan_tests(44); + plan_tests(47); /* Test LIST_HEAD, list_empty and check_list */ ok1(list_empty(&static_list)); ok1(list_check(&static_list, NULL)); @@ -71,6 +71,11 @@ int main(int argc, char *argv[]) /* Test list_check */ ok1(list_check(&parent.children, NULL)); + /* Test list_check_node */ + ok1(list_check_node(&c1.list, NULL)); + ok1(list_check_node(&c2.list, NULL)); + ok1(list_check_node(&c3.list, NULL)); + /* Test list_top */ ok1(list_top(&parent.children, struct child, list) == &c1); -- 2.39.2