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
196#define llist_first_entry(list, type, member) \
197 llist_entry(llist_first(list), type, member)
198
199#define llist_last_entry(list, type, member) \
200 llist_entry(llist_last(list), type, member)
201
203static PURE inline bool llist_is_empty(const llist_t *list)
204{
205 return llist_first(list) == llist_head(list);
206}
207
209static inline void __llist_add(node_t *new, node_t *prev, node_t *next)
210{
211 next->prev = new;
212 new->next = next;
213 new->prev = prev;
214 prev->next = new;
215}
216
222static inline void __list_remove(node_t *prev, node_t *next)
223{
224 next->prev = prev;
225 prev->next = next;
226}
227
233static inline void llist_add_after(node_t *prev, node_t *new)
234{
235 __llist_add(new, prev, prev->next);
236}
237
243static inline void llist_add_before(node_t *next, node_t *new)
244{
245 __llist_add(new, next->prev, next);
246}
247
253static inline void llist_add(llist_t *list, node_t *new)
254{
255 llist_add_after(llist_head(list), new);
256}
257
263static inline void llist_add_tail(llist_t *list, node_t *new)
264{
265 llist_add_after(llist_last(list), new);
266}
267
273static inline node_t *llist_remove(node_t *node)
274{
275 __list_remove(node->prev, node->next);
276 node->next = node;
277 node->prev = node;
278 return node;
279}
280
286static inline node_t *llist_pop(llist_t *list)
287{
288 if (llist_is_empty(list))
289 return NULL;
290
291 return llist_remove(llist_first(list));
292}
293
299static inline node_t *llist_pop_tail(llist_t *list)
300{
301 if (llist_is_empty(list))
302 return NULL;
303
304 return llist_remove(llist_last(list));
305}
306
314static inline void
315llist_insert_sorted(llist_t *list, node_t *new, compare_t compare)
316{
317 node_t *node = llist_first(list);
318
319 while (node != llist_head(list)) {
320 if (compare(new, node) <= 0)
321 break;
322 node = llist_next(node);
323 }
324
325 llist_add_before(node, new);
326}
327
339static inline bool
340llist_insert_sorted_unique(llist_t *list, node_t *new, compare_t compare)
341{
342 node_t *node = llist_first(list);
343 int ret;
344
345 while (node != llist_head(list)) {
346 ret = compare(new, node);
347 if (ret == 0)
348 return false;
349 if (ret < 0)
350 break;
351 node = llist_next(node);
352 }
353
354 llist_add_before(node, new);
355
356 return true;
357}
358
368static inline node_t *
369llist_find_first(const llist_t *list, const void *data, compare_t compare)
370{
371 FOREACH_LLIST (node, list) {
372 if (!compare(node, data))
373 return node;
374 }
375
376 return NULL;
377}
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:263
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:369
static node_t * llist_pop_tail(llist_t *list)
Pop the last element in a list.
Definition: linked_list.h:299
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:243
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:315
static void llist_add_after(node_t *prev, node_t *new)
Insert a new entry into a list.
Definition: linked_list.h:233
static node_t * llist_remove(node_t *node)
Remove an entry from a list.
Definition: linked_list.h:273
static void __list_remove(node_t *prev, node_t *next)
Delete a list entry (internal use only).
Definition: linked_list.h:222
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:203
static node_t * llist_pop(llist_t *list)
Pop the first element in a list.
Definition: linked_list.h:286
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:209
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:340
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:253
The head of a doubly linked list.
Definition: linked_list.h:43
Intrusive doubly-linked list node.
Definition: linked_list.h:27