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