X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Flist%2Flist.h;h=03614873ef6a718aaaadec32a27356f82c6c7912;hb=715de3cf272d057e176d032986db45d2270494fc;hp=8e2f6df0273998764bb89cb69fb4c25d6e5b1070;hpb=c35fcafc261eb9c0f5aff1a608568b38ddc01f66;p=ccan diff --git a/ccan/list/list.h b/ccan/list/list.h index 8e2f6df0..03614873 100644 --- a/ccan/list/list.h +++ b/ccan/list/list.h @@ -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; } +/** + * 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 @@ -371,6 +399,43 @@ static inline const void *list_tail_(const struct list_head *h, size_t off) #define list_for_each_safe(h, i, nxt, member) \ list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) +/** + * list_next - get the next entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the last entry in the list, returns NULL. + * + * Example: + * struct child *second; + * second = list_next(&parent->children, first, list); + * if (!second) + * printf("No second child!\n"); + */ +#define list_next(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h), \ + (i)->member.next, \ + list_off_var_((i), member))) + +/** + * list_prev - get the previous entry in a list + * @h: the list_head + * @i: a pointer to an entry in the list. + * @member: the list_node member of the structure + * + * If @i was the first entry in the list, returns NULL. + * + * Example: + * first = list_prev(&parent->children, second, list); + * if (!first) + * printf("Can't go back to first child?!\n"); + */ +#define list_prev(h, i, member) \ + ((list_typeof(i))list_entry_or_null(list_debug(h), \ + (i)->member.prev, \ + list_off_var_((i), member))) + /** * list_append_list - empty one list onto the end of another. * @to: the list to append into @@ -532,4 +597,19 @@ static inline struct list_node *list_node_from_off_(void *ptr, size_t off) (container_off_var(var, member) + \ check_type(var->member, struct list_node)) +#if HAVE_TYPEOF +#define list_typeof(var) typeof(var) +#else +#define list_typeof(var) void * +#endif + +/* Returns member, or NULL if at end of list. */ +static inline void *list_entry_or_null(struct list_head *h, + struct list_node *n, + size_t off) +{ + if (n == &h->n) + return NULL; + return (char *)n - off; +} #endif /* CCAN_LIST_H */