Commit dc0aafc9 authored by Rusty Russell's avatar Rusty Russell

list: list_del_from()

Deletion from a specific list.
parent a04a5f74
#ifndef CCAN_LIST_H #ifndef CCAN_LIST_H
#define CCAN_LIST_H #define CCAN_LIST_H
#include <stdbool.h> #include <stdbool.h>
#include <assert.h>
#include <ccan/container_of/container_of.h> #include <ccan/container_of/container_of.h>
/** /**
...@@ -164,9 +165,30 @@ static inline void list_add_tail(struct list_head *h, struct list_node *n) ...@@ -164,9 +165,30 @@ static inline void list_add_tail(struct list_head *h, struct list_node *n)
} }
/** /**
* list_del - delete an entry from a linked list. * list_empty - is a list empty?
* @h: the list_head
*
* If the list is empty, returns true.
*
* Example:
* assert(list_empty(&parent->children) == (parent->num_children == 0));
*/
static inline bool list_empty(const struct list_head *h)
{
(void)list_debug(h);
return h->n.next == &h->n;
}
/**
* list_del - delete an entry from an (unknown) linked list.
* @n: the list_node to delete from the list. * @n: the list_node to delete from the list.
* *
* Note that this leaves @n in an undefined state; it can be added to
* another list, but not deleted again.
*
* See also:
* list_del_from()
*
* Example: * Example:
* list_del(&child->list); * list_del(&child->list);
* parent->num_children--; * parent->num_children--;
...@@ -183,18 +205,33 @@ static inline void list_del(struct list_node *n) ...@@ -183,18 +205,33 @@ static inline void list_del(struct list_node *n)
} }
/** /**
* list_empty - is a list empty? * list_del_from - delete an entry from a known linked list.
* @h: the list_head * @h: the list_head the node is in.
* @n: the list_node to delete from the list.
* *
* If the list is empty, returns true. * This explicitly indicates which list a node is expected to be in,
* which is better documentation and can catch more bugs.
*
* See also: list_del()
* *
* Example: * Example:
* assert(list_empty(&parent->children) == (parent->num_children == 0)); * list_del_from(&parent->children, &child->list);
* parent->num_children--;
*/ */
static inline bool list_empty(const struct list_head *h) static inline void list_del_from(struct list_head *h, struct list_node *n)
{ {
(void)list_debug(h); #ifdef CCAN_LIST_DEBUG
return h->n.next == &h->n; {
/* Thorough check: make sure it was in list! */
struct list_node *i;
for (i = h->n.next; i != n; i = i->next)
assert(i != &h->n);
}
#endif /* CCAN_LIST_DEBUG */
/* Quick test that catches a surprising number of bugs. */
assert(!list_empty(h));
list_del(n);
} }
/** /**
......
...@@ -102,21 +102,23 @@ int main(int argc, char *argv[]) ...@@ -102,21 +102,23 @@ int main(int argc, char *argv[])
} }
ok1(i == 3); ok1(i == 3);
/* Test list_for_each_safe and list_del. */ /* Test list_for_each_safe, list_del and list_del_from. */
i = 0; i = 0;
list_for_each_safe(&parent.children, c, n, list) { list_for_each_safe(&parent.children, c, n, list) {
switch (i++) { switch (i++) {
case 0: case 0:
ok1(c == &c1); ok1(c == &c1);
list_del(&c->list);
break; break;
case 1: case 1:
ok1(c == &c2); ok1(c == &c2);
list_del_from(&parent.children, &c->list);
break; break;
case 2: case 2:
ok1(c == &c3); ok1(c == &c3);
list_del_from(&parent.children, &c->list);
break; break;
} }
list_del(&c->list);
ok1(list_check(&parent.children, NULL)); ok1(list_check(&parent.children, NULL));
if (i > 2) if (i > 2)
break; break;
......
...@@ -101,21 +101,23 @@ int main(int argc, char *argv[]) ...@@ -101,21 +101,23 @@ int main(int argc, char *argv[])
} }
ok1(i == 3); ok1(i == 3);
/* Test list_for_each_safe and list_del. */ /* Test list_for_each_safe, list_del and list_del_from. */
i = 0; i = 0;
list_for_each_safe(&parent.children, c, n, list) { list_for_each_safe(&parent.children, c, n, list) {
switch (i++) { switch (i++) {
case 0: case 0:
ok1(c == &c1); ok1(c == &c1);
list_del(&c->list);
break; break;
case 1: case 1:
ok1(c == &c2); ok1(c == &c2);
list_del_from(&parent.children, &c->list);
break; break;
case 2: case 2:
ok1(c == &c3); ok1(c == &c3);
list_del_from(&parent.children, &c->list);
break; break;
} }
list_del(&c->list);
ok1(list_check(&parent.children, NULL)); ok1(list_check(&parent.children, NULL));
if (i > 2) if (i > 2)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment