list: add list_for_each_rev_safe{,_off} macros
[ccan] / ccan / list / list.h
index 90989c5fc04b6bd8436361dcda42f8f5f0ce7853..275442d23da05cb8fe9c462e75ffd589fa97e374 100644 (file)
@@ -522,9 +522,29 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
  *             printf("Name: %s\n", child->name);
  */
 #define list_for_each_rev(h, i, member)                                        \
-       for (i = container_of_var(list_debug(h, LIST_LOC)->n.prev, i, member); \
-            &i->member != &(h)->n;                                     \
-            i = container_of_var(i->member.prev, i, member))
+       list_for_each_rev_off(h, i, list_off_var_(i, member))
+
+/**
+ * list_for_each_rev_safe - iterate through a list backwards,
+ * maybe during deletion
+ * @h: the list_head
+ * @i: the structure containing the list_node
+ * @nxt: the structure containing the list_node
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list backwards.
+ * It's a for loop, so you can break and continue as normal.  The extra
+ * variable * @nxt is used to hold the next element, so you can delete @i
+ * from the list.
+ *
+ * Example:
+ *     struct child *next;
+ *     list_for_each_rev_safe(&parent->children, child, next, list) {
+ *             printf("Name: %s\n", child->name);
+ *     }
+ */
+#define list_for_each_rev_safe(h, i, nxt, member)                      \
+       list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member))
 
 /**
  * list_for_each_safe - iterate through a list, maybe during deletion
@@ -538,7 +558,6 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
  * @nxt is used to hold the next element, so you can delete @i from the list.
  *
  * Example:
- *     struct child *next;
  *     list_for_each_safe(&parent->children, child, next, list) {
  *             list_del(&child->list);
  *             parent->num_children--;
@@ -703,6 +722,17 @@ static inline void list_prepend_list_(struct list_head *to,
 #define list_for_each_off(h, i, off)                                    \
        list_for_each_off_dir_((h),(i),(off),next)
 
+/**
+ * list_for_each_rev_off - iterate through a list of memory regions backwards
+ * @h: the list_head
+ * @i: the pointer to a memory region wich contains list node data.
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * See list_for_each_off for details
+ */
+#define list_for_each_rev_off(h, i, off)                                    \
+       list_for_each_off_dir_((h),(i),(off),prev)
+
 /**
  * list_for_each_safe_off - iterate through a list of memory regions, maybe
  * during deletion
@@ -722,6 +752,25 @@ static inline void list_prepend_list_(struct list_head *to,
 #define list_for_each_safe_off(h, i, nxt, off)                          \
        list_for_each_safe_off_dir_((h),(i),(nxt),(off),next)
 
+/**
+ * list_for_each_rev_safe_off - iterate backwards through a list of
+ * memory regions, maybe during deletion
+ * @h: the list_head
+ * @i: the pointer to a memory region wich contains list node data.
+ * @nxt: the structure containing the list_node
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * For details see `list_for_each_rev_off' and `list_for_each_rev_safe'
+ * descriptions.
+ *
+ * Example:
+ *     list_for_each_rev_safe_off(&parent->children, child,
+ *             next, offsetof(struct child, list))
+ *             printf("Name: %s\n", child->name);
+ */
+#define list_for_each_rev_safe_off(h, i, nxt, off)                      \
+       list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev)
+
 /* Other -off variants. */
 #define list_entry_off(n, type, off)           \
        ((type *)list_node_from_off_((n), (off)))