| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #ifndef CCAN_TLIST_H
- #define CCAN_TLIST_H
- #include <ccan/list/list.h>
- #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().
- *
- * Example:
- * // Defines struct tlist_children
- * TLIST_TYPE(children, struct child);
- * struct parent {
- * const char *name;
- * struct tlist_children children;
- * unsigned int num_children;
- * };
- *
- * struct child {
- * const char *name;
- * struct list_node list;
- * };
- */
- #define TLIST_TYPE(suffix, type) \
- struct tlist_##suffix { \
- struct list_head raw; \
- const type *tcheck[]; \
- }
- /**
- * 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.
- *
- * Explicit initializer for an empty list.
- *
- * See also:
- * tlist_init()
- *
- * Example:
- * static struct tlist_children my_list = TLIST_INIT(my_list);
- */
- #define TLIST_INIT(name) { LIST_HEAD_INIT(name.raw) }
- /**
- * tlist_check - check head of a list for consistency
- * @h: the tlist_head
- * @abortstr: the location to print on aborting, or NULL.
- *
- * Because list_nodes have redundant information, consistency checking between
- * the back and forward links can be done. This is useful as a debugging check.
- * If @abortstr is non-NULL, that will be printed in a diagnostic if the list
- * is inconsistent, and the function will abort.
- *
- * Returns non-NULL if the list is consistent, NULL otherwise (it
- * can never return NULL if @abortstr is set).
- *
- * See also: list_check()
- *
- * Example:
- * static void dump_parent(struct parent *p)
- * {
- * struct child *c;
- *
- * printf("%s (%u children):\n", p->name, p->num_children);
- * tlist_check(&p->children, "bad child list");
- * tlist_for_each(&p->children, c, list)
- * printf(" -> %s\n", c->name);
- * }
- */
- #define tlist_check(h, abortstr) \
- list_check(&(h)->raw, (abortstr))
- /**
- * tlist_init - initialize a tlist
- * @h: the tlist to set to the empty list
- *
- * Example:
- * ...
- * struct parent *parent = malloc(sizeof(*parent));
- *
- * tlist_init(&parent->children);
- * parent->num_children = 0;
- */
- #define tlist_init(h) list_head_init(&(h)->raw)
- /**
- * tlist_add - add an entry at the start of a linked list.
- * @h: the tlist to add the node to
- * @n: the entry to add to the list.
- * @member: the member of n to add to the list.
- *
- * The entry's list_node does not need to be initialized; it will be
- * overwritten.
- * Example:
- * struct child *child = malloc(sizeof(*child));
- *
- * child->name = "marvin";
- * tlist_add(&parent->children, child, list);
- * parent->num_children++;
- */
- #define tlist_add(h, n, member) list_add(tlist_raw((h), (n)), &(n)->member)
- /**
- * tlist_add_tail - add an entry at the end of a linked list.
- * @h: the tlist to add the node to
- * @n: the entry to add to the list.
- * @member: the member of n to add to the list.
- *
- * The list_node does not need to be initialized; it will be overwritten.
- * Example:
- * tlist_add_tail(&parent->children, child, list);
- * parent->num_children++;
- */
- #define tlist_add_tail(h, n, member) \
- list_add_tail(tlist_raw((h), (n)), &(n)->member)
- /**
- * tlist_del_from - delete an entry from a linked list.
- * @h: the tlist @n is in
- * @n: the entry to delete
- * @member: the member of n to remove from the list.
- *
- * This explicitly indicates which list a node is expected to be in,
- * which is better documentation and can catch more bugs.
- *
- * Note that this leaves @n->@member in an undefined state; it
- * can be added to another list, but not deleted again.
- *
- * See also: tlist_del()
- *
- * Example:
- * tlist_del_from(&parent->children, child, list);
- * parent->num_children--;
- */
- #define tlist_del_from(h, n, member) \
- list_del_from(tlist_raw((h), (n)), &(n)->member)
- /**
- * tlist_del - delete an entry from an unknown linked list.
- * @n: the entry to delete from the list.
- * @member: the member of @n which is in the list.
- *
- * Example:
- * tlist_del(child, list);
- * parent->num_children--;
- */
- #define tlist_del(n, member) \
- list_del(&(n)->member)
- /**
- * tlist_empty - is a list empty?
- * @h: the tlist
- *
- * If the list is empty, returns true.
- *
- * Example:
- * assert(tlist_empty(&parent->children) == (parent->num_children == 0));
- */
- #define tlist_empty(h) list_empty(&(h)->raw)
- /**
- * 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);
- */
- #define tlist_top(h, type, member) \
- list_top(tlist_raw((h), (type *)NULL), type, member)
- /**
- * 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);
- */
- #define tlist_tail(h, type, member) \
- list_tail(tlist_raw((h), (type *)NULL), type, member)
- /**
- * tlist_for_each - iterate through a list.
- * @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(&parent->children, child, list)
- * printf("Name: %s\n", child->name);
- */
- #define tlist_for_each(h, i, member) \
- list_for_each(tlist_raw((h), (i)), (i), member)
- /**
- * tlist_for_each_safe - iterate through a list, maybe during deletion
- * @h: the tlist
- * @i: an iterator of suitable type for this list.
- * @nxt: another iterator to store the next entry.
- * @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. The extra variable
- * @nxt is used to hold the next element, so you can delete @i from the list.
- *
- * Example:
- * struct child *next;
- * tlist_for_each_safe(&parent->children, child, next, list) {
- * tlist_del(child, list);
- * parent->num_children--;
- * }
- */
- #define tlist_for_each_safe(h, i, nxt, member) \
- list_for_each_safe(tlist_raw((h), (i)), (i), (nxt), member)
- #endif /* CCAN_TLIST_H */
|