Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_list.c
Go to the documentation of this file.
1
8#include "nilorea/n_common.h"
9#include <pthread.h>
10#include "nilorea/n_log.h"
11#include "nilorea/n_list.h"
12
18LIST* new_generic_list(size_t max_items) {
19 LIST* list = NULL;
20
21 Malloc(list, LIST, 1);
22 __n_assert(list, return NULL);
23
24 list->nb_max_items = max_items;
25 list->nb_items = 0;
26
27 list->start = list->end = NULL;
28
29 return list;
30} /* new_generic_list */
31
38LIST_NODE* new_list_node(void* ptr, void (*destructor)(void* ptr)) {
39 LIST_NODE* node = NULL;
40
41 Malloc(node, LIST_NODE, 1);
42 __n_assert(node, n_log(LOG_ERR, "Error allocating node for ptr %p", ptr); return NULL);
43
44 node->ptr = ptr;
45 node->destroy_func = destructor;
46 node->next = node->prev = NULL;
47
48 return node;
49} /* new_list_node(...) */
50
57void* remove_list_node_f(LIST* list, LIST_NODE* node) {
58 void* ptr = NULL;
59
60 __n_assert(list, n_log(LOG_ERR, "can't remove from NULL list"); return NULL);
61 __n_assert(list->start, n_log(LOG_ERR, "can't remove from NULL list->start"); return NULL);
62 __n_assert(list->end, n_log(LOG_ERR, "can't remove from NULL list->end"); return NULL);
63 __n_assert(node, n_log(LOG_ERR, "can't remove from NULL node"); return NULL);
64
65 ptr = node->ptr;
66 if (node->prev && node->next) {
67 node->prev->next = node->next;
68 node->next->prev = node->prev;
69 } else {
70 if (node->prev == NULL && node->next) {
71 node->next->prev = NULL;
72 list->start = node->next;
73 } else {
74 if (node->prev && node->next == NULL) {
75 node->prev->next = NULL;
76 list->end = node->prev;
77 } else {
78 if (node->prev == NULL && node->next == NULL) {
79 /* removing last item */
80 list->start = list->end = NULL;
81 }
82 }
83 }
84 }
85 Free(node);
86 list->nb_items--;
87 return ptr;
88} /* remove_list_node_f(...) */
89
96int list_node_push(LIST* list, LIST_NODE* node) {
97 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
98 __n_assert(node, n_log(LOG_ERR, "invalid node: NULL"); return FALSE);
99
100 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
101 n_log(LOG_ERR, "list is full");
102 return FALSE;
103 }
104 if (list->end) {
105 list->end->next = node;
106 node->prev = list->end;
107 list->end = node;
108 } else {
109 list->start = list->end = node;
110 }
111 list->nb_items++;
112 return TRUE;
113} /* list_node_push() */
114
121 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return NULL);
122
123 if (list->nb_items == 0 || list->end == NULL)
124 return NULL;
125
126 LIST_NODE* nodeptr = NULL;
127
128 nodeptr = list->end;
129 if (list->end->prev) {
130 list->end = list->end->prev;
131 list->end->next = NULL;
132 }
133 list->nb_items--;
134 if (list->nb_items == 0)
135 list->start = list->end = NULL;
136
137 return nodeptr;
138} /* list_node_pop() */
139
146 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return NULL);
147
148 if (list->nb_items == 0 || list->start == NULL)
149 return NULL;
150
151 LIST_NODE* nodeptr = NULL;
152 nodeptr = list->start;
153
154 if (list->start->next) {
155 list->start = list->start->next;
156 list->start->prev = NULL;
157 }
158
159 list->nb_items--;
160
161 if (list->nb_items == 0)
162 list->start = list->end = NULL;
163
164 return nodeptr;
165} /* list_node_shift() */
166
174 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
175 __n_assert(node, n_log(LOG_ERR, "invalid node: NULL"); return FALSE);
176
177 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
178 n_log(LOG_ERR, "list is full");
179 return FALSE;
180 }
181 if (list->start) {
182 link_node(node, list->start);
183 list->start = node;
184 } else {
185 list->start = list->end = node;
186 }
187 list->nb_items++;
188
189 return TRUE;
190} /* list_node_unshift() */
191
199int list_push(LIST* list, void* ptr, void (*destructor)(void* ptr)) {
200 LIST_NODE* node = NULL;
201
202 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
203 __n_assert(ptr, n_log(LOG_ERR, "invalid ptr: NULL"); return FALSE);
204
205 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
206 n_log(LOG_ERR, "list is full");
207 return FALSE;
208 }
209
210 node = new_list_node(ptr, destructor);
211 __n_assert(node, n_log(LOG_ERR, "Couldn't allocate new node"); return FALSE);
212
213 list->nb_items++;
214
215 if (list->end) {
216 list->end->next = node;
217 node->prev = list->end;
218 list->end = node;
219 } else {
220 list->start = list->end = node;
221 }
222 return TRUE;
223} /* list_push( ... ) */
224
233int list_push_sorted(LIST* list, void* ptr, int (*comparator)(const void* a, const void* b), void (*destructor)(void* ptr)) {
234 LIST_NODE* nodeptr = NULL;
235 int ret = TRUE;
236
237 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
238 __n_assert(ptr, n_log(LOG_ERR, "invalid ptr: NULL"); return FALSE);
239
240 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
241 n_log(LOG_ERR, "list is full");
242 return FALSE;
243 }
244
245 if (list->end) {
246 nodeptr = list->end;
247 while (nodeptr && (comparator(ptr, nodeptr->ptr) < 0))
248 nodeptr = nodeptr->prev;
249
250 if (!nodeptr) {
251 /* It's the lower ranked element in the sort */
252 ret = list_unshift(list, ptr, destructor);
253 if (ret == FALSE) {
254 n_log(LOG_ERR, "Couldn't list_unshift in list %p ptr %p with destructor %p", list, ptr, destructor);
255 return FALSE;
256 }
257 } else {
258 /* we have a match inside the list. let's insert the datas */
259 LIST_NODE* node_next = nodeptr->next;
260 LIST_NODE* newnode = new_list_node(ptr, destructor);
261 __n_assert(newnode, n_log(LOG_ERR, "Couldn't allocate new node"); return FALSE);
262
263 if (node_next) {
264 link_node(newnode, node_next);
265 } else
266 list->end = newnode;
267
268 link_node(nodeptr, newnode);
269 list->nb_items++;
270 }
271 } else {
272 ret = list_push(list, ptr, destructor);
273 if (ret == FALSE) {
274 n_log(LOG_ERR, "Couldn't list_push in list %p ptr %p with destructor %p", list, ptr, destructor);
275 return FALSE;
276 }
277 }
278 return ret;
279} /* list_push_sorted( ... ) */
280
288int list_unshift(LIST* list, void* ptr, void (*destructor)(void* ptr)) {
289 LIST_NODE* node = NULL;
290
291 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
292 __n_assert(ptr, n_log(LOG_ERR, "invalid ptr: NULL"); return FALSE);
293
294 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
295 n_log(LOG_ERR, "list is full");
296 return FALSE;
297 }
298 node = new_list_node(ptr, destructor);
299 __n_assert(node, n_log(LOG_ERR, "Couldn't allocate new node"); return FALSE);
300
301 list->nb_items++;
302
303 if (list->start) {
304 link_node(node, list->start);
305 list->start = node;
306 } else {
307 list->start = list->end = node;
308 }
309
310 return TRUE;
311} /* list_unshift_f(...) */
312
321int list_unshift_sorted(LIST* list, void* ptr, int (*comparator)(const void* a, const void* b), void (*destructor)(void* ptr)) {
322 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return FALSE);
323 __n_assert(ptr, n_log(LOG_ERR, "invalid ptr: NULL"); return FALSE);
324
325 LIST_NODE* nodeptr = NULL;
326 int ret = TRUE;
327
328 if (list->nb_max_items > 0 && (list->nb_items >= list->nb_max_items)) {
329 n_log(LOG_ERR, "list is full");
330 return FALSE;
331 }
332
333 if (list->start) {
334 nodeptr = list->start;
335 while (nodeptr && (comparator(ptr, nodeptr->ptr) > 0))
336 nodeptr = nodeptr->next;
337
338 if (!nodeptr) {
339 /* It's the higher ranked element in the sort */
340 ret = list_push(list, ptr, destructor);
341 if (ret == FALSE) {
342 n_log(LOG_ERR, "Couldn't list_push in list %p ptr %p with destructor %p", list, ptr, destructor);
343 return FALSE;
344 }
345 } else {
346 /* we have a match inside the list. let's insert the datas */
347 LIST_NODE* node_prev = nodeptr->prev;
348 LIST_NODE* newnode = new_list_node(ptr, destructor);
349 __n_assert(newnode, n_log(LOG_ERR, "Couldn't allocate new node"); return FALSE);
350
351 if (node_prev) {
352 link_node(node_prev, newnode);
353 } else
354 list->start = newnode;
355
356 link_node(newnode, nodeptr);
357 list->nb_items++;
358 }
359 } else {
360 ret = list_unshift(list, ptr, destructor);
361 if (ret == FALSE) {
362 n_log(LOG_ERR, "Couldn't list_unshift in list %p ptr %p with destructor %p", list, ptr, destructor);
363 return FALSE;
364 }
365 }
366 return ret;
367} /* list_unshift_sorted(...) */
368
374void* list_pop_f(LIST* list) {
375 LIST_NODE* nodeptr = NULL;
376 void* ptr = NULL;
377
378 __n_assert(list, n_log(LOG_ERR, "invalid list: NULL"); return NULL);
379
380 if (list->nb_items == 0 || list->end == NULL)
381 return NULL;
382
383 nodeptr = list->end;
384 ptr = nodeptr->ptr;
385
386 if (list->end->prev) {
387 list->end = list->end->prev;
388 list->end->next = NULL;
389 }
390
391 list->nb_items--;
392 if (list->nb_items == 0)
393 list->start = list->end = NULL;
394
395 Free(nodeptr);
396
397 return ptr;
398} /* list_pop_f( ... ) */
399
407void* list_shift_f(LIST* list, char* file, size_t line) {
408 LIST_NODE* nodeptr = NULL;
409 void* ptr = NULL;
410
411 __n_assert(list, n_log(LOG_ERR, "%s:%d: invalid list: NULL", file, line); return NULL);
412
413 if (list->nb_items == 0 || list->start == NULL)
414 return NULL;
415
416 nodeptr = list->start;
417 ptr = nodeptr->ptr;
418
419 if (list->start->next) {
420 list->start = list->start->next;
421 list->start->prev = NULL;
422 }
423
424 list->nb_items--;
425
426 if (list->nb_items == 0)
427 list->start = list->end = NULL;
428
429 Free(nodeptr);
430
431 return ptr;
432} /* list_shift_f(...)*/
433
440LIST_NODE* list_search(LIST* list, void* ptr) {
441 __n_assert(list, return NULL);
442
443 list_foreach(node, list) {
444 if (node->ptr == ptr)
445 return node;
446 }
447 return NULL;
448} /* list_search */
449
456LIST_NODE* list_search_with_f(LIST* list, int (*checkfunk)(void* ptr)) {
457 __n_assert(list, return NULL);
458
459 list_foreach(node, list) {
460 if (checkfunk(node->ptr))
461 return node;
462 }
463 return NULL;
464} /* list_search */
465
471int list_empty(LIST* list) {
472 LIST_NODE *node = NULL, *node_ptr = NULL;
473
474 __n_assert(list, n_log(LOG_ERR, "list is NULL"); return FALSE);
475
476 node = list->start;
477 while (node) {
478 node_ptr = node;
479 node = node->next;
480 if (node_ptr->destroy_func != NULL) {
481 node_ptr->destroy_func(node_ptr->ptr);
482 }
483 Free(node_ptr);
484 }
485 list->start = list->end = NULL;
486 list->nb_items = 0;
487 return TRUE;
488} /* list_empty( ... ) */
489
496int list_empty_with_f(LIST* list, void (*free_fnct)(void* ptr)) {
497 LIST_NODE *node = NULL, *node_ptr = NULL;
498
499 __n_assert(list, n_log(LOG_ERR, "list is NULL"); return FALSE);
500
501 node = list->start;
502 while (node) {
503 node_ptr = node;
504 node = node->next;
505 free_fnct(node_ptr->ptr);
506 Free(node_ptr);
507 }
508 list->start = list->end = NULL;
509 list->nb_items = 0;
510 return TRUE;
511} /* list_empty_with_f */
512
518int list_destroy(LIST** list) {
519 __n_assert(list && (*list), n_log(LOG_ERR, "list already destroyed"); return FALSE);
520 list_empty((*list));
521 Free((*list));
522 return TRUE;
523} /* free_list( ... ) */
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:187
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:258
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:242
LIST_NODE * end
pointer to the end of the list
Definition n_list.h:48
void * ptr
void pointer to store
Definition n_list.h:26
size_t nb_max_items
maximum number of item in the list.
Definition n_list.h:43
struct LIST_NODE * prev
pointer to the previous node
Definition n_list.h:34
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:46
size_t nb_items
number of item currently in the list
Definition n_list.h:41
void(* destroy_func)(void *ptr)
pointer to destructor function if any, else NULL
Definition n_list.h:29
struct LIST_NODE * next
pointer to the next node
Definition n_list.h:32
void * list_pop_f(LIST *list)
Get a pointer from the end of the list.
Definition n_list.c:374
void * list_shift_f(LIST *list, char *file, size_t line)
Get a pointer from the start of the list.
Definition n_list.c:407
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition n_list.c:471
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:199
int list_node_unshift(LIST *list, LIST_NODE *node)
Add a pointer at the start of the list.
Definition n_list.c:173
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
Definition n_list.h:65
int list_unshift(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer at the start of the list.
Definition n_list.c:288
LIST_NODE * list_node_shift(LIST *list)
Get a LIST_NODE pointer from the start of the list.
Definition n_list.c:145
LIST_NODE * new_list_node(void *ptr, void(*destructor)(void *ptr))
Allocate a new node to link in a list.
Definition n_list.c:38
#define link_node(__NODE_1, __NODE_2)
Macro helper for linking two nodes.
Definition n_list.h:58
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:518
int list_unshift_sorted(LIST *list, void *ptr, int(*comparator)(const void *a, const void *b), void(*destructor)(void *ptr))
Add a pointer sorted in the list , starting by the start of the list.
Definition n_list.c:321
LIST_NODE * list_node_pop(LIST *list)
Get a LIST_NODE pointer from the end of the list.
Definition n_list.c:120
void * remove_list_node_f(LIST *list, LIST_NODE *node)
Internal function called each time we need to get a node out of a list.
Definition n_list.c:57
LIST_NODE * list_search(LIST *list, void *ptr)
search ptr in list
Definition n_list.c:440
int list_push_sorted(LIST *list, void *ptr, int(*comparator)(const void *a, const void *b), void(*destructor)(void *ptr))
Add a pointer sorted in the list , starting by the end of the list.
Definition n_list.c:233
int list_empty_with_f(LIST *list, void(*free_fnct)(void *ptr))
Empty a LIST list of pointers.
Definition n_list.c:496
LIST_NODE * list_search_with_f(LIST *list, int(*checkfunk)(void *ptr))
search ptr in list
Definition n_list.c:456
int list_node_push(LIST *list, LIST_NODE *node)
Add a filled node to the end of the list.
Definition n_list.c:96
Structure of a generic LIST container.
Definition n_list.h:39
Structure of a generic list node.
Definition n_list.h:24
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:69
#define LOG_ERR
error conditions
Definition n_log.h:56
Common headers and low-level functions & define.
List structures and definitions.
Generic log system.