From: David Tardon Date: Wed, 9 Aug 2023 14:35:08 +0000 (+0200) Subject: list: add LIST_CLEAR() helper that empties the list X-Git-Tag: v255-rc1~698^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d327b7752f124050bf90cbd0b99cf3a0fc90eedc;p=thirdparty%2Fsystemd.git list: add LIST_CLEAR() helper that empties the list --- diff --git a/src/basic/list.h b/src/basic/list.h index e4e5dff3ea2..497d116387f 100644 --- a/src/basic/list.h +++ b/src/basic/list.h @@ -192,6 +192,18 @@ _p; \ }) +#define LIST_CLEAR(name, head, free_func) \ + _LIST_CLEAR(name, head, free_func, UNIQ_T(elem, UNIQ)) + +/* Clear the list, destroing each element with free_func */ +#define _LIST_CLEAR(name, head, free_func, elem) \ + ({ \ + typeof(head) elem; \ + while ((elem = LIST_POP(name, head))) \ + free_func(elem); \ + head; \ + }) + /* Now include "macro.h", because we want our definition of assert() which the macros above use. We include * it down here instead of up top, since macro.h pulls in log.h which in turn needs our own definitions. */ #include "macro.h" diff --git a/src/test/test-list.c b/src/test/test-list.c index 307c1bf9361..4b20a9f956d 100644 --- a/src/test/test-list.c +++ b/src/test/test-list.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "alloc-util.h" #include "list.h" int main(int argc, const char *argv[]) { @@ -254,5 +255,29 @@ int main(int argc, const char *argv[]) { assert_se(LIST_POP(item_list, head) == items + 0); assert_se(LIST_POP(item_list, head) == NULL); + /* No-op on an empty list */ + + LIST_CLEAR(item_list, head, free); + + /* A non-empty list is cleared */ + + assert_se(LIST_PREPEND(item_list, head, new0(list_item, 1))); + assert_se(LIST_PREPEND(item_list, head, new0(list_item, 1))); + + LIST_CLEAR(item_list, head, free); + + assert_se(head == NULL); + + /* A list can be cleared partially */ + + assert_se(LIST_PREPEND(item_list, head, new0(list_item, 1))); + assert_se(LIST_PREPEND(item_list, head, new0(list_item, 1))); + assert_se(LIST_PREPEND(item_list, head, items + 0) == items + 0); + + LIST_CLEAR(item_list, head->item_list_next, free); + + assert_se(head == items + 0); + assert_se(head->item_list_next == NULL); + return 0; }