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