X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftlist%2Ftlist.h;h=37882ee7bbdcc62f0eaa38097a3c9b66eacc05fa;hb=78b06543e80fc76b953b6a65684dce312da7e660;hp=7e43fe29ee8a8ed664374ec8b59ca82376f988f1;hpb=74257cee33ae3033f961d5f22a0313b8cb1b18d4;p=ccan diff --git a/ccan/tlist/tlist.h b/ccan/tlist/tlist.h index 7e43fe29..37882ee7 100644 --- a/ccan/tlist/tlist.h +++ b/ccan/tlist/tlist.h @@ -2,24 +2,25 @@ #ifndef CCAN_TLIST_H #define CCAN_TLIST_H #include +#include -#if HAVE_FLEXIBLE_ARRAY_MEMBER /** * TLIST_TYPE - declare a typed list type (struct tlist) * @suffix: the name to use (struct tlist_@suffix) * @type: the type the list will contain (void for any type) * - * This declares a structure "struct tlist_@suffix" to use for - * lists containing this type. The actual list can be accessed using - * ".raw" or tlist_raw(). + * This declares a structure "struct tlist_@suffix" to use for lists + * containing this type. The actual list can be accessed using + * tlist_raw(). For maximum portability, place tlists embedded in + * structures as the last member. * * Example: * // Defines struct tlist_children * TLIST_TYPE(children, struct child); * struct parent { * const char *name; - * struct tlist_children children; * unsigned int num_children; + * struct tlist_children children; * }; * * struct child { @@ -27,31 +28,11 @@ * struct list_node list; * }; */ -#define TLIST_TYPE(suffix, type) \ - struct tlist_##suffix { \ - struct list_head raw; \ - const type *tcheck[]; \ +#define TLIST_TYPE(suffix, type) \ + struct tlist_##suffix { \ + TCON_WRAP(struct list_head, type *canary); \ } -/** - * tlist_raw - access the raw list inside a typed list head. - * @h: the head of the typed list (struct tlist_@suffix) - * @test_var: a pointer to the expected element type. - * - * This elaborate macro usually causes the compiler to emit a warning - * if the variable is of an unexpected type. It is used internally - * where we need to access the raw underlying list. - */ -#define tlist_raw(h, test_var) \ - (sizeof((h)->tcheck[0] == (test_var)) ? &(h)->raw : &(h)->raw) -#else -#define TLIST_TYPE(suffix, type) \ - struct tlist_##suffix { \ - struct list_head raw; \ - } -#define tlist_raw(h, test_var) (&(h)->raw) -#endif - /** * TLIST_INIT - initalizer for an empty tlist * @name: the name of the list. @@ -64,7 +45,7 @@ * Example: * static struct tlist_children my_list = TLIST_INIT(my_list); */ -#define TLIST_INIT(name) { LIST_HEAD_INIT(name.raw) } +#define TLIST_INIT(name) TCON_WRAP_INIT(LIST_HEAD_INIT(*tcon_unwrap(&name))) /** * tlist_check - check head of a list for consistency @@ -93,7 +74,7 @@ * } */ #define tlist_check(h, abortstr) \ - list_check(&(h)->raw, (abortstr)) + list_check(tcon_unwrap(h), (abortstr)) /** * tlist_init - initialize a tlist @@ -106,7 +87,18 @@ * tlist_init(&parent->children); * parent->num_children = 0; */ -#define tlist_init(h) list_head_init(&(h)->raw) +#define tlist_init(h) list_head_init(tcon_unwrap(h)) + +/** + * tlist_raw - unwrap the typed list and check the type + * @h: the tlist + * @expr: the expression to check the type against (not evaluated) + * + * This macro usually causes the compiler to emit a warning if the + * variable is of an unexpected type. It is used internally where we + * need to access the raw underlying list. + */ +#define tlist_raw(h, expr) tcon_unwrap(tcon_check((h), canary, (expr))) /** * tlist_add - add an entry at the start of a linked list. @@ -181,37 +173,69 @@ * Example: * assert(tlist_empty(&parent->children) == (parent->num_children == 0)); */ -#define tlist_empty(h) list_empty(&(h)->raw) +#define tlist_empty(h) list_empty(tcon_unwrap(h)) /** * tlist_top - get the first entry in a list * @h: the tlist - * @type: the type of the entry * @member: the list_node member of the type * * If the list is empty, returns NULL. * * Example: * struct child *first; - * first = tlist_top(&parent->children, struct child, list); + * first = tlist_top(&parent->children, list); + * if (!first) + * printf("Empty list!\n"); */ -#define tlist_top(h, type, member) \ - list_top(tlist_raw((h), (type *)NULL), type, member) +#define tlist_top(h, member) \ + ((tcon_type((h), canary)) \ + list_top_(tcon_unwrap((h)), \ + (char *)(&(h)->_tcon[0].canary->member) - \ + (char *)((h)->_tcon[0].canary))) /** * tlist_tail - get the last entry in a list * @h: the tlist - * @type: the type of the entry * @member: the list_node member of the type * * If the list is empty, returns NULL. * * Example: * struct child *last; - * last = tlist_tail(&parent->children, struct child, list); + * last = tlist_tail(&parent->children, list); + * if (!last) + * printf("Empty list!\n"); + */ +#define tlist_tail(h, member) \ + ((tcon_type((h), canary)) \ + list_tail_(tcon_unwrap(h), \ + (char *)(&(h)->_tcon[0].canary->member) - \ + (char *)((h)->_tcon[0].canary))) + +/** + * tlist_next - get the next entry in a list + * @h: the tlist + * @n: the list element + * @member: the list_node member of the type + * + * Returns the element of list @h immediately after @n, or NULL, if @n + * is the last element in the list. */ -#define tlist_tail(h, type, member) \ - list_tail(tlist_raw((h), (type *)NULL), type, member) +#define tlist_next(h, n, member) \ + list_next(tlist_raw((h), (n)), (n), member) + +/** + * tlist_prev - get the previous entry in a list + * @h: the tlist + * @n: the list element + * @member: the list_node member of the type + * + * Returns the element of list @h immediately before @n, or NULL, if + * @n is the first element in the list. + */ +#define tlist_prev(h, n, member) \ + list_prev(tlist_raw((h), (n)), (n), member) /** * tlist_for_each - iterate through a list. @@ -229,6 +253,22 @@ #define tlist_for_each(h, i, member) \ list_for_each(tlist_raw((h), (i)), (i), member) +/** + * tlist_for_each - iterate through a list backwards. + * @h: the tlist + * @i: an iterator of suitable type for this list. + * @member: the list_node member of @i + * + * 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: + * tlist_for_each_rev(&parent->children, child, list) + * printf("Name: %s\n", child->name); + */ +#define tlist_for_each_rev(h, i, member) \ + list_for_each_rev(tlist_raw((h), (i)), (i), member) + /** * tlist_for_each_safe - iterate through a list, maybe during deletion * @h: the tlist