2 * Some simple implementation of lists similar to the one used in the kernel.
4 * Copyright (c) 2016-2019 The strace developers.
7 * SPDX-License-Identifier: LGPL-2.1-or-later
11 # define STRACE_LIST_H
14 * struct list_item and related macros and functions provide an interface
15 * for manipulating and iterating linked lists. In order to have list
16 * associated with its payload, struct list_item has to be embedded into
17 * a structure type representing payload, and (optionally) an additional
18 * struct list_item should be added somewhere as a starting point for list
19 * iteration (creating a list with a designated head). A situation where
20 * no designated head exists, and each embedded struct list_head is considered
21 * a head (i.e. starting point for list iteration), is also possible.
23 * List head has to be initialised with list_init() call. Statically allocated
24 * list heads can also be defined with an EMPTY_LIST() macro.
26 * In order to get a pointer to list item from a struct list_item, list_elem
29 * When a designated head is used, list_head() and list_tail() can be used
30 * for getting pointer to the first and the last list item, respectively.
32 * list_next() and list_prev() macros can be used for obtaining pointers
33 * to the next and the previous items in the list, respectively. Note that
34 * they do not perform additional checks for the validity of these pointers,
35 * so they have to be guarded with respective list_head/list_tail checks in case
36 * of lists with designated heads (where the list's head is not embedded withing
39 * list_{insert,append,remove,remove_tail,remove_head,replace} provide some
40 * basic means of list manipulation.
42 * list_foreach() and list_foreach_safe() are wrapper macros for simplifying
43 * iteration over a list, with the latter having an additional argument
44 * for storing temporary pointer, thus allowing list manipulations during
51 * struct list_item l1;
52 * struct list_item l2;
55 * EMPTY_LIST(list_1); <--- Defining a designated head for list
57 * struct my_struct *item =
58 * calloc(1, sizeof(*item));
59 * list_init(&item->l2); <--- Initialising structure field that
60 * is used for lists without designated
62 * list_insert(&list_1, &item->l1); <--- Inserting an item into the list
64 * item = calloc(1, sizeof(*item));
65 * list_init(&item->l2);
67 * list_append(&(list_head(list_1, struct my_struct, l1)->l2), &item->l2);
69 * struct my_struct *cur = item; <--- Iteration over a headless list
71 * printf("%d\n", cur->a);
72 * } while ((cur = list_next(&cur, l2)) != item);
74 * struct my_struct *i;
75 * list_foreach(i, list_1, l1) { <--- Iteration over list_1 without list
76 * printf("%d\n", i->a); modification
79 * struct my_struct *tmp; <--- Iteration with modification
80 * list_foreach_safe(i, list_1, l1, tmp) {
81 * list_remove(&i->l1);
86 * "Linux kernel design patterns - part 2", section "Linked Lists"
87 * https://lwn.net/Articles/336255/
93 struct list_item *prev;
94 struct list_item *next;
98 * Define an empty list head.
100 * @param l_ List head variable name.
102 # define EMPTY_LIST(l_) struct list_item l_ = { &l_, &l_ }
104 /** Initialise an empty list. */
106 list_init(struct list_item *l)
112 /** Check whether list is empty. */
114 list_is_empty(const struct list_item *l)
116 return ((l->next == l) && (l->prev == l))
118 * XXX This could be the case when struct list_item hasn't been
119 * initialised at all; we should probably also call some
120 * errror_func_msg() in that case, as it looks like sloppy
123 || (!l->next && !l->prev);
127 * Convert a pointer to a struct list_item to a pointer to a list item.
129 * @param var Pointer to struct list_item.
130 * @param type Type of the list's item.
131 * @param field Name of the field that holds the respective struct list_item.
133 # define list_elem(var, type, field) containerof((var), type, field)
136 * Get the first element in a list.
138 * @param head Pointer to the list's head.
139 * @param type Type of the list's item.
140 * @param field Name of the field that holds the respective struct list_item.
142 # define list_head(head, type, field) \
143 (list_is_empty(head) ? NULL : list_elem((head)->next, type, field))
145 * Get the last element in a list.
147 * @param head Pointer to the list's head.
148 * @param type Type of the list's item.
149 * @param field Name of the field that holds the respective struct list_item.
151 # define list_tail(head, type, field) \
152 (list_is_empty(head) ? NULL : list_elem((head)->prev, type, field))
155 * Get the next element in a list.
157 * @param var Pointer to a list item.
158 * @param field Name of the field that holds the respective struct list_item.
160 # define list_next(var, field) \
161 list_elem((var)->field.next, typeof(*(var)), field)
163 * Get the previous element in a list.
165 * @param var Pointer to a list item.
166 * @param field Name of the field that holds the respective struct list_item.
168 # define list_prev(var, field) \
169 list_elem((var)->field.prev, typeof(*(var)), field)
172 * Insert an item into a list. The item is placed as the next list item
176 list_insert(struct list_item *head, struct list_item *item)
178 item->next = head->next;
180 head->next->prev = item;
185 * Insert an item into a list. The item is placed as the previous list item
189 list_append(struct list_item *head, struct list_item *item)
192 item->prev = head->prev;
193 head->prev->next = item;
198 * Remove an item from a list.
200 * @param item Pointer to struct list_item of the item to be removed.
201 * @return Whether the action has been performed.
204 list_remove(struct list_item *item)
206 if (!item->next || !item->prev || list_is_empty(item))
209 item->prev->next = item->next;
210 item->next->prev = item->prev;
211 item->next = item->prev = item;
217 * Remove the last element of a list.
219 * @param head Pointer to the list's head.
220 * @return Pointer to struct list_item removed from the list;
221 * or NULL, if the list is empty.
223 static inline struct list_item *
224 list_remove_tail(struct list_item *head)
226 struct list_item *t = list_is_empty(head) ? NULL : head->prev;
235 * Remove the first element of a list.
237 * @param head Pointer to the list's head.
238 * @return Pointer to struct list_item removed from the list;
239 * or NULL, if the list is empty.
241 static inline struct list_item *
242 list_remove_head(struct list_item *head)
244 struct list_item *h = list_is_empty(head) ? NULL : head->next;
253 * Replace an old struct list_item in a list with the new one.
255 * @param old Pointer to struct list_item of the item to be replaced.
256 * @param new Pointer to struct list_item of the item to be replaced with.
257 * @return Whether the replacement has been performed.
260 list_replace(struct list_item *old, struct list_item *new)
262 if (!old->next || !old->prev || list_is_empty(old))
265 new->next = old->next;
266 new->prev = old->prev;
267 old->prev->next = new;
268 old->next->prev = new;
269 old->next = old->prev = old;
275 * List iteration wrapper for non-destructive operations.
277 * @param var_ Variable holding pointer to a current list item.
278 * @param head_ Pointer to the list's head.
279 * @param field_ Name of the field containing the respective struct list_item
282 # define list_foreach(var_, head_, field_) \
283 for (var_ = list_elem((head_)->next, typeof(*var_), field_); \
284 &(var_->field_) != (head_); var_ = list_next(var_, field_))
287 * List iteration wrapper for destructive operations.
289 * @param var_ Variable holding pointer to a current list item.
290 * @param head_ Pointer to the list's head.
291 * @param field_ Name of the field containing the respective struct list_item
293 * @param _tmp Temporary variable for storing pointer to the next item.
295 # define list_foreach_safe(var_, head_, field_, _tmp) \
296 for (var_ = list_elem((head_)->next, typeof(*var_), field_), \
297 _tmp = list_elem((var_)->field_.next, typeof(*var_), field_); \
298 &var_->field_ != head_; var_ = _tmp, _tmp = list_next(_tmp, field_))
300 #endif /* !STRACE_LIST_H */