Commit e4046df7 authored by Eric Wong's avatar Eric Wong Committed by Rusty Russell

list: list_add_after and list_add_before functions

These make it easy to add a new element before or after an
existing element in the middle of the list.

The existing list_add and list_add_tail functions are trivially
reimplemented on top of these new functions.
Signed-off-by: default avatarEric Wong <normalperson@yhbt.net>
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent c1bace5e
......@@ -157,6 +157,36 @@ static inline void list_node_init(struct list_node *n)
n->next = n->prev = n;
}
/**
* list_add_after - add an entry after an existing node in a linked list
* @h: the list_head to add the node to (for debugging)
* @p: the existing list_node to add the node after
* @n: the new list_node to add to the list.
*
* The existing list_node must already be a member of the list.
* The new list_node does not need to be initialized; it will be overwritten.
*
* Example:
* struct child c1, c2, c3;
* LIST_HEAD(h);
*
* list_add_tail(&h, &c1.list);
* list_add_tail(&h, &c3.list);
* list_add_after(&h, &c1.list, &c2.list);
*/
#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC)
static inline void list_add_after_(struct list_head *h,
struct list_node *p,
struct list_node *n,
const char *abortstr)
{
n->next = p->next;
n->prev = p;
p->next->prev = n;
p->next = n;
(void)list_debug(h, abortstr);
}
/**
* list_add - add an entry at the start of a linked list.
* @h: the list_head to add the node to
......@@ -175,10 +205,34 @@ static inline void list_add_(struct list_head *h,
struct list_node *n,
const char *abortstr)
{
n->next = h->n.next;
n->prev = &h->n;
h->n.next->prev = n;
h->n.next = n;
list_add_after_(h, &h->n, n, abortstr);
}
/**
* list_add_before - add an entry before an existing node in a linked list
* @h: the list_head to add the node to (for debugging)
* @p: the existing list_node to add the node before
* @n: the new list_node to add to the list.
*
* The existing list_node must already be a member of the list.
* The new list_node does not need to be initialized; it will be overwritten.
*
* Example:
* list_head_init(&h);
* list_add_tail(&h, &c1.list);
* list_add_tail(&h, &c3.list);
* list_add_before(&h, &c3.list, &c2.list);
*/
#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC)
static inline void list_add_before_(struct list_head *h,
struct list_node *p,
struct list_node *n,
const char *abortstr)
{
n->next = p;
n->prev = p->prev;
p->prev->next = n;
p->prev = n;
(void)list_debug(h, abortstr);
}
......@@ -197,11 +251,7 @@ static inline void list_add_tail_(struct list_head *h,
struct list_node *n,
const char *abortstr)
{
n->next = &h->n;
n->prev = h->n.prev;
h->n.prev->next = n;
h->n.prev = n;
(void)list_debug(h, abortstr);
list_add_before_(h, &h->n, n, abortstr);
}
/**
......
......@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
opaque_t *q, *nq;
struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
plan_tests(70);
plan_tests(79);
/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
ok1(list_empty(&static_list));
ok1(list_check(&static_list, NULL));
......@@ -215,5 +215,43 @@ int main(int argc, char *argv[])
ok1(list_top(&parent.children, struct child, list) == NULL);
ok1(list_tail(&parent.children, struct child, list) == NULL);
ok1(list_pop(&parent.children, struct child, list) == NULL);
/* Test list_add_before and list_add_after */
list_add(&parent.children, &c1.list);
list_add_after(&parent.children, &c1.list, &c2.list);
ok1(list_check(&parent.children, "list_add_after"));
i = 0;
list_for_each(&parent.children, c, list) {
switch (i++) {
case 0:
ok1(c == &c1);
break;
case 1:
ok1(c == &c2);
break;
}
}
ok1(i == 2);
list_add_before(&parent.children, &c2.list, &c3.list);
ok1(list_check(&parent.children, "list_add_before"));
i = 0;
list_for_each(&parent.children, c, list) {
switch (i++) {
case 0:
ok1(c == &c1);
break;
case 1:
ok1(c == &c3);
break;
case 2:
ok1(c == &c2);
break;
}
}
ok1(i == 3);
return exit_status();
}
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