Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
lists.c
Go to the documentation of this file.
1
8#if !defined(HAVE_ETH2) && !defined(USE_LIB_ETHEREUM) || defined(HAVE_SDK_LL_LIB)
9
10#include "lists.h"
11#include "os_helpers.h"
12
13// ============================================================================
14// Internal shared functions with strict validation
15// ============================================================================
16
17static bool push_front_internal(flist_node_t **list, flist_node_t *node, bool doubly_linked)
18{
19 if ((list == NULL) || (node == NULL)) {
20 return false;
21 }
22 node->next = *list;
23 *list = node;
24 if (doubly_linked) {
25 if (node->next != NULL) {
26 ((list_node_t *) node->next)->prev = (list_node_t *) node;
27 }
28 ((list_node_t *) node)->prev = NULL;
29 }
30 return true;
31}
32
33static bool pop_front_internal(flist_node_t **list, f_list_node_del del_func, bool doubly_linked)
34{
35 flist_node_t *tmp;
36
37 if ((list == NULL) || (*list == NULL)) {
38 return false;
39 }
40 tmp = *list;
41 *list = tmp->next;
42 if (del_func != NULL) {
43 del_func(tmp);
44 }
45 if (doubly_linked) {
46 if (*list != NULL) {
47 (*(list_node_t **) list)->prev = NULL;
48 }
49 }
50 return true;
51}
52
53static bool push_back_internal(flist_node_t **list, flist_node_t *node, bool doubly_linked)
54{
55 flist_node_t *tmp;
56
57 if ((list == NULL) || (node == NULL)) {
58 return false;
59 }
60 node->next = NULL;
61 if (*list == NULL) {
62 if (doubly_linked) {
63 ((list_node_t *) node)->prev = NULL;
64 }
65 *list = node;
66 }
67 else {
68 tmp = *list;
69 while (tmp->next != NULL) {
70 tmp = tmp->next;
71 }
72 if (doubly_linked) {
73 ((list_node_t *) node)->prev = (list_node_t *) tmp;
74 }
75 tmp->next = node;
76 }
77 return true;
78}
79
80static bool insert_after_internal(flist_node_t *ref, flist_node_t *node, bool doubly_linked)
81{
82 if ((ref == NULL) || (node == NULL)) {
83 return false;
84 }
85 if (doubly_linked) {
86 if (ref->next != NULL) {
87 ((list_node_t *) (ref->next))->prev = (list_node_t *) node;
88 }
89 ((list_node_t *) node)->prev = (list_node_t *) ref;
90 }
91 node->next = ref->next;
92 ref->next = node;
93 return true;
94}
95
96static bool remove_internal(flist_node_t **list,
97 flist_node_t *node,
98 f_list_node_del del_func,
99 bool doubly_linked)
100{
101 flist_node_t *it;
102 flist_node_t *tmp;
103
104 if ((list == NULL) || (node == NULL) || (*list == NULL)) {
105 return false;
106 }
107 if (node == *list) {
108 // first element
109 return pop_front_internal(list, del_func, doubly_linked);
110 }
111 it = *list;
112 while ((it->next != node) && (it->next != NULL)) {
113 it = it->next;
114 }
115 if (it->next == NULL) {
116 // node not found
117 return false;
118 }
119 tmp = it->next->next;
120 if (doubly_linked) {
121 if (tmp != NULL) {
122 ((list_node_t *) tmp)->prev = ((list_node_t *) node)->prev;
123 }
124 }
125 if (del_func != NULL) {
126 del_func(it->next);
127 }
128 it->next = tmp;
129 return true;
130}
131
132static size_t remove_if_internal(flist_node_t **list,
133 f_list_node_pred pred_func,
134 f_list_node_del del_func,
135 bool doubly_linked)
136{
137 flist_node_t *node;
138 flist_node_t *tmp;
139 size_t count = 0;
140
141 if ((list == NULL) || (pred_func == NULL)) {
142 return 0;
143 }
144 node = *list;
145 while (node != NULL) {
146 tmp = node->next;
147 if (pred_func(node)) {
148 if (remove_internal(list, node, del_func, doubly_linked)) {
149 count += 1;
150 }
151 }
152 node = tmp;
153 }
154 return count;
155}
156
157static bool sort_internal(flist_node_t **list, f_list_node_cmp cmp_func, bool doubly_linked)
158{
159 flist_node_t **tmp;
160 flist_node_t *a, *b;
161 bool sorted;
162
163 if ((list == NULL) || (cmp_func == NULL)) {
164 return false;
165 }
166 do {
167 sorted = true;
168 for (tmp = list; (*tmp != NULL) && ((*tmp)->next != NULL); tmp = &(*tmp)->next) {
169 a = *tmp;
170 b = a->next;
171 if (cmp_func(a, b) == false) {
172 *tmp = b;
173 a->next = b->next;
174 b->next = a;
175 if (doubly_linked) {
176 ((list_node_t *) b)->prev = ((list_node_t *) a)->prev;
177 ((list_node_t *) a)->prev = (list_node_t *) b;
178 if (a->next != NULL) {
179 ((list_node_t *) a->next)->prev = (list_node_t *) a;
180 }
181 }
182 sorted = false;
183 }
184 }
185 } while (!sorted);
186 return true;
187}
188
189static size_t unique_internal(flist_node_t **list,
190 f_list_node_bin_pred pred_func,
191 f_list_node_del del_func,
192 bool doubly_linked)
193{
194 size_t count = 0;
195
196 if ((list == NULL) || (pred_func == NULL)) {
197 return 0;
198 }
199 for (flist_node_t *ref = *list; ref != NULL; ref = ref->next) {
200 flist_node_t *node = ref->next;
201 while ((node != NULL) && (pred_func(ref, node))) {
202 flist_node_t *tmp = node->next;
203 if (remove_internal(list, node, del_func, doubly_linked)) {
204 count += 1;
205 }
206 node = tmp;
207 }
208 }
209 return count;
210}
211
212static bool reverse_internal(flist_node_t **list, bool doubly_linked)
213{
214 flist_node_t *node;
215 flist_node_t *prev = NULL;
216 flist_node_t *next;
217
218 if (list == NULL) {
219 return false;
220 }
221 node = *list;
222 while (node != NULL) {
223 next = node->next;
224 node->next = prev;
225 if (doubly_linked) {
226 ((list_node_t *) node)->prev = (list_node_t *) next;
227 }
228 *list = node;
229 prev = node;
230 node = next;
231 }
232 return true;
233}
234
235// ============================================================================
236// Forward list (singly-linked) functions
237// ============================================================================
238
240{
241 return push_front_internal(list, node, false);
242}
243
245{
246 return pop_front_internal(list, del_func, false);
247}
248
250{
251 return push_back_internal(list, node, false);
252}
253
255{
256 flist_node_t *tmp;
257
258 if ((list == NULL) || (*list == NULL)) {
259 return false;
260 }
261 tmp = *list;
262 // only one element
263 if (tmp->next == NULL) {
264 return flist_pop_front(list, del_func);
265 }
266 while (tmp->next->next != NULL) {
267 tmp = tmp->next;
268 }
269 if (del_func != NULL) {
270 del_func(tmp->next);
271 }
272 tmp->next = NULL;
273 return true;
274}
275
277{
278 UNUSED(list);
279 return insert_after_internal(ref, node, false);
280}
281
283{
284 return remove_internal(list, node, del_func, false);
285}
286
288{
289 return remove_if_internal(list, pred_func, del_func, false);
290}
291
293{
294 flist_node_t *tmp;
295 flist_node_t *next;
296
297 if (list == NULL) {
298 return false;
299 }
300 tmp = *list;
301 while (tmp != NULL) {
302 next = tmp->next;
303 if (del_func != NULL) {
304 del_func(tmp);
305 }
306 tmp = next;
307 }
308 *list = NULL;
309 return true;
310}
311
312size_t flist_size(flist_node_t *const *list)
313{
314 size_t size = 0;
315
316 if (list != NULL) {
317 for (flist_node_t *tmp = *list; tmp != NULL; tmp = tmp->next) {
318 size += 1;
319 }
320 }
321 return size;
322}
323
324bool flist_empty(flist_node_t *const *list)
325{
326 return flist_size(list) == 0;
327}
328
330{
331 return sort_internal(list, cmp_func, false);
332}
333
335{
336 return unique_internal(list, pred_func, del_func, false);
337}
338
340{
341 return reverse_internal(list, false);
342}
343
344// ============================================================================
345// Doubly-linked list functions
346// ============================================================================
347
349{
350 return push_front_internal((flist_node_t **) list, (flist_node_t *) node, true);
351}
352
354{
355 return pop_front_internal((flist_node_t **) list, del_func, true);
356}
357
359{
360 return push_back_internal((flist_node_t **) list, (flist_node_t *) node, true);
361}
362
364{
365 return flist_pop_back((flist_node_t **) list, del_func);
366}
367
369{
370 if ((ref == NULL) || (node == NULL)) {
371 return false;
372 }
373 if (ref->prev == NULL) {
374 if ((list != NULL) && (*list == ref)) {
375 return list_push_front(list, node);
376 }
377 return false;
378 }
379 return list_insert_after(list, ref->prev, node);
380}
381
383{
384 UNUSED(list);
385 return insert_after_internal((flist_node_t *) ref, (flist_node_t *) node, true);
386}
387
389{
390 return remove_internal((flist_node_t **) list, (flist_node_t *) node, del_func, true);
391}
392
394{
395 return remove_if_internal((flist_node_t **) list, pred_func, del_func, true);
396}
397
399{
400 return flist_clear((flist_node_t **) list, del_func);
401}
402
403size_t list_size(list_node_t *const *list)
404{
405 return flist_size((flist_node_t **) list);
406}
407
408bool list_empty(list_node_t *const *list)
409{
410 return list_size(list) == 0;
411}
412
414{
415 return sort_internal((flist_node_t **) list, cmp_func, true);
416}
417
419{
420 return unique_internal((flist_node_t **) list, pred_func, del_func, true);
421}
422
424{
425 return reverse_internal((flist_node_t **) list, true);
426}
427
428#endif // !defined(HAVE_ETH2) || defined(HAVE_SDK_LL_LIB)
bool list_push_back(list_node_t **list, list_node_t *node)
Add a node at the end of the doubly-linked list.
Definition lists.c:358
bool flist_sort(flist_node_t **list, f_list_node_cmp cmp_func)
Sort the forward list using a comparison function.
Definition lists.c:329
bool flist_reverse(flist_node_t **list)
Reverse the order of nodes in the forward list.
Definition lists.c:339
bool list_remove(list_node_t **list, list_node_t *node, f_list_node_del del_func)
Remove and delete a specific node from the doubly-linked list.
Definition lists.c:388
size_t flist_remove_if(flist_node_t **list, f_list_node_pred pred_func, f_list_node_del del_func)
Remove all nodes matching a predicate from the forward list.
Definition lists.c:287
bool flist_push_back(flist_node_t **list, flist_node_t *node)
Add a node at the end of the forward list.
Definition lists.c:249
bool flist_pop_front(flist_node_t **list, f_list_node_del del_func)
Remove and delete the first node from the forward list.
Definition lists.c:244
size_t flist_size(flist_node_t *const *list)
Get the number of nodes in the forward list.
Definition lists.c:312
bool list_clear(list_node_t **list, f_list_node_del del_func)
Remove and delete all nodes from the doubly-linked list.
Definition lists.c:398
bool list_sort(list_node_t **list, f_list_node_cmp cmp_func)
Sort the doubly-linked list using a comparison function.
Definition lists.c:413
bool list_pop_front(list_node_t **list, f_list_node_del del_func)
Remove and delete the first node from the doubly-linked list.
Definition lists.c:353
bool list_pop_back(list_node_t **list, f_list_node_del del_func)
Remove and delete the last node from the doubly-linked list.
Definition lists.c:363
bool list_empty(list_node_t *const *list)
Check if the doubly-linked list is empty.
Definition lists.c:408
bool flist_insert_after(flist_node_t **list, flist_node_t *ref, flist_node_t *node)
Insert a node after a reference node in the forward list.
Definition lists.c:276
bool flist_remove(flist_node_t **list, flist_node_t *node, f_list_node_del del_func)
Remove and delete a specific node from the forward list.
Definition lists.c:282
size_t list_size(list_node_t *const *list)
Get the number of nodes in the doubly-linked list.
Definition lists.c:403
bool list_insert_before(list_node_t **list, list_node_t *ref, list_node_t *node)
Insert a node before a reference node in the doubly-linked list.
Definition lists.c:368
size_t flist_unique(flist_node_t **list, f_list_node_bin_pred pred_func, f_list_node_del del_func)
Remove consecutive duplicate nodes from the forward list.
Definition lists.c:334
bool flist_empty(flist_node_t *const *list)
Check if the forward list is empty.
Definition lists.c:324
bool list_reverse(list_node_t **list)
Reverse the order of nodes in the doubly-linked list.
Definition lists.c:423
size_t list_unique(list_node_t **list, f_list_node_bin_pred pred_func, f_list_node_del del_func)
Remove consecutive duplicate nodes from the doubly-linked list.
Definition lists.c:418
bool list_push_front(list_node_t **list, list_node_t *node)
Add a node at the beginning of the doubly-linked list.
Definition lists.c:348
bool flist_push_front(flist_node_t **list, flist_node_t *node)
Add a node at the beginning of the forward list.
Definition lists.c:239
size_t list_remove_if(list_node_t **list, f_list_node_pred pred_func, f_list_node_del del_func)
Remove all nodes matching a predicate from the doubly-linked list.
Definition lists.c:393
bool flist_clear(flist_node_t **list, f_list_node_del del_func)
Remove and delete all nodes from the forward list.
Definition lists.c:292
bool flist_pop_back(flist_node_t **list, f_list_node_del del_func)
Remove and delete the last node from the forward list.
Definition lists.c:254
bool list_insert_after(list_node_t **list, list_node_t *ref, list_node_t *node)
Insert a node after a reference node in the doubly-linked list.
Definition lists.c:382
Generic linked list implementation (singly and doubly-linked)
bool(* f_list_node_cmp)(const flist_node_t *a, const flist_node_t *b)
Callback function to compare two nodes for sorting.
Definition lists.h:72
bool(* f_list_node_bin_pred)(const flist_node_t *a, const flist_node_t *b)
Callback function to test two nodes for equality (binary predicate)
Definition lists.h:102
void(* f_list_node_del)(flist_node_t *node)
Callback function to delete/free a node.
Definition lists.h:56
bool(* f_list_node_pred)(const flist_node_t *node)
Callback function to test a single node (unary predicate)
Definition lists.h:86
Forward list node structure (singly-linked)
Definition lists.h:24
struct flist_node_t * next
Definition lists.h:25
Doubly-linked list node structure.
Definition lists.h:39
struct list_node_t * prev
Definition lists.h:41