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
13
14
20LIST *new_generic_list( int max_items )
21{
22 LIST *list = NULL ;
23
24 Malloc( list, LIST, 1 );
25 __n_assert( list, return NULL );
26
27 if( max_items <= 0 )
28 list -> nb_max_items = 0 ;
29 else
30 list -> nb_max_items = max_items ;
31
32 list -> nb_items = 0 ;
33 list -> start = list -> end = NULL ;
34
35 return list ;
36} /* new_generic_list */
37
38
39
46LIST_NODE *new_list_node( void *ptr, void (*destructor)( void *ptr ) )
47{
48 LIST_NODE *node = NULL ;
49
50 Malloc( node, LIST_NODE, 1 );
51 __n_assert( node, n_log( LOG_ERR, "Error allocating node for ptr %p", ptr ); return NULL );
52
53 node -> ptr = ptr ;
54 node -> destroy_func = destructor ;
55 node -> next = node -> prev = NULL ;
56
57 return node ;
58} /* new_list_node(...) */
59
60
61
68void *remove_list_node_f( LIST *list, LIST_NODE *node )
69{
70 void *ptr = NULL ;
71
72 __n_assert( list, n_log( LOG_ERR, "can't remove from NULL list" ); return NULL );
73 __n_assert( list->start, n_log( LOG_ERR, "can't remove from NULL list->start" ); return NULL );
74 __n_assert( list->end, n_log( LOG_ERR, "can't remove from NULL list->end" ); return NULL );
75 __n_assert( node, n_log( LOG_ERR, "can't remove from NULL node" ); return NULL );
76
77 ptr = node -> ptr ;
78 if( node -> prev && node -> next )
79 {
80 node -> prev -> next = node -> next ;
81 node -> next -> prev = node -> prev ;
82 }
83 else
84 {
85 if( node -> prev == NULL && node -> next )
86 {
87 node -> next -> prev = NULL ;
88 list -> start = node -> next ;
89 }
90 else
91 {
92 if( node -> prev && node -> next == NULL )
93 {
94 node -> prev -> next = NULL ;
95 list -> end = node -> prev ;
96 }
97 else
98 {
99 if( node -> prev == NULL && node -> next == NULL )
100 {
101 /* removing last item */
102 list -> start = list -> end = NULL ;
103 }
104 }
105 }
106 }
107 Free( node );
108 list -> nb_items -- ;
109 return ptr ;
110} /* remove_list_node_f(...) */
111
112
113
120int list_node_push( LIST *list, LIST_NODE *node )
121{
122 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
123
124 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
125 {
126 n_log( LOG_ERR, "list is full" );
127 return FALSE ;
128 }
129 if( list -> end )
130 {
131 list -> end -> next = node ;
132 node -> prev = list -> end ;
133 list -> end = node ;
134 }
135 else
136 {
137 list -> start = list -> end = node ;
138 }
139 list -> nb_items ++ ;
140 return TRUE ;
141} /* list_node_push() */
142
143
144
151{
152 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return NULL );
153
154 if( list -> nb_items == 0 || list -> end == NULL )
155 return NULL ;
156
157 LIST_NODE *nodeptr = NULL ;
158
159 nodeptr = list -> end ;
160 if( list -> end -> prev )
161 {
162 list -> end = list -> end -> prev ;
163 list -> end -> next = NULL ;
164 }
165 list -> nb_items -- ;
166 if( list -> nb_items == 0 )
167 list -> start = list -> end = NULL ;
168
169 return nodeptr ;
170} /* list_node_pop() */
171
172
173
180{
181 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return NULL );
182
183 if( list -> nb_items == 0 || list -> start == NULL )
184 return NULL ;
185
186 LIST_NODE *nodeptr = NULL ;
187 nodeptr = list -> start ;
188
189 if( list -> start -> next )
190 {
191 list -> start = list -> start -> next ;
192 list -> start -> prev = NULL ;
193 }
194
195 list -> nb_items -- ;
196
197 if( list -> nb_items == 0 )
198 list -> start = list -> end = NULL ;
199
200
201 return nodeptr ;
202} /* list_node_shift() */
203
204
205
213{
214 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
215
216 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
217 {
218 n_log( LOG_ERR, "list is full" );
219 return FALSE ;
220 }
221 if( list -> start )
222 {
223 link_node( node, list -> start );
224 list -> start = node ;
225 }
226 else
227 {
228 list -> start = list -> end = node ;
229 }
230 list -> nb_items ++ ;
231
232 return TRUE ;
233} /* list_node_unshift() */
234
235
236
244int list_push( LIST *list, void *ptr, void (*destructor)( void *ptr ) )
245{
246 LIST_NODE *node = NULL ;
247
248 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
249 __n_assert( ptr, n_log( LOG_ERR, "invalid ptr: NULL" ); return FALSE );
250
251 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
252 {
253 n_log( LOG_ERR, "list is full" );
254 return FALSE ;
255 }
256
257 node = new_list_node( ptr, destructor );
258 __n_assert( node, n_log( LOG_ERR, "Couldn't allocate new node" ); return FALSE );
259
260 list -> nb_items ++ ;
261
262 if( list -> end )
263 {
264 list -> end -> next = node ;
265 node -> prev = list -> end ;
266 list -> end = node ;
267 }
268 else
269 {
270 list -> start = list -> end = node ;
271 }
272 return TRUE ;
273} /* list_push( ... ) */
274
275
276
285int list_push_sorted( LIST *list, void *ptr, int (*comparator)( const void *a, const void *b ), void (*destructor)( void *ptr ) )
286{
287 LIST_NODE *nodeptr = NULL ;
288
289 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
290 __n_assert( ptr, n_log( LOG_ERR, "invalid ptr: NULL" ); return FALSE );
291
292 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
293 {
294 n_log( LOG_ERR, "list is full" );
295 return FALSE ;
296 }
297
298 if( list -> end )
299 {
300 nodeptr = list -> end ;
301 while( nodeptr && ( comparator( ptr, nodeptr -> ptr ) < 0 ) )
302 nodeptr = nodeptr -> prev ;
303
304 if( !nodeptr )
305 {
306 /* It's the lower ranked element in the sort */
307 list_unshift( list, ptr, destructor );
308 }
309 else
310 {
311 /* we have a match inside the list. let's insert the datas */
312 LIST_NODE *node_next = nodeptr -> next ;
313 LIST_NODE *newnode = new_list_node( ptr, destructor );
314 __n_assert( newnode, n_log( LOG_ERR, "Couldn't allocate new node" ); return FALSE );
315
316 if( node_next )
317 {
318 link_node( newnode, node_next );
319 }
320 else
321 list -> end = newnode ;
322
323 link_node( nodeptr, newnode );
324 list -> nb_items ++ ;
325 }
326 }
327 else
328 list_push( list, ptr, destructor );
329
330 return TRUE ;
331} /* list_push_sorted( ... ) */
332
333
334
342int list_unshift( LIST *list, void *ptr, void (*destructor)( void *ptr ) )
343{
344 LIST_NODE *node = NULL ;
345
346 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
347 __n_assert( ptr, n_log( LOG_ERR, "invalid ptr: NULL" ); return FALSE );
348
349 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
350 {
351 n_log( LOG_ERR, "list is full" );
352 return FALSE ;
353 }
354 node = new_list_node( ptr, destructor );
355 __n_assert( node, n_log( LOG_ERR, "Couldn't allocate new node" ); return FALSE );
356
357 list -> nb_items ++ ;
358
359 if( list -> start )
360 {
361 link_node( node, list -> start );
362 list -> start = node ;
363 }
364 else
365 {
366 list -> start = list -> end = node ;
367 }
368
369 return TRUE ;
370} /* list_unshift_f(...) */
371
372
373
382int list_unshift_sorted( LIST *list, void *ptr, int (*comparator)( const void *a, const void *b ), void (*destructor)( void *ptr ) )
383{
384 LIST_NODE *nodeptr = NULL ;
385
386 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return FALSE );
387 __n_assert( ptr, n_log( LOG_ERR, "invalid ptr: NULL" ); return FALSE );
388
389 if( list -> nb_max_items > 0 && ( list -> nb_items >= list -> nb_max_items ) )
390 {
391 n_log( LOG_ERR, "list is full" );
392 return FALSE ;
393 }
394
395 if( list -> start )
396 {
397 nodeptr = list -> start ;
398 while( nodeptr && ( comparator( ptr, nodeptr -> ptr ) > 0 ) )
399 nodeptr = nodeptr -> next ;
400
401 if( !nodeptr )
402 {
403 /* It's the higher ranked element in the sort */
404 list_push( list, ptr, destructor );
405 }
406 else
407 {
408 /* we have a match inside the list. let's insert the datas */
409 LIST_NODE *node_prev = nodeptr -> prev ;
410 LIST_NODE *newnode = new_list_node( ptr, destructor );
411 __n_assert( newnode, n_log( LOG_ERR, "Couldn't allocate new node" ); return FALSE );
412
413 if( node_prev )
414 {
415 link_node( node_prev, newnode );
416 }
417 else
418 list -> start = newnode ;
419
420 link_node( newnode, nodeptr );
421 list -> nb_items ++ ;
422 }
423 }
424 else
425 list_unshift( list, ptr, destructor );
426
427 return TRUE ;
428} /* list_unshift_sorted(...) */
429
430
431
437void *list_pop_f( LIST *list )
438{
439 LIST_NODE *nodeptr = NULL ;
440 void *ptr = NULL ;
441
442 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return NULL );
443
444 if( list -> nb_items == 0 || list -> end == NULL )
445 return NULL ;
446
447 nodeptr = list -> end ;
448 ptr = nodeptr -> ptr ;
449
450 if( list -> end -> prev )
451 {
452 list -> end = list -> end -> prev ;
453 list -> end -> next = NULL ;
454 }
455
456 list -> nb_items -- ;
457 if( list -> nb_items == 0 )
458 list -> start = list -> end = NULL ;
459
460 Free( nodeptr );
461
462 return ptr ;
463} /* list_pop_f( ... ) */
464
465
466
474void *list_shift_f( LIST *list , char *file ,size_t line )
475{
476 LIST_NODE *nodeptr = NULL ;
477 void *ptr = NULL ;
478
479 __n_assert( list, n_log( LOG_ERR, "%s:%d: invalid list: NULL" , file , line ); return NULL );
480
481 if( list -> nb_items == 0 || list -> start == NULL )
482 return NULL ;
483
484 nodeptr = list -> start ;
485 ptr = nodeptr -> ptr ;
486
487 if( list -> start -> next )
488 {
489 list -> start = list -> start -> next ;
490 list -> start -> prev = NULL ;
491 }
492
493 list -> nb_items -- ;
494
495 if( list -> nb_items == 0 )
496 list -> start = list -> end = NULL ;
497
498 Free( nodeptr );
499
500 return ptr ;
501} /* list_shift_f(...)*/
502
503
510LIST_NODE *list_search( LIST *list, void *ptr )
511{
512 __n_assert( list, return NULL );
513
514 list_foreach( node, list )
515 {
516 if( node -> ptr == ptr )
517 return node ;
518 }
519 return NULL ;
520} /* list_search */
521
522
523
530LIST_NODE *list_search_with_f( LIST *list, int (*checkfunk)( void *ptr ) )
531{
532 __n_assert( list, return NULL );
533
534 list_foreach( node, list )
535 {
536 if( checkfunk( node -> ptr ) )
537 return node ;
538 }
539 return NULL ;
540} /* list_search */
541
542
543
549int list_empty( LIST *list )
550{
551 LIST_NODE *node = NULL, *node_ptr = NULL ;
552
553 __n_assert( list, n_log( LOG_ERR, "list is NULL" ); return FALSE );
554
555 node = list -> start ;
556 while( node )
557 {
558 node_ptr = node ;
559 node = node -> next ;
560 if( node_ptr -> destroy_func != NULL )
561 {
562 node_ptr -> destroy_func( node_ptr -> ptr );
563 }
564 Free( node_ptr );
565 }
566 list -> start = list -> end = NULL ;
567 list -> nb_items = 0 ;
568 return TRUE ;
569} /* list_empty( ... ) */
570
571
572
579int list_empty_with_f( LIST *list, void (*free_fnct)( void *ptr ) )
580{
581 LIST_NODE *node = NULL, *node_ptr = NULL ;
582
583 __n_assert( list, n_log( LOG_ERR, "list is NULL" ); return FALSE );
584
585 node = list -> start ;
586 while( node )
587 {
588 node_ptr = node ;
589 node = node -> next ;
590 free_fnct( node_ptr -> ptr );
591 Free( node_ptr );
592 }
593 list -> start = list -> end = NULL ;
594 list -> nb_items = 0 ;
595 return TRUE ;
596} /* list_empty_with_f */
597
598
599
605int list_destroy( LIST **list )
606{
607 __n_assert( list&&(*list), n_log( LOG_ERR, "list already destroyed" ); return FALSE );
608 list_empty( (*list) );
609 Free( (*list ) );
610 return TRUE ;
611} /* free_list( ... ) */
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:191
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:284
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:264
LIST_NODE * end
pointer to the end of the list
Definition n_list.h:54
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:52
void * list_pop_f(LIST *list)
Get a pointer from the end of the list.
Definition n_list.c:437
void * list_shift_f(LIST *list, char *file, size_t line)
Get a pointer from the start of the list.
Definition n_list.c:474
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition n_list.c:549
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:244
int list_node_unshift(LIST *list, LIST_NODE *node)
Add a pointer at the start of the list.
Definition n_list.c:212
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
Definition n_list.h:70
int list_unshift(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer at the start of the list.
Definition n_list.c:342
LIST_NODE * list_node_shift(LIST *list)
Get a LIST_NODE pointer from the start of the list.
Definition n_list.c:179
LIST_NODE * new_list_node(void *ptr, void(*destructor)(void *ptr))
Allocate a new node to link in a list.
Definition n_list.c:46
#define link_node(__NODE_1, __NODE_2)
Macro helper for linking two nodes.
Definition n_list.h:61
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:605
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:382
LIST_NODE * list_node_pop(LIST *list)
Get a LIST_NODE pointer from the end of the list.
Definition n_list.c:150
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:68
LIST * new_generic_list(int max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:20
LIST_NODE * list_search(LIST *list, void *ptr)
search ptr in list
Definition n_list.c:510
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:285
int list_empty_with_f(LIST *list, void(*free_fnct)(void *ptr))
Empty a LIST list of pointers.
Definition n_list.c:579
LIST_NODE * list_search_with_f(LIST *list, int(*checkfunk)(void *ptr))
search ptr in list
Definition n_list.c:530
int list_node_push(LIST *list, LIST_NODE *node)
Add a filled node to the end of the list.
Definition n_list.c:120
Structure of a generic LIST container.
Definition n_list.h:45
Structure of a generic list node.
Definition n_list.h:27
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:74
#define LOG_ERR
error conditions
Definition n_log.h:58
Common headers and low-level hugly functions & define.
List structures and definitions.
Generic log system.