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
#define CCAN_LIST_H
#include <stdbool.h>
#include <assert.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)
}
/**
* 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.
*
* 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:
* list_del(&child->list);
* parent->num_children--;
......@@ -183,18 +205,33 @@ static inline void list_del(struct list_node *n)
}
/**
* list_empty - is a list empty?
* @h: the list_head
* list_del_from - delete an entry from a known linked list.
* @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:
* 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);
return h->n.next == &h->n;
#ifdef CCAN_LIST_DEBUG
{
/* 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[])
}
ok1(i == 3);
/* Test list_for_each_safe and list_del. */
/* Test list_for_each_safe, list_del and list_del_from. */
i = 0;
list_for_each_safe(&parent.children, c, n, list) {
switch (i++) {
case 0:
ok1(c == &c1);
ok1(c == &c1);
list_del(&c->list);
break;
case 1:
ok1(c == &c2);
list_del_from(&parent.children, &c->list);
break;
case 2:
ok1(c == &c3);
list_del_from(&parent.children, &c->list);
break;
}
list_del(&c->list);
ok1(list_check(&parent.children, NULL));
if (i > 2)
break;
......
......@@ -101,21 +101,23 @@ int main(int argc, char *argv[])
}
ok1(i == 3);
/* Test list_for_each_safe and list_del. */
/* Test list_for_each_safe, list_del and list_del_from. */
i = 0;
list_for_each_safe(&parent.children, c, n, list) {
switch (i++) {
case 0:
ok1(c == &c1);
ok1(c == &c1);
list_del(&c->list);
break;
case 1:
ok1(c == &c2);
list_del_from(&parent.children, &c->list);
break;
case 2:
ok1(c == &c3);
list_del_from(&parent.children, &c->list);
break;
}
list_del(&c->list);
ok1(list_check(&parent.children, NULL));
if (i > 2)
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