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