My Kernel v0.1.0
linked_list.h
Go to the documentation of this file.
1#pragma once
2
18#include <kernel/types.h>
19
20#include <utils/container_of.h>
21#include <utils/compiler.h>
22
27typedef struct linked_list_node {
30} node_t;
31
43typedef struct linked_list_head {
44 struct linked_list_node head;
45} llist_t;
46
48#define __LLIST_INIT(_head) \
49 { \
50 { \
51 _head, _head \
52 } \
53 }
54#define LLIST_INIT(_list) ((llist_t)__LLIST_INIT(&(_list).head))
55
57#define __INIT_LLIST(_name) _name = __LLIST_INIT(_name)
58#define INIT_LLIST(_name) _name = LLIST_INIT(_name)
59
61#define DECLARE_LLIST(_name) llist_t INIT_LLIST(_name)
62
64#define LLIST_NODE(_name) node_t _name
65
71#define FOREACH_LLIST(_name, _list) \
72 for (node_t *_name = llist_first(_list); _name != llist_head(_list); \
73 _name = llist_next(_name))
74
84#define FOREACH_LLIST_SAFE(_name, _tmp, _list) \
85 for (node_t *_name = llist_first(_list), *_tmp = llist_next(_name); \
86 _name != llist_head(_list); _name = _tmp, _tmp = llist_next(_tmp))
87
93#define FOREACH_LLIST_REVERSE(_name, _list) \
94 for (node_t *_name = llist_last(_list); _name != llist_head(_list); \
95 _name = llist_prev(_name))
96
106#define FOREACH_LLIST_SAFE_REVERSE(_name, _tmp, _list) \
107 for (node_t *_name = llist_last(_list), *_tmp = llist_prev(_name); \
108 _name != llist_head(_list); _name = _tmp, _tmp = llist_prev(_tmp))
109
116#define FOREACH_LLIST_ENTRY(_entry, _list, _field) \
117 for (_entry = llist_entry(llist_first(_list), typeof(*_entry), _field); \
118 &_entry->_field != llist_head(_list); \
119 _entry = llist_entry(llist_next(&_entry->_field), typeof(*_entry), \
120 _field))
121
129#define FOREACH_LLIST_ENTRY_SAFE(_entry, _tmp, _list, _field) \
130 for (_entry = llist_entry(llist_first(_list), typeof(*_entry), _field), \
131 _tmp = \
132 llist_entry(llist_next(&_entry->_field), typeof(*_tmp), _field); \
133 &_entry->_field != llist_head(_list); \
134 _entry = _tmp, _tmp = llist_entry(llist_next(&_tmp->_field), \
135 typeof(*_entry), _field))
136
143#define FOREACH_LLIST_ENTRY_REVERSE(_entry, _list, _field) \
144 for (_entry = llist_entry(llist_last(_list), typeof(*_entry), _field); \
145 &_entry->_field != llist_head(_list); \
146 _entry = llist_entry(llist_prev(&_entry->_field), typeof(*_entry), \
147 _field))
148
156#define FOREACH_LLIST_ENTRY_REVERSE_SAFE(_entry, _tmp, _list, _field) \
157 for (_entry = llist_entry(llist_last(_list), typeof(*_entry), _field), \
158 _tmp = \
159 llist_entry(llist_prev(&_entry->_field), typeof(*_tmp), _field); \
160 &_entry->_field != llist_head(_list); \
161 _entry = _tmp, _tmp = llist_entry(llist_prev(&_tmp->_field), \
162 typeof(*_entry), _field))
163
165#define llist_head(_list) (&(_list)->head)
166
168static inline node_t *llist_first(const llist_t *list)
169{
170 return llist_head(list)->next;
171}
172
174static inline node_t *llist_last(const llist_t *list)
175{
176 return llist_head(list)->prev;
177}
178
179/***/
180static inline node_t *llist_next(const node_t *entry)
181{
182 return entry->next;
183}
184
185/***/
186static inline node_t *llist_prev(const node_t *entry)
187{
188 return entry->prev;
189}
190
194#define llist_entry(ptr, type, member) container_of(ptr, type, member)
195
197static PURE inline bool llist_is_empty(const llist_t *list)
198{
199 return llist_first(list) == llist_head(list);
200}
201
203static inline void __llist_add(node_t *new, node_t *prev, node_t *next)
204{
205 next->prev = new;
206 new->next = next;
207 new->prev = prev;
208 prev->next = new;
209}
210
216static inline void __list_remove(node_t *prev, node_t *next)
217{
218 next->prev = prev;
219 prev->next = next;
220}
221
227static inline void llist_add_after(node_t *prev, node_t *new)
228{
229 __llist_add(new, prev, prev->next);
230}
231
237static inline void llist_add_before(node_t *next, node_t *new)
238{
239 __llist_add(new, next->prev, next);
240}
241
247static inline void llist_add(llist_t *list, node_t *new)
248{
249 llist_add_after(llist_head(list), new);
250}
251
257static inline void llist_add_tail(llist_t *list, node_t *new)
258{
259 llist_add_after(llist_last(list), new);
260}
261
267static inline node_t *llist_remove(node_t *node)
268{
269 __list_remove(node->prev, node->next);
270 return node;
271}
272
278static inline node_t *llist_pop(llist_t *list)
279{
280 if (llist_is_empty(list))
281 return NULL;
282
283 return llist_remove(llist_first(list));
284}
285
291static inline node_t *llist_pop_tail(llist_t *list)
292{
293 if (llist_is_empty(list))
294 return NULL;
295
296 return llist_remove(llist_last(list));
297}
298
306static inline void
307llist_insert_sorted(llist_t *list, node_t *new, compare_t compare)
308{
309 node_t *node = llist_first(list);
310
311 while (node != llist_head(list)) {
312 if (compare(new, node) <= 0)
313 break;
314 node = llist_next(node);
315 }
316
317 llist_add_before(node, new);
318}
319
331static inline bool
332llist_insert_sorted_unique(llist_t *list, node_t *new, compare_t compare)
333{
334 node_t *node = llist_first(list);
335 int ret;
336
337 while (node != llist_head(list)) {
338 ret = compare(new, node);
339 if (ret == 0)
340 return false;
341 if (ret < 0)
342 break;
343 node = llist_next(node);
344 }
345
346 llist_add_before(node, new);
347
348 return true;
349}
350
360static inline node_t *
361llist_find_first(const llist_t *list, const void *data, compare_t compare)
362{
363 FOREACH_LLIST (node, list) {
364 if (!compare(node, data))
365 return node;
366 }
367
368 return NULL;
369}
static node_t * llist_first(const llist_t *list)
Definition: linked_list.h:168
static void llist_add_tail(llist_t *list, node_t *new)
Insert a new entry as the last element of the list.
Definition: linked_list.h:257
struct linked_list_node * next
Next item in the list.
Definition: linked_list.h:28
static node_t * llist_find_first(const llist_t *list, const void *data, compare_t compare)
Retreive the first matching element inside the list (or NULL)
Definition: linked_list.h:361
static node_t * llist_pop_tail(llist_t *list)
Pop the last element in a list.
Definition: linked_list.h:291
static node_t * llist_last(const llist_t *list)
Definition: linked_list.h:174
#define llist_head(_list)
Definition: linked_list.h:165
#define FOREACH_LLIST(_name, _list)
Loop over each element inside a linked list.
Definition: linked_list.h:71
static void llist_add_before(node_t *next, node_t *new)
Insert a new entry into a list.
Definition: linked_list.h:237
static void llist_insert_sorted(llist_t *list, node_t *new, compare_t compare)
Insert a new item inside a sorted list in ascending order.
Definition: linked_list.h:307
static void llist_add_after(node_t *prev, node_t *new)
Insert a new entry into a list.
Definition: linked_list.h:227
static node_t * llist_remove(node_t *node)
Remove an entry from a list.
Definition: linked_list.h:267
static void __list_remove(node_t *prev, node_t *next)
Delete a list entry (internal use only).
Definition: linked_list.h:216
struct linked_list_node * prev
Previous item in the list.
Definition: linked_list.h:29
static PURE bool llist_is_empty(const llist_t *list)
Definition: linked_list.h:197
static node_t * llist_pop(llist_t *list)
Pop the first element in a list.
Definition: linked_list.h:278
static void __llist_add(node_t *new, node_t *prev, node_t *next)
Insert a new entry between two known consecutive ones (internal use only)
Definition: linked_list.h:203
static bool llist_insert_sorted_unique(llist_t *list, node_t *new, compare_t compare)
Insert a new item inside a sorted list in ascending order.
Definition: linked_list.h:332
static void llist_add(llist_t *list, node_t *new)
Insert a new entry as the first element of the list.
Definition: linked_list.h:247
The head of a doubly linked list.
Definition: linked_list.h:43
Intrusive doubly-linked list node.
Definition: linked_list.h:27