]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[list] Add list_next_entry() and list_prev_entry()
authorMichael Brown <mcb30@ipxe.org>
Wed, 31 Aug 2016 14:05:22 +0000 (15:05 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 31 Aug 2016 14:06:36 +0000 (15:06 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/list.h
src/tests/list_test.c

index 6a9b76f91ad69eb1923bbd93f3a147a021865f7a..274fb64c6f02cc2d6bd75156cf3561fad3f8169a 100644 (file)
@@ -348,6 +348,34 @@ extern void extern_list_splice_tail_init ( struct list_head *list,
          ( type * ) NULL :                                     \
          list_entry ( (list)->prev, type, member ) )
 
+/**
+ * Get the container of the next entry in a list
+ *
+ * @v pos              Current list entry
+ * @v head             List head
+ * @v member           Name of list field within iterator's type
+ * @ret next           Next list entry, or NULL at end of list
+ */
+#define list_next_entry( pos, head, member ) ( {               \
+       typeof (pos) next = list_entry ( (pos)->member.next,    \
+                                        typeof ( *(pos) ),     \
+                                        member );              \
+       ( ( &next->member == (head) ) ? NULL : next ); } )
+
+/**
+ * Get the container of the previous entry in a list
+ *
+ * @v pos              Current list entry
+ * @v head             List head
+ * @v member           Name of list field within iterator's type
+ * @ret next           Next list entry, or NULL at end of list
+ */
+#define list_prev_entry( pos, head, member ) ( {               \
+       typeof (pos) prev = list_entry ( (pos)->member.prev,    \
+                                        typeof ( *(pos) ),     \
+                                        member );              \
+       ( ( &prev->member == (head) ) ? NULL : prev ); } )
+
 /**
  * Iterate over a list
  *
index 352c87da07e2253870fe7f21fbae2a9067354bcb..f016a32ebf59a501a19ba802291bfad702d21b18 100644 (file)
@@ -396,6 +396,29 @@ static void list_test_exec ( void ) {
        ok ( list_first_entry ( list, struct list_test, list ) == NULL );
        ok ( list_last_entry ( list, struct list_test, list ) == NULL );
 
+       /* Test list_next_entry() and list_prev_entry() */
+       INIT_LIST_HEAD ( list );
+       list_add_tail ( &list_tests[5].list, list );
+       list_add_tail ( &list_tests[3].list, list );
+       list_add_tail ( &list_tests[1].list, list );
+       list_add_tail ( &list_tests[7].list, list );
+       ok ( list_prev_entry ( &list_tests[5], list, list ) == NULL );
+       ok ( list_next_entry ( &list_tests[5], list, list ) == &list_tests[3] );
+       ok ( list_prev_entry ( &list_tests[3], list, list ) == &list_tests[5] );
+       ok ( list_next_entry ( &list_tests[3], list, list ) == &list_tests[1] );
+       ok ( list_prev_entry ( &list_tests[1], list, list ) == &list_tests[3] );
+       ok ( list_next_entry ( &list_tests[1], list, list ) == &list_tests[7] );
+       ok ( list_prev_entry ( &list_tests[7], list, list ) == &list_tests[1] );
+       ok ( list_next_entry ( &list_tests[7], list, list ) == NULL );
+       list_del ( &list_tests[7].list );
+       ok ( list_prev_entry ( &list_tests[1], list, list ) == &list_tests[3] );
+       ok ( list_next_entry ( &list_tests[1], list, list ) == NULL );
+       list_del ( &list_tests[3].list );
+       ok ( list_prev_entry ( &list_tests[5], list, list ) == NULL );
+       ok ( list_next_entry ( &list_tests[5], list, list ) == &list_tests[1] );
+       ok ( list_prev_entry ( &list_tests[1], list, list ) == &list_tests[5] );
+       ok ( list_next_entry ( &list_tests[1], list, list ) == NULL );
+
        /* Test list_for_each() */
        INIT_LIST_HEAD ( list );
        list_add_tail ( &list_tests[6].list, list );