]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[list] Add list_for_each_entry_safe_continue()
authorMichael Brown <mcb30@ipxe.org>
Tue, 13 Feb 2024 16:26:34 +0000 (16:26 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 14 Feb 2024 16:40:05 +0000 (16:40 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/list.h
src/tests/list_test.c

index 53edfc9f74bca711b3f9cbe73789438361d453ab..2f02e71f0a876d70641868eeb833c236a6afae13 100644 (file)
@@ -489,6 +489,22 @@ extern void extern_list_splice_tail_init ( struct list_head *list,
              &pos->member != (head);                                         \
              pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
 
+/**
+ * Iterate over subsequent entries in a list, safe against deletion
+ *
+ * @v pos              Iterator
+ * @v tmp              Temporary value (of same type as iterator)
+ * @v head             List head
+ * @v member           Name of list field within iterator's type
+ */
+#define list_for_each_entry_safe_continue( pos, tmp, head, member )          \
+       for ( list_check ( (head) ),                                          \
+             pos = list_entry ( pos->member.next, typeof ( *pos ), member ), \
+             tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \
+             &pos->member != (head);                                         \
+             pos = tmp,                                                      \
+             tmp = list_entry ( tmp->member.next, typeof ( *tmp ), member ) )
+
 /**
  * Test if list contains a specified entry
  *
index f18c63f2de90abe9d5882fb76172629a413c87ed..c24e808283cd22338588a43d796fa97a0d8b3273 100644 (file)
@@ -518,6 +518,38 @@ static void list_test_exec ( void ) {
        list_iterate_entry_ok ( list_for_each_entry_continue_reverse, "",
                                pos, list, list );
 
+       /* Test list_for_each_entry_safe_continue() */
+       INIT_LIST_HEAD ( list );
+       list_add_tail ( &list_tests[9].list, list );
+       list_add_tail ( &list_tests[4].list, list );
+       list_add_tail ( &list_tests[2].list, list );
+       list_add_tail ( &list_tests[5].list, list );
+       list_add_tail ( &list_tests[7].list, list );
+       {
+               char *expecteds[] = { "94257", "9457", "947", "94" };
+               char **expected = expecteds;
+               pos = &list_tests[4];
+               list_for_each_entry_safe_continue ( pos, tmp, list, list ) {
+                       list_contents_ok ( list, *expected );
+                       list_del ( &pos->list );
+                       expected++;
+                       list_contents_ok ( list, *expected );
+               }
+       }
+       list_contents_ok ( list, "94" );
+       {
+               char *expecteds[] = { "94", "4", "" };
+               char **expected = expecteds;
+               ok ( pos == list_entry ( list, struct list_test, list ) );
+               list_for_each_entry_safe_continue ( pos, tmp, list, list ) {
+                       list_contents_ok ( list, *expected );
+                       list_del ( &pos->list );
+                       expected++;
+                       list_contents_ok ( list, *expected );
+               }
+       }
+       ok ( list_empty ( list ) );
+
        /* Test list_contains() and list_contains_entry() */
        INIT_LIST_HEAD ( list );
        INIT_LIST_HEAD ( &list_tests[3].list );