VLC 4.0.0-dev
Loading...
Searching...
No Matches
vlc_list.h
Go to the documentation of this file.
1/******************************************************************************
2 * vlc_list.h
3 ******************************************************************************
4 * Copyright © 2018 Rémi Denis-Courmont
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
20
21#ifndef VLC_LIST_H
22# define VLC_LIST_H 1
23
24# include <stdalign.h>
25# include <stdbool.h>
26
27/**
28 * \defgroup list Linked lists
29 * \ingroup cext
30 * @{
31 * \file
32 * This provides convenience helpers for linked lists.
33 */
34
35/**
36 * Doubly-linked list node.
37 *
38 * This data structure provides a doubly-linked list node.
39 * It must be embedded in each member of a list as a node proper.
40 * It also serves as a list head in the object containing the list.
41 */
42struct vlc_list
44 struct vlc_list *prev;
45 struct vlc_list *next;
46};
47
48/**
49 * Static initializer for a list head.
50 */
51#define VLC_LIST_INITIALIZER(h) { h, h }
53/**
54 * Initializes an empty list head.
55 */
56static inline void vlc_list_init(struct vlc_list *restrict head)
58 head->prev = head;
59 head->next = head;
60}
61
62/**
63 * Inserts an element in a list.
64 *
65 * \param node [out] Node pointer of the element to insert.
66 * \param prev Node pointer of the previous element.
67 * \param next Node pointer of the next element.
68 */
69static inline void vlc_list_add_between(struct vlc_list *restrict node,
70 struct vlc_list *prev,
71 struct vlc_list *next)
72{
73 node->prev = prev;
74 node->next = next;
75 prev->next = node;
76 next->prev = node;
77}
78
79/**
80 * Inserts an element after another.
81 *
82 * \param node [out] Node pointer of the element to insert
83 * \param prev Node pointer of the previous element.
84 */
85static inline void vlc_list_add_after(struct vlc_list *restrict node,
86 struct vlc_list *prev)
87{
89}
90
91/**
92 * Inserts an element before another.
93 *
94 * \param node [out] Node pointer of the element to insert.
95 * \param next Node pointer of the next element.
96 */
97static inline void vlc_list_add_before(struct vlc_list *restrict node,
98 struct vlc_list *next)
99{
101}
102
103/**
104 * Appends an element into a list.
105 *
106 * \param node [out] Node pointer of the element to append to the list.
107 * \param head Head pointer of the list to append the element to.
108 */
109static inline void vlc_list_append(struct vlc_list *restrict node,
110 struct vlc_list *head)
111{
112 vlc_list_add_before(node, head);
113}
114
115/**
116 * Prepends an element into a list.
117 *
118 * \param node [out] Node pointer of the element to prepend to the list.
119 * \param head Head pointer of the list to prepend the element to.
120 */
121static inline void vlc_list_prepend(struct vlc_list *restrict node,
122 struct vlc_list *head)
123{
124 vlc_list_add_after(node, head);
125}
126
127/**
128 * Removes an element from a list.
129 *
130 * \param node Node of the element to remove from a list.
131 * \warning The element must be inside a list.
132 * Otherwise the behaviour is undefined.
133 */
134static inline void vlc_list_remove(struct vlc_list *restrict node)
136 struct vlc_list *prev = node->prev;
137 struct vlc_list *next = node->next;
138
139 prev->next = next;
140 next->prev = prev;
141}
142
143/**
144 * Replaces an element with another one.
145 *
146 * \param original [in] Node pointer of the element to remove from the list.
147 * \param substitute [out] Node pointer of the replacement.
148 */
149static inline void vlc_list_replace(const struct vlc_list *original,
150 struct vlc_list *restrict substitute)
151{
152 vlc_list_add_between(substitute, original->prev, original->next);
153}
154
155/**
156 * Checks if a list is empty.
157 *
158 * \param head [in] Head of the list to be checked.
159 *
160 * \retval false The list is not empty.
161 * \retval true The list is empty.
162 *
163 * \note Obviously the list must have been initialized.
164 * Otherwise, the behaviour is undefined.
165 */
166static inline bool vlc_list_is_empty(const struct vlc_list *head)
168 return head->next == head;
169}
170
171/**
172 * Checks if an element is first in a list.
173 *
174 * \param node [in] List node of the element.
175 * \param head [in] Head of the list to be checked.
176 *
177 * \retval false The element is not first (or is in another list).
178 * \retval true The element is first.
179 */
180static inline bool vlc_list_is_first(const struct vlc_list *node,
181 const struct vlc_list *head)
182{
183 return node->prev == head;
184}
185
186/**
187 * Checks if an element is last in a list.
188 *
189 * \param node [in] List node of the element.
190 * \param head [in] Head of the list to be checked.
191 *
192 * \retval false The element is not last (or is in another list).
193 * \retval true The element is last.
194 */
195static inline bool vlc_list_is_last(const struct vlc_list *node,
196 const struct vlc_list *head)
197{
198 return node->next == head;
199}
200
201/**
202 * List iterator.
203 */
204struct vlc_list_it
206 const struct vlc_list *head;
208 struct vlc_list *next;
210
211static inline
214 struct vlc_list *first = head->next;
215
216 struct vlc_list_it it = { head, first, first->next };
217 return it;
218}
219
220static inline
223 struct vlc_list *first = head->next;
224
225 struct vlc_list_it it = { head, first, first->next };
226 return it;
227}
228
229static inline
232 struct vlc_list *first = head->prev;
233
234 struct vlc_list_it it = { head, first, first->prev };
235 return it;
236}
237
238static inline
241 struct vlc_list *first = head->prev;
242
243 struct vlc_list_it it = { head, first, first->prev };
244 return it;
245}
246
247static inline bool vlc_list_it_continue(const struct vlc_list_it *restrict it)
249 return it->current != it->head;
250}
251
252static inline void vlc_list_it_next(struct vlc_list_it *restrict it)
254 struct vlc_list *next = it->next;
255
256 it->current = next;
257 it->next = next->next;
258}
259
260static inline void vlc_list_it_prev(struct vlc_list_it *restrict it)
262 struct vlc_list *next = it->next;
263
264 it->current = next;
265 it->next = next->prev;
266}
267
268/**
269 * List iteration macro.
270 *
271 * This macro iterates over all elements (excluding the head) of a list,
272 * in order from the first to the last.
273 *
274 * For each iteration, it sets the cursor variable to the current element.
275 *
276 * \param pos Cursor pointer variable identifier.
277 * \param head [in] Head pointer of the list to iterate.
278 * \param member Identifier of the member of the data type
279 * serving as list node.
280 * \note It it safe to delete the current item while iterating.
281 * It is however <b>not</b> safe to delete another item.
282 */
283#define vlc_list_foreach(pos, head, member) \
284 for (struct vlc_list_it vlc_list_it__##pos = vlc_list_it_start(head); \
285 vlc_list_it_continue(&(vlc_list_it__##pos)) \
286 && ((pos) = container_of((vlc_list_it__##pos).current, \
287 typeof (*(pos)), member), true); \
288 vlc_list_it_next(&(vlc_list_it__##pos)))
289#define vlc_list_foreach_const(pos, head, member) \
290 for (struct vlc_list_it vlc_list_it__##pos = vlc_list_it_start_const(head); \
291 vlc_list_it_continue(&(vlc_list_it__##pos)) \
292 && ((pos) = container_of((vlc_list_it__##pos).current, \
293 const typeof (*(pos)), member), true); \
294 vlc_list_it_next(&(vlc_list_it__##pos)))
295
296/**
297 * List iteration macro.
298 *
299 * This macro iterates over all elements (excluding the head) of a list,
300 * in reversed order from the first to the last.
301 *
302 * For each iteration, it sets the cursor variable to the current element.
303 *
304 * \param pos Cursor pointer variable identifier.
305 * \param head [in] Head pointer of the list to iterate.
306 * \param member Identifier of the member of the data type
307 * serving as list node.
308 * \note It it safe to delete the current item while iterating.
309 * It is however <b>not</b> safe to delete another item.
310 */
311#define vlc_list_reverse_foreach(pos, head, member) \
312 for (struct vlc_list_it vlc_list_it_##pos = vlc_list_it_reverse_start(head); \
313 vlc_list_it_continue(&(vlc_list_it_##pos)) \
314 && ((pos) = container_of((vlc_list_it_##pos).current, \
315 typeof (*(pos)), member), true); \
316 vlc_list_it_prev(&(vlc_list_it_##pos)))
317
318/**
319 * Converts a list node pointer to an element pointer.
320 *
321 * \param ptr list node pointer
322 * \param type list data element type name
323 * \param member list node member within the data element compound type
324 */
325#define vlc_list_entry(ptr, type, member) container_of(ptr, type, member)
327static inline void *vlc_list_first_or_null(const struct vlc_list *head,
328 size_t offset)
329{
330 if (vlc_list_is_empty(head))
331 return NULL;
332 return ((char *)(head->next)) - offset;
333}
334
335static inline void *vlc_list_last_or_null(const struct vlc_list *head,
336 size_t offset)
337{
338 if (vlc_list_is_empty(head))
339 return NULL;
340 return ((char *)(head->prev)) - offset;
341}
342
343static inline void *vlc_list_prev_or_null(const struct vlc_list *head,
344 const struct vlc_list *node,
345 size_t offset)
346{
347 if (vlc_list_is_first(node, head))
348 return NULL;
349 return ((char *)(node->prev)) - offset;
350}
351
352static inline void *vlc_list_next_or_null(const struct vlc_list *head,
353 const struct vlc_list *node,
354 size_t offset)
355{
356 if (vlc_list_is_last(node, head))
357 return NULL;
358 return ((char *)(node->next)) - offset;
359}
360
361/**
362 * Gets the first element.
363 *
364 * \param head [in] Head of list whose last element to get.
365 *
366 * \return the first entry in a list or NULL if empty.
367 */
368#define vlc_list_first_entry_or_null(head, type, member) \
369 ((type *)vlc_list_first_or_null(head, offsetof (type, member)))
370
371/**
372 * Gets the last element.
373 *
374 * \param head [in] Head of list whose last element to get.
375 *
376 * \return the last entry in a list or NULL if empty.
377 */
378#define vlc_list_last_entry_or_null(head, type, member) \
379 ((type *)vlc_list_last_or_null(head, offsetof (type, member)))
380
381#define vlc_list_prev_entry_or_null(head, entry, type, member) \
382 ((type *)vlc_list_prev_or_null(head, &(entry)->member, \
383 offsetof (type, member)))
384#define vlc_list_next_entry_or_null(head, entry, type, member) \
385 ((type *)vlc_list_next_or_null(head, &(entry)->member, \
386 offsetof (type, member)))
387
388/** \todo Merging lists, splitting lists. */
389
390/** @} */
391
392#endif /* VLC_LIST_H */
static void vlc_list_it_prev(struct vlc_list_it *restrict it)
Definition vlc_list.h:261
static void * vlc_list_last_or_null(const struct vlc_list *head, size_t offset)
Definition vlc_list.h:336
static void vlc_list_append(struct vlc_list *restrict node, struct vlc_list *head)
Appends an element into a list.
Definition vlc_list.h:110
static void vlc_list_init(struct vlc_list *restrict head)
Initializes an empty list head.
Definition vlc_list.h:57
static void vlc_list_prepend(struct vlc_list *restrict node, struct vlc_list *head)
Prepends an element into a list.
Definition vlc_list.h:122
static bool vlc_list_is_last(const struct vlc_list *node, const struct vlc_list *head)
Checks if an element is last in a list.
Definition vlc_list.h:196
static struct vlc_list_it vlc_list_it_reverse_start(struct vlc_list *head)
Definition vlc_list.h:231
static bool vlc_list_is_first(const struct vlc_list *node, const struct vlc_list *head)
Checks if an element is first in a list.
Definition vlc_list.h:181
static void * vlc_list_first_or_null(const struct vlc_list *head, size_t offset)
Definition vlc_list.h:328
static struct vlc_list_it vlc_list_it_start(struct vlc_list *head)
Definition vlc_list.h:213
static struct vlc_list_it vlc_list_it_start_const(const struct vlc_list *head)
Definition vlc_list.h:222
static bool vlc_list_is_empty(const struct vlc_list *head)
Checks if a list is empty.
Definition vlc_list.h:167
static void * vlc_list_next_or_null(const struct vlc_list *head, const struct vlc_list *node, size_t offset)
Definition vlc_list.h:353
static void vlc_list_add_before(struct vlc_list *restrict node, struct vlc_list *next)
Inserts an element before another.
Definition vlc_list.h:98
static struct vlc_list_it vlc_list_it_reverse_start_const(const struct vlc_list *head)
Definition vlc_list.h:240
static void * vlc_list_prev_or_null(const struct vlc_list *head, const struct vlc_list *node, size_t offset)
Definition vlc_list.h:344
static void vlc_list_remove(struct vlc_list *restrict node)
Removes an element from a list.
Definition vlc_list.h:135
static bool vlc_list_it_continue(const struct vlc_list_it *restrict it)
Definition vlc_list.h:248
static void vlc_list_add_after(struct vlc_list *restrict node, struct vlc_list *prev)
Inserts an element after another.
Definition vlc_list.h:86
static void vlc_list_add_between(struct vlc_list *restrict node, struct vlc_list *prev, struct vlc_list *next)
Inserts an element in a list.
Definition vlc_list.h:70
static void vlc_list_it_next(struct vlc_list_it *restrict it)
Definition vlc_list.h:253
static void vlc_list_replace(const struct vlc_list *original, struct vlc_list *restrict substitute)
Replaces an element with another one.
Definition vlc_list.h:150
List iterator.
Definition vlc_list.h:206
const struct vlc_list * head
Definition vlc_list.h:207
struct vlc_list * next
Definition vlc_list.h:209
struct vlc_list * current
Definition vlc_list.h:208
Doubly-linked list node.
Definition vlc_list.h:44
struct vlc_list * prev
Definition vlc_list.h:45
struct vlc_list * next
Definition vlc_list.h:46
This file is a collection of common definitions and types.