basic/list: add LIST_JOIN helper

Joins together two lists, tail to head.

a -> b
c -> d

a -> b -> c -> d
This commit is contained in:
Luca Boccassi 2020-07-17 18:26:51 +01:00
parent 6b222c4b02
commit 5511d8c1b9
2 changed files with 62 additions and 0 deletions

View File

@ -169,3 +169,18 @@
#define LIST_IS_EMPTY(head) \
(!(head))
/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
#define LIST_JOIN(name,a,b) \
do { \
assert(b); \
if (!(a)) \
(a) = (b); \
else { \
typeof(*(a)) *_head = (b), *_tail; \
LIST_FIND_TAIL(name, (a), _tail); \
_tail->name##_next = _head; \
_head->name##_prev = _tail; \
} \
(b) = NULL; \
} while (false)

View File

@ -12,11 +12,14 @@ int main(int argc, const char *argv[]) {
LIST_FIELDS(struct list_item, item);
} list_item;
LIST_HEAD(list_item, head);
LIST_HEAD(list_item, head2);
list_item items[4];
list_item *cursor;
LIST_HEAD_INIT(head);
LIST_HEAD_INIT(head2);
assert_se(head == NULL);
assert_se(head2 == NULL);
for (i = 0; i < ELEMENTSOF(items); i++) {
LIST_INIT(item, &items[i]);
@ -203,5 +206,49 @@ int main(int argc, const char *argv[]) {
assert_se(head == NULL);
for (i = 0; i < ELEMENTSOF(items) / 2; i++) {
LIST_INIT(item, &items[i]);
assert_se(LIST_JUST_US(item, &items[i]));
LIST_PREPEND(item, head, &items[i]);
}
for (i = ELEMENTSOF(items) / 2; i < ELEMENTSOF(items); i++) {
LIST_INIT(item, &items[i]);
assert_se(LIST_JUST_US(item, &items[i]));
LIST_PREPEND(item, head2, &items[i]);
}
assert_se(items[0].item_next == NULL);
assert_se(items[1].item_next == &items[0]);
assert_se(items[2].item_next == NULL);
assert_se(items[3].item_next == &items[2]);
assert_se(items[0].item_prev == &items[1]);
assert_se(items[1].item_prev == NULL);
assert_se(items[2].item_prev == &items[3]);
assert_se(items[3].item_prev == NULL);
LIST_JOIN(item, head2, head);
assert_se(head == NULL);
assert_se(items[0].item_next == NULL);
assert_se(items[1].item_next == &items[0]);
assert_se(items[2].item_next == &items[1]);
assert_se(items[3].item_next == &items[2]);
assert_se(items[0].item_prev == &items[1]);
assert_se(items[1].item_prev == &items[2]);
assert_se(items[2].item_prev == &items[3]);
assert_se(items[3].item_prev == NULL);
LIST_JOIN(item, head, head2);
assert_se(head2 == NULL);
assert_se(!LIST_IS_EMPTY(head));
for (i = 0; i < ELEMENTSOF(items); i++)
LIST_REMOVE(item, head, &items[i]);
assert_se(head == NULL);
return 0;
}