Browse Source

list: implement list_for_each_rev()

Rusty Russell 14 years ago
parent
commit
c414947a86
2 changed files with 38 additions and 1 deletions
  1. 18 0
      ccan/list/list.h
  2. 20 1
      ccan/list/test/run.c

+ 18 - 0
ccan/list/list.h

@@ -315,6 +315,24 @@ static inline void list_del_from(struct list_head *h, struct list_node *n)
 	     &i->member != &(h)->n;					\
 	     &i->member != &(h)->n;					\
 	     i = container_of_var(i->member.next, i, member))
 	     i = container_of_var(i->member.next, i, member))
 
 
+/**
+ * list_for_each_rev - iterate through a list backwards.
+ * @h: the list_head
+ * @i: 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.  It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ *	list_for_each_rev(&parent->children, child, list)
+ *		printf("Name: %s\n", child->name);
+ */
+#define list_for_each_rev(h, i, member)					\
+	for (i = container_of_var(list_debug(h)->n.prev, i, member);	\
+	     &i->member != &(h)->n;					\
+	     i = container_of_var(i->member.prev, i, member))
+
 /**
 /**
  * list_for_each_safe - iterate through a list, maybe during deletion
  * list_for_each_safe - iterate through a list, maybe during deletion
  * @h: the list_head
  * @h: the list_head

+ 20 - 1
ccan/list/test/run.c

@@ -22,7 +22,7 @@ int main(int argc, char *argv[])
 	unsigned int i;
 	unsigned int i;
 	struct list_head list = LIST_HEAD_INIT(list);
 	struct list_head list = LIST_HEAD_INIT(list);
 
 
-	plan_tests(49);
+	plan_tests(53);
 	/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
 	/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
 	ok1(list_empty(&static_list));
 	ok1(list_empty(&static_list));
 	ok1(list_check(&static_list, NULL));
 	ok1(list_check(&static_list, NULL));
@@ -104,6 +104,25 @@ int main(int argc, char *argv[])
 	}
 	}
 	ok1(i == 3);
 	ok1(i == 3);
 
 
+	/* Test list_for_each_rev. */
+	i = 0;
+	list_for_each_rev(&parent.children, c, list) {
+		switch (i++) {
+		case 0:
+			ok1(c == &c3);
+			break;
+		case 1:
+			ok1(c == &c2);
+			break;
+		case 2:
+			ok1(c == &c1);
+			break;
+		}
+		if (i > 2)
+			break;
+	}
+	ok1(i == 3);
+
 	/* Test list_for_each_safe, list_del and list_del_from. */
 	/* Test list_for_each_safe, list_del and list_del_from. */
 	i = 0;
 	i = 0;
 	list_for_each_safe(&parent.children, c, n, list) {
 	list_for_each_safe(&parent.children, c, n, list) {