util: add the macros to run through a list backwards

This ended up being unused but I wrote the code so we might as well
include it.
This commit is contained in:
Peter Hutterer 2022-05-17 13:55:46 +10:00
parent d99e42b808
commit 0d5ce5dd87
2 changed files with 84 additions and 0 deletions

View file

@ -190,4 +190,67 @@ MUNIT_TEST(test_list_nth)
return MUNIT_OK;
}
MUNIT_TEST(list_first_last)
{
struct list_test {
int val;
struct list node;
} tests[] = {
{ .val = 1 },
{ .val = 2 },
{ .val = 3 },
{ .val = 4 },
};
struct list_test *t;
struct list head;
list_init(&head);
ARRAY_FOR_EACH(tests, t) {
list_append(&head, &t->node);
}
struct list_test *first = list_first_entry(&head, t, node);
munit_assert_int(first->val, ==, 1);
first = list_first_entry_by_type(&head, struct list_test, node);
munit_assert_int(first->val, ==, 1);
struct list_test *last = list_last_entry(&head, t, node);
munit_assert_int(last->val, ==, 4);
last = list_last_entry_by_type(&head, struct list_test, node);
munit_assert_int(last->val, ==, 4);
return MUNIT_OK;
}
MUNIT_TEST(list_foreach)
{
struct list_test {
int val;
struct list node;
} tests[] = {
{ .val = 1 },
{ .val = 2 },
{ .val = 3 },
{ .val = 4 },
};
struct list_test *t;
struct list head;
list_init(&head);
ARRAY_FOR_EACH(tests, t) {
list_append(&head, &t->node);
}
unsigned int idx = 0;
list_for_each(t, &head, node) {
munit_assert_int(t->val, ==, tests[idx++].val);
}
list_for_each_backwards(t, &head, node) {
munit_assert_int(t->val, ==, tests[--idx].val);
}
return MUNIT_OK;
}
#endif

View file

@ -88,6 +88,7 @@ void list_append(struct list *list, struct list *elm);
*
*/
void list_remove(struct list *elm);
/**
* Returns true if the given list head is an empty list.
*/
@ -139,6 +140,12 @@ bool list_empty(const struct list *list);
#define list_first_entry(head, pointer_of_type, member) \
container_of((head)->next, __typeof__(*pointer_of_type), member)
/**
* Return the last entry of the list. See list_first_entry() for details.
*/
#define list_last_entry(head, pointer_of_type, member) \
container_of((head)->prev, __typeof__(*pointer_of_type), member)
/**
* Given a list 'head', return the first entry of type 'container_type' that
* has a member 'link'.
@ -159,6 +166,12 @@ bool list_empty(const struct list *list);
#define list_first_entry_by_type(head, container_type, member) \
container_of((head)->next, container_type, member)
/**
* Return the last entry of the list. See list_first_entry_by_type() for details.
*/
#define list_last_entry_by_type(head, container_type, member) \
container_of((head)->prev, container_type, member)
/**
* Iterate through the list.
*
@ -177,6 +190,14 @@ bool list_empty(const struct list *list);
&pos->member != (head); \
pos = list_first_entry_by_type(&pos->member, __typeof__(*pos), member))
/**
* Iterate through the list backwards.
*/
#define list_for_each_backwards(pos, head, member) \
for (pos = list_last_entry_by_type(head, __typeof__(*pos), member); \
&pos->member != (head); \
pos = list_last_entry_by_type(&pos->member, __typeof__(*pos), member))
/**
* Iterate through the list. Equivalent to list_for_each() but allows
* calling list_remove() on the element.