]> git.ozlabs.org Git - ccan/blob - ccan/tlist/tlist.h
tlist: Place tlists last in structures
[ccan] / ccan / tlist / tlist.h
1 /* Licensed under LGPL - see LICENSE file for details */
2 #ifndef CCAN_TLIST_H
3 #define CCAN_TLIST_H
4 #include <ccan/list/list.h>
5 #include <ccan/tcon/tcon.h>
6
7 /**
8  * TLIST_TYPE - declare a typed list type (struct tlist)
9  * @suffix: the name to use (struct tlist_@suffix)
10  * @type: the type the list will contain (void for any type)
11  *
12  * This declares a structure "struct tlist_@suffix" to use for
13  * lists containing this type.  The actual list can be accessed using
14  * ".raw" or tlist_raw().  For maximum portability, place tlists
15  * embedded in structures as the last member.
16  *
17  * Example:
18  *      // Defines struct tlist_children
19  *      TLIST_TYPE(children, struct child);
20  *      struct parent {
21  *              const char *name;
22  *              unsigned int num_children;
23  *              struct tlist_children children;
24  *      };
25  *
26  *      struct child {
27  *              const char *name;
28  *              struct list_node list;
29  *      };
30  */
31 #define TLIST_TYPE(suffix, type)                        \
32         struct tlist_##suffix {                         \
33                 struct list_head raw;                   \
34                 TCON(type *canary);                     \
35         }
36
37 /**
38  * TLIST_INIT - initalizer for an empty tlist
39  * @name: the name of the list.
40  *
41  * Explicit initializer for an empty list.
42  *
43  * See also:
44  *      tlist_init()
45  *
46  * Example:
47  *      static struct tlist_children my_list = TLIST_INIT(my_list);
48  */
49 #define TLIST_INIT(name) { LIST_HEAD_INIT(name.raw) }
50
51 /**
52  * tlist_check - check head of a list for consistency
53  * @h: the tlist_head
54  * @abortstr: the location to print on aborting, or NULL.
55  *
56  * Because list_nodes have redundant information, consistency checking between
57  * the back and forward links can be done.  This is useful as a debugging check.
58  * If @abortstr is non-NULL, that will be printed in a diagnostic if the list
59  * is inconsistent, and the function will abort.
60  *
61  * Returns non-NULL if the list is consistent, NULL otherwise (it
62  * can never return NULL if @abortstr is set).
63  *
64  * See also: list_check()
65  *
66  * Example:
67  *      static void dump_parent(struct parent *p)
68  *      {
69  *              struct child *c;
70  *
71  *              printf("%s (%u children):\n", p->name, p->num_children);
72  *              tlist_check(&p->children, "bad child list");
73  *              tlist_for_each(&p->children, c, list)
74  *                      printf(" -> %s\n", c->name);
75  *      }
76  */
77 #define tlist_check(h, abortstr) \
78         list_check(&(h)->raw, (abortstr))
79
80 /**
81  * tlist_init - initialize a tlist
82  * @h: the tlist to set to the empty list
83  *
84  * Example:
85  *      ...
86  *      struct parent *parent = malloc(sizeof(*parent));
87  *
88  *      tlist_init(&parent->children);
89  *      parent->num_children = 0;
90  */
91 #define tlist_init(h) list_head_init(&(h)->raw)
92
93 /**
94  * tlist_raw - unwrap the typed list and check the type
95  * @h: the tlist
96  * @expr: the expression to check the type against (not evaluated)
97  *
98  * This macro usually causes the compiler to emit a warning if the
99  * variable is of an unexpected type.  It is used internally where we
100  * need to access the raw underlying list.
101  */
102 #define tlist_raw(h, expr) (&tcon_check((h), canary, (expr))->raw)
103
104 /**
105  * tlist_add - add an entry at the start of a linked list.
106  * @h: the tlist to add the node to
107  * @n: the entry to add to the list.
108  * @member: the member of n to add to the list.
109  *
110  * The entry's list_node does not need to be initialized; it will be
111  * overwritten.
112  * Example:
113  *      struct child *child = malloc(sizeof(*child));
114  *
115  *      child->name = "marvin";
116  *      tlist_add(&parent->children, child, list);
117  *      parent->num_children++;
118  */
119 #define tlist_add(h, n, member) list_add(tlist_raw((h), (n)), &(n)->member)
120
121 /**
122  * tlist_add_tail - add an entry at the end of a linked list.
123  * @h: the tlist to add the node to
124  * @n: the entry to add to the list.
125  * @member: the member of n to add to the list.
126  *
127  * The list_node does not need to be initialized; it will be overwritten.
128  * Example:
129  *      tlist_add_tail(&parent->children, child, list);
130  *      parent->num_children++;
131  */
132 #define tlist_add_tail(h, n, member) \
133         list_add_tail(tlist_raw((h), (n)), &(n)->member)
134
135 /**
136  * tlist_del_from - delete an entry from a linked list.
137  * @h: the tlist @n is in
138  * @n: the entry to delete
139  * @member: the member of n to remove from the list.
140  *
141  * This explicitly indicates which list a node is expected to be in,
142  * which is better documentation and can catch more bugs.
143  *
144  * Note that this leaves @n->@member in an undefined state; it
145  * can be added to another list, but not deleted again.
146  *
147  * See also: tlist_del()
148  *
149  * Example:
150  *      tlist_del_from(&parent->children, child, list);
151  *      parent->num_children--;
152  */
153 #define tlist_del_from(h, n, member) \
154         list_del_from(tlist_raw((h), (n)), &(n)->member)
155
156 /**
157  * tlist_del - delete an entry from an unknown linked list.
158  * @n: the entry to delete from the list.
159  * @member: the member of @n which is in the list.
160  *
161  * Example:
162  *      tlist_del(child, list);
163  *      parent->num_children--;
164  */
165 #define tlist_del(n, member) \
166         list_del(&(n)->member)
167
168 /**
169  * tlist_empty - is a list empty?
170  * @h: the tlist
171  *
172  * If the list is empty, returns true.
173  *
174  * Example:
175  *      assert(tlist_empty(&parent->children) == (parent->num_children == 0));
176  */
177 #define tlist_empty(h) list_empty(&(h)->raw)
178
179 /**
180  * tlist_top - get the first entry in a list
181  * @h: the tlist
182  * @member: the list_node member of the type
183  *
184  * If the list is empty, returns NULL.
185  *
186  * Example:
187  *      struct child *first;
188  *      first = tlist_top(&parent->children, list);
189  *      if (!first)
190  *              printf("Empty list!\n");
191  */
192 #define tlist_top(h, member)                                            \
193         ((tcon_type((h), canary))                                       \
194          list_top_(&(h)->raw,                                           \
195                    (char *)(&(h)->_tcon[0].canary->member) -            \
196                    (char *)((h)->_tcon[0].canary)))
197
198 /**
199  * tlist_tail - get the last entry in a list
200  * @h: the tlist
201  * @member: the list_node member of the type
202  *
203  * If the list is empty, returns NULL.
204  *
205  * Example:
206  *      struct child *last;
207  *      last = tlist_tail(&parent->children, list);
208  *      if (!last)
209  *              printf("Empty list!\n");
210  */
211 #define tlist_tail(h, member)                                           \
212         ((tcon_type((h), canary))                                       \
213          list_tail_(&(h)->raw,                                          \
214                     (char *)(&(h)->_tcon[0].canary->member) -           \
215                     (char *)((h)->_tcon[0].canary)))
216
217 /**
218  * tlist_next - get the next entry in a list
219  * @h: the tlist
220  * @n: the list element
221  * @member: the list_node member of the type
222  *
223  * Returns the element of list @h immediately after @n, or NULL, if @n
224  * is the last element in the list.
225  */
226 #define tlist_next(h, n, member)                                        \
227         list_next(tlist_raw((h), (n)), (n), member)
228
229 /**
230  * tlist_prev - get the previous entry in a list
231  * @h: the tlist
232  * @n: the list element
233  * @member: the list_node member of the type
234  *
235  * Returns the element of list @h immediately before @n, or NULL, if
236  * @n is the first element in the list.
237  */
238 #define tlist_prev(h, n, member)                                        \
239         list_prev(tlist_raw((h), (n)), (n), member)
240
241 /**
242  * tlist_for_each - iterate through a list.
243  * @h: the tlist
244  * @i: an iterator of suitable type for this list.
245  * @member: the list_node member of @i
246  *
247  * This is a convenient wrapper to iterate @i over the entire list.  It's
248  * a for loop, so you can break and continue as normal.
249  *
250  * Example:
251  *      tlist_for_each(&parent->children, child, list)
252  *              printf("Name: %s\n", child->name);
253  */
254 #define tlist_for_each(h, i, member)                                    \
255         list_for_each(tlist_raw((h), (i)), (i), member)
256
257 /**
258  * tlist_for_each - iterate through a list backwards.
259  * @h: the tlist
260  * @i: an iterator of suitable type for this list.
261  * @member: the list_node member of @i
262  *
263  * This is a convenient wrapper to iterate @i over the entire list.  It's
264  * a for loop, so you can break and continue as normal.
265  *
266  * Example:
267  *      tlist_for_each_rev(&parent->children, child, list)
268  *              printf("Name: %s\n", child->name);
269  */
270 #define tlist_for_each_rev(h, i, member)                                        \
271         list_for_each_rev(tlist_raw((h), (i)), (i), member)
272
273 /**
274  * tlist_for_each_safe - iterate through a list, maybe during deletion
275  * @h: the tlist
276  * @i: an iterator of suitable type for this list.
277  * @nxt: another iterator to store the next entry.
278  * @member: the list_node member of the structure
279  *
280  * This is a convenient wrapper to iterate @i over the entire list.  It's
281  * a for loop, so you can break and continue as normal.  The extra variable
282  * @nxt is used to hold the next element, so you can delete @i from the list.
283  *
284  * Example:
285  *      struct child *next;
286  *      tlist_for_each_safe(&parent->children, child, next, list) {
287  *              tlist_del(child, list);
288  *              parent->num_children--;
289  *      }
290  */
291 #define tlist_for_each_safe(h, i, nxt, member)                          \
292         list_for_each_safe(tlist_raw((h), (i)), (i), (nxt), member)
293
294 #endif /* CCAN_TLIST_H */