]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
list: add LIST_CLEAR() helper that empties the list
authorDavid Tardon <dtardon@redhat.com>
Wed, 9 Aug 2023 14:35:08 +0000 (16:35 +0200)
committerDavid Tardon <dtardon@redhat.com>
Thu, 17 Aug 2023 07:48:17 +0000 (09:48 +0200)
src/basic/list.h
src/test/test-list.c

index e4e5dff3ea2678568efdbf692e4ca1a32f457a22..497d116387f048091683e3116101500727b40d48 100644 (file)
                 _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"
index 307c1bf9361197529f768b8fc7ebca1925030303..4b20a9f956d677e1a0455276ce2421877bb921df 100644 (file)
@@ -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;
 }