]> git.ozlabs.org Git - ccan/commitdiff
list: list_pop
authorRusty Russell <rusty@rustcorp.com.au>
Sun, 17 Mar 2013 04:42:14 +0000 (15:12 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Sun, 17 Mar 2013 04:42:14 +0000 (15:12 +1030)
list_top + list_del, as suggested by Ben Herrenschmidt.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/list/list.h
ccan/list/test/run.c

index 8e2f6df0273998764bb89cb69fb4c25d6e5b1070..ab3240871773d90ceee149c3cb30931e228326fb 100644 (file)
@@ -292,6 +292,34 @@ static inline const void *list_top_(const struct list_head *h, size_t off)
        return (const char *)h->n.next - off;
 }
 
        return (const char *)h->n.next - off;
 }
 
+/**
+ * list_pop - remove the first entry in a list
+ * @h: the list_head
+ * @type: the type of the entry
+ * @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ *     struct child *one;
+ *     one = list_pop(&parent->children, struct child, list);
+ *     if (!one)
+ *             printf("Empty list!\n");
+ */
+#define list_pop(h, type, member)                                      \
+       ((type *)list_pop_((h), list_off_(type, member)))
+
+static inline const void *list_pop_(const struct list_head *h, size_t off)
+{
+       struct list_node *n;
+
+       if (list_empty(h))
+               return NULL;
+       n = h->n.next;
+       list_del(n);
+       return (const char *)n - off;
+}
+
 /**
  * list_tail - get the last entry in a list
  * @h: the list_head
 /**
  * list_tail - get the last entry in a list
  * @h: the list_head
index 1d02acd5b763123ae365f4e185c676dd6c35453d..dad308282f7c14aa77bb2ecd54277770618b0ed5 100644 (file)
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
        opaque_t *q, *nq;
        struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
 
        opaque_t *q, *nq;
        struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
 
-       plan_tests(65);
+       plan_tests(68);
        /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
        ok1(list_empty(&static_list));
        ok1(list_check(&static_list, NULL));
        /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
        ok1(list_empty(&static_list));
        ok1(list_check(&static_list, NULL));
@@ -85,6 +85,11 @@ int main(int argc, char *argv[])
        /* Test list_top */
        ok1(list_top(&parent.children, struct child, list) == &c1);
 
        /* Test list_top */
        ok1(list_top(&parent.children, struct child, list) == &c1);
 
+       /* Test list_pop */
+       ok1(list_pop(&parent.children, struct child, list) == &c1);
+       ok1(list_top(&parent.children, struct child, list) == &c2);
+       list_add(&parent.children, &c1.list);
+
        /* Test list_tail */
        ok1(list_tail(&parent.children, struct child, list) == &c3);
 
        /* Test list_tail */
        ok1(list_tail(&parent.children, struct child, list) == &c3);
 
@@ -193,8 +198,9 @@ int main(int argc, char *argv[])
        ok1(i == 3);
        ok1(list_empty(&opaque_list));
 
        ok1(i == 3);
        ok1(list_empty(&opaque_list));
 
-       /* Test list_top/list_tail on empty list. */
+       /* Test list_top/list_tail/list_pop on empty list. */
        ok1(list_top(&parent.children, struct child, list) == NULL);
        ok1(list_tail(&parent.children, struct child, list) == NULL);
        ok1(list_top(&parent.children, struct child, list) == NULL);
        ok1(list_tail(&parent.children, struct child, list) == NULL);
+       ok1(list_pop(&parent.children, struct child, list) == NULL);
        return exit_status();
 }
        return exit_status();
 }