]> git.ozlabs.org Git - ccan/blob - ccan/tlist/tlist.h
tlist: use ccan/tcon
[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  * @type: the type of the entry
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, struct child, list);
189  */
190 #define tlist_top(h, type, member) \
191         list_top(tlist_raw((h), (type *)NULL), type, member)
192
193 /**
194  * tlist_tail - get the last entry in a list
195  * @h: the tlist
196  * @type: the type of the entry
197  * @member: the list_node member of the type
198  *
199  * If the list is empty, returns NULL.
200  *
201  * Example:
202  *      struct child *last;
203  *      last = tlist_tail(&parent->children, struct child, list);
204  */
205 #define tlist_tail(h, type, member) \
206         list_tail(tlist_raw((h), (type *)NULL), type, member)
207
208 /**
209  * tlist_for_each - iterate through a list.
210  * @h: the tlist
211  * @i: an iterator of suitable type for this list.
212  * @member: the list_node member of @i
213  *
214  * This is a convenient wrapper to iterate @i over the entire list.  It's
215  * a for loop, so you can break and continue as normal.
216  *
217  * Example:
218  *      tlist_for_each(&parent->children, child, list)
219  *              printf("Name: %s\n", child->name);
220  */
221 #define tlist_for_each(h, i, member)                                    \
222         list_for_each(tlist_raw((h), (i)), (i), member)
223
224 /**
225  * tlist_for_each_safe - iterate through a list, maybe during deletion
226  * @h: the tlist
227  * @i: an iterator of suitable type for this list.
228  * @nxt: another iterator to store the next entry.
229  * @member: the list_node member of the structure
230  *
231  * This is a convenient wrapper to iterate @i over the entire list.  It's
232  * a for loop, so you can break and continue as normal.  The extra variable
233  * @nxt is used to hold the next element, so you can delete @i from the list.
234  *
235  * Example:
236  *      struct child *next;
237  *      tlist_for_each_safe(&parent->children, child, next, list) {
238  *              tlist_del(child, list);
239  *              parent->num_children--;
240  *      }
241  */
242 #define tlist_for_each_safe(h, i, nxt, member)                          \
243         list_for_each_safe(tlist_raw((h), (i)), (i), (nxt), member)
244
245 #endif /* CCAN_TLIST_H */