Nilorea Library
C utilities for networking, threading, graphics
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
472void *list_shift_f( LIST *list )
473{
474 LIST_NODE *nodeptr = NULL ;
475 void *ptr = NULL ;
476
477 __n_assert( list, n_log( LOG_ERR, "invalid list: NULL" ); return NULL );
478
479 if( list -> nb_items == 0 || list -> start == NULL )
480 return NULL ;
481
482 nodeptr = list -> start ;
483 ptr = nodeptr -> ptr ;
484
485 if( list -> start -> next )
486 {
487 list -> start = list -> start -> next ;
488 list -> start -> prev = NULL ;
489 }
490
491 list -> nb_items -- ;
492
493 if( list -> nb_items == 0 )
494 list -> start = list -> end = NULL ;
495
496 Free( nodeptr );
497
498 return ptr ;
499} /* list_shift_f(...)*/
500
501
508LIST_NODE *list_search( LIST *list, void *ptr )
509{
510 __n_assert( list, return NULL );
511
512 list_foreach( node, list )
513 {
514 if( node -> ptr == ptr )
515 return node ;
516 }
517 return NULL ;
518} /* list_search */
519
520
521
528LIST_NODE *list_search_with_f( LIST *list, int (*checkfunk)( void *ptr ) )
529{
530 __n_assert( list, return NULL );
531
532 list_foreach( node, list )
533 {
534 if( checkfunk( node -> ptr ) )
535 return node ;
536 }
537 return NULL ;
538} /* list_search */
539
540
541
547int list_empty( LIST *list )
548{
549 LIST_NODE *node = NULL, *node_ptr = NULL ;
550
551 __n_assert( list, n_log( LOG_ERR, "list is NULL" ); return FALSE );
552
553 node = list -> start ;
554 while( node )
555 {
556 node_ptr = node ;
557 node = node -> next ;
558 if( node_ptr -> destroy_func != NULL )
559 {
560 node_ptr -> destroy_func( node_ptr -> ptr );
561 }
562 Free( node_ptr );
563 }
564 list -> start = list -> end = NULL ;
565 list -> nb_items = 0 ;
566 return TRUE ;
567} /* list_empty( ... ) */
568
569
570
577int list_empty_with_f( LIST *list, void (*free_fnct)( void *ptr ) )
578{
579 LIST_NODE *node = NULL, *node_ptr = NULL ;
580
581 __n_assert( list, n_log( LOG_ERR, "list is NULL" ); return FALSE );
582
583 node = list -> start ;
584 while( node )
585 {
586 node_ptr = node ;
587 node = node -> next ;
588 free_fnct( node_ptr -> ptr );
589 Free( node_ptr );
590 }
591 list -> start = list -> end = NULL ;
592 list -> nb_items = 0 ;
593 return TRUE ;
594} /* list_empty_with_f */
595
596
597
603int list_destroy( LIST **list )
604{
605 __n_assert( list&&(*list), n_log( LOG_ERR, "list already destroyed" ); return FALSE );
606 list_empty( (*list) );
607 Free( (*list ) );
608 return TRUE ;
609} /* free_list( ... ) */
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition: n_common.h:183
#define __n_assert(__ptr, __ret)
macro to assert things
Definition: n_common.h:276
#define Free(__ptr)
Free Handler to get errors.
Definition: n_common.h:256
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
int list_empty(LIST *list)
Empty a LIST list of pointers.
Definition: n_list.c:547
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:603
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
void * list_shift_f(LIST *list)
Get a pointer from the start of the list.
Definition: n_list.c:472
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:508
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:577
LIST_NODE * list_search_with_f(LIST *list, int(*checkfunk)(void *ptr))
search ptr in list
Definition: n_list.c:528
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.