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 node->next = node;
271 node->prev = node;
272 return node;
273}
274
280static inline node_t *llist_pop(llist_t *list)
281{
282 if (llist_is_empty(list))
283 return NULL;
284
285 return llist_remove(llist_first(list));
286}
287
293static inline node_t *llist_pop_tail(llist_t *list)
294{
295 if (llist_is_empty(list))
296 return NULL;
297
298 return llist_remove(llist_last(list));
299}
300
308static inline void
309llist_insert_sorted(llist_t *list, node_t *new, compare_t compare)
310{
311 node_t *node = llist_first(list);
312
313 while (node != llist_head(list)) {
314 if (compare(new, node) <= 0)
315 break;
316 node = llist_next(node);
317 }
318
319 llist_add_before(node, new);
320}
321
333static inline bool
334llist_insert_sorted_unique(llist_t *list, node_t *new, compare_t compare)
335{
336 node_t *node = llist_first(list);
337 int ret;
338
339 while (node != llist_head(list)) {
340 ret = compare(new, node);
341 if (ret == 0)
342 return false;
343 if (ret < 0)
344 break;
345 node = llist_next(node);
346 }
347
348 llist_add_before(node, new);
349
350 return true;
351}
352
362static inline node_t *
363llist_find_first(const llist_t *list, const void *data, compare_t compare)
364{
365 FOREACH_LLIST (node, list) {
366 if (!compare(node, data))
367 return node;
368 }
369
370 return NULL;
371}
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:363
static node_t * llist_pop_tail(llist_t *list)
Pop the last element in a list.
Definition: linked_list.h:293
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:309
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:280
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:334
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