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