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