]> git.ozlabs.org Git - ccan/blob - ccan/tlist2/tlist2.h
crypto/shachain/tools: update to new rbuf API.
[ccan] / ccan / tlist2 / tlist2.h
1 /* Licensed under LGPL - see LICENSE file for details */
2 #ifndef CCAN_TLIST2_H
3 #define CCAN_TLIST2_H
4 #include <ccan/list/list.h>
5 #include <ccan/tcon/tcon.h>
6
7 /**
8  * TLIST2 - declare a typed list type (struct tlist)
9  * @etype: the type the list will contain
10  * @link: the name of the member of @etype that is the link
11  *
12  * This declares an anonymous structure to use for lists containing this type.
13  * The actual list can be accessed using tlist2_raw().
14  *
15  * Example:
16  *      #include <ccan/list/list.h>
17  *      #include <ccan/tlist2/tlist2.h>
18  *      struct child {
19  *              const char *name;
20  *              struct list_node list;
21  *      };
22  *      struct parent {
23  *              const char *name;
24  *              TLIST2(struct child, list) children;
25  *              unsigned int num_children;
26  *      };
27  *
28  */
29 #define TLIST2(etype, link)                             \
30         TCON_WRAP(struct list_head,                     \
31                 TCON_CONTAINER(canary, etype, link))
32
33 /**
34  * TLIST2_INIT - initializer for an empty tlist
35  * @name: the name of the list.
36  *
37  * Explicit initializer for an empty list.
38  *
39  * See also:
40  *      tlist2_init()
41  *
42  * Example:
43  *      TLIST2(struct child, list) my_list = TLIST2_INIT(my_list);
44  */
45 #define TLIST2_INIT(name) TCON_WRAP_INIT( LIST_HEAD_INIT(*tcon_unwrap(&(name))) )
46
47 /**
48  * tlist2_check - check head of a list for consistency
49  * @h: the tlist2 head
50  * @abortstr: the location to print on aborting, or NULL.
51  *
52  * Because list_nodes have redundant information, consistency checking between
53  * the back and forward links can be done.  This is useful as a debugging check.
54  * If @abortstr is non-NULL, that will be printed in a diagnostic if the list
55  * is inconsistent, and the function will abort.
56  *
57  * Returns non-NULL if the list is consistent, NULL otherwise (it
58  * can never return NULL if @abortstr is set).
59  *
60  * See also: list_check()
61  *
62  * Example:
63  *      static void dump_parent(struct parent *p)
64  *      {
65  *              struct child *c;
66  *
67  *              printf("%s (%u children):\n", p->name, p->num_children);
68  *              tlist2_check(&p->children, "bad child list");
69  *              tlist2_for_each(&p->children, c)
70  *                      printf(" -> %s\n", c->name);
71  *      }
72  */
73 #define tlist2_check(h, abortstr) \
74         list_check(tcon_unwrap(h), (abortstr))
75
76 /**
77  * tlist2_init - initialize a tlist
78  * @h: the tlist to set to the empty list
79  *
80  * Example:
81  *      ...
82  *      struct parent *parent = malloc(sizeof(*parent));
83  *
84  *      tlist2_init(&parent->children);
85  *      parent->num_children = 0;
86  */
87 #define tlist2_init(h) list_head_init(tcon_unwrap(h))
88
89 /**
90  * tlist2_raw - unwrap the typed list and check the type
91  * @h: the tlist
92  * @expr: the expression to check the type against (not evaluated)
93  *
94  * This macro usually causes the compiler to emit a warning if the
95  * variable is of an unexpected type.  It is used internally where we
96  * need to access the raw underlying list.
97  */
98 #define tlist2_raw(h, expr) tcon_unwrap(tcon_container_check_ptr(h, canary, expr))
99
100 /**
101  * tlist2_unwrap - unwrap the typed list without any checks
102  * @h: the tlist
103  */
104 #define tlist2_unwrap(h) tcon_unwrap(h)
105
106 /**
107  * tlist2_add - add an entry at the start of a linked list.
108  * @h: the tlist to add the node to
109  * @n: the entry to add to the list.
110  *
111  * The entry's list_node does not need to be initialized; it will be
112  * overwritten.
113  * Example:
114  *      struct child *child = malloc(sizeof(*child));
115  *
116  *      child->name = "marvin";
117  *      tlist2_add(&parent->children, child);
118  *      parent->num_children++;
119  */
120 #define tlist2_add(h, n) list_add(tlist2_raw((h), (n)), tcon_member_of(h, canary, n))
121
122 /**
123  * tlist2_add_tail - add an entry at the end of a linked list.
124  * @h: the tlist to add the node to
125  * @n: the entry to add to the list.
126  *
127  * The list_node does not need to be initialized; it will be overwritten.
128  * Example:
129  *      tlist2_add_tail(&parent->children, child);
130  *      parent->num_children++;
131  */
132 #define tlist2_add_tail(h, n) \
133         list_add_tail(tlist2_raw((h), (n)), tcon_member_of((h), canary, (n)))
134
135 /**
136  * tlist2_del_from - delete an entry from a linked list.
137  * @h: the tlist @n is in
138  * @n: the entry to delete
139  *
140  * This explicitly indicates which list a node is expected to be in,
141  * which is better documentation and can catch more bugs.
142  *
143  * Note that this leaves @n->@member in an undefined state; it
144  * can be added to another list, but not deleted again.
145  *
146  * Example:
147  *      tlist2_del_from(&parent->children, child);
148  *      parent->num_children--;
149  */
150 #define tlist2_del_from(h, n) \
151         list_del_from(tlist2_raw((h), (n)), tcon_member_of((h), canary, (n)))
152
153 /**
154  * tlist2_empty - is a list empty?
155  * @h: the tlist
156  *
157  * If the list is empty, returns true.
158  *
159  * Example:
160  *      assert(tlist2_empty(&parent->children) == (parent->num_children == 0));
161  */
162 #define tlist2_empty(h) list_empty(tcon_unwrap(h))
163
164 /**
165  * tlist2_top - get the first entry in a list
166  * @h: the tlist
167  *
168  * If the list is empty, returns NULL.
169  *
170  * Example:
171  *      struct child *first;
172  *      first = tlist2_top(&parent->children);
173  *      if (!first)
174  *              printf("Empty list!\n");
175  */
176 #define tlist2_top(h) tcon_container_of((h), canary, list_top_(tcon_unwrap(h), 0))
177
178 /**
179  * tlist2_tail - get the last entry in a list
180  * @h: the tlist
181  *
182  * If the list is empty, returns NULL.
183  *
184  * Example:
185  *      struct child *last;
186  *      last = tlist2_tail(&parent->children);
187  *      if (!last)
188  *              printf("Empty list!\n");
189  */
190 #define tlist2_tail(h) tcon_container_of((h), canary, list_tail_(tcon_unwrap(h), 0))
191
192 /**
193  * tlist2_for_each - iterate through a list.
194  * @h: the tlist
195  * @i: an iterator of suitable type for this list.
196  *
197  * This is a convenient wrapper to iterate @i over the entire list.  It's
198  * a for loop, so you can break and continue as normal.
199  *
200  * Example:
201  *      tlist2_for_each(&parent->children, child)
202  *              printf("Name: %s\n", child->name);
203  */
204 #define tlist2_for_each(h, i)                                   \
205         list_for_each_off(tlist2_raw((h), (i)), (i), tcon_offset((h), canary))
206
207 /**
208  * tlist2_for_each_rev - iterate through a list backwards.
209  * @h: the tlist
210  * @i: an iterator of suitable type for this list.
211  *
212  * This is a convenient wrapper to iterate @i over the entire list.  It's
213  * a for loop, so you can break and continue as normal.
214  *
215  * Example:
216  *      tlist2_for_each_rev(&parent->children, child)
217  *              printf("Name: %s\n", child->name);
218  */
219 #define tlist2_for_each_rev(h, i)                                       \
220         list_for_each_rev_off(tlist2_raw((h), (i)), (i), tcon_offset((h), canary))
221
222 /**
223  * tlist2_for_each_safe - iterate through a list, maybe during deletion
224  * @h: the tlist
225  * @i: an iterator of suitable type for this list.
226  * @nxt: another iterator to store the next entry.
227  *
228  * This is a convenient wrapper to iterate @i over the entire list.  It's
229  * a for loop, so you can break and continue as normal.  The extra variable
230  * @nxt is used to hold the next element, so you can delete @i from the list.
231  *
232  * Example:
233  *      struct child *next;
234  *      tlist2_for_each_safe(&parent->children, child, next) {
235  *              tlist2_del_from(&parent->children, child);
236  *              parent->num_children--;
237  *      }
238  */
239 #define tlist2_for_each_safe(h, i, nxt)                         \
240         list_for_each_safe_off(tlist2_raw((h), (i)), (i), (nxt), tcon_offset((h), canary))
241
242 #endif /* CCAN_TLIST2_H */