1 /*
2  *  Copyright (C) 2011 Christos Tsantilas
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2.1 of the License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  *  MA  02110-1301  USA.
18  */
19 
20 #ifndef __ARRAY_H
21 #define __ARRAY_H
22 
23 #include "c-icap.h"
24 #include "mem.h"
25 
26 #ifdef __cplusplus
27 extern "C"
28 {
29 #endif
30 
31 /**
32  \defgroup ARRAYS  Arrays, stacks, queues and vectors related API
33  \ingroup API
34  * Arrays, stacks, queues and vectors related API.
35  */
36 
37 typedef struct ci_array_item {
38     char *name;
39     void *value;
40 } ci_array_item_t;
41 
42 /**
43  \defgroup SIMPLE_ARRAYS  Simple arrays related API
44  \ingroup ARRAYS
45  * Arrays which store  name/value pair items
46 */
47 
48 /**
49    \typedef ci_array_t
50    \ingroup SIMPLE_ARRAYS
51    * The ci_array_t objects can store a list of name/value pairs. Currently
52    * can grow up to a fixed size.
53  */
54 typedef struct ci_array {
55     ci_array_item_t *items;
56     char *mem;
57     size_t max_size;
58     unsigned int count;
59     ci_mem_allocator_t *alloc;
60 } ci_array_t;
61 
62 /**
63  \def ci_array_value(array, pos)
64  \ingroup SIMPLE_ARRAYS
65  * Return the value of item on position 'pos'
66  */
67 #define ci_array_value(array, pos) (pos < (array)->count ?  (array)->items[pos].value : NULL)
68 
69 /**
70  \def ci_array_name(array, pos)
71  \ingroup SIMPLE_ARRAYS
72  * Return the name of item on position 'pos'
73  */
74 #define ci_array_name(array, pos) (pos < (array)->count ?  (array)->items[pos].name : NULL)
75 
76 /**
77  \def ci_array_size(array)
78  \ingroup SIMPLE_ARRAYS
79  * Return the size of array 'array'
80  */
81 #define ci_array_size(array) ((array)->count)
82 
83 /**
84  * Allocate the required memory and initialize an ci_array_t object
85  \ingroup SIMPLE_ARRAYS
86  \param max_mem_size the maximum memory to use
87  \return the allocated object on success, or NULL on failure
88  *
89  */
90 CI_DECLARE_FUNC(ci_array_t *) ci_array_new(size_t max_mem_size);
91 
92 /**
93  * Create and initialize an ci_array_t object for the given number of items
94  \ingroup SIMPLE_ARRAYS
95  \param items the maximum aray items
96  \param item_size the items size
97  \return the allocated object on success, or NULL on failure
98  */
99 CI_DECLARE_FUNC(ci_array_t *) ci_array_new2(size_t items, size_t item_size);
100 
101 /**
102  * Destroy an ci_array_t object
103  \ingroup SIMPLE_ARRAYS
104  \param array a pointer to ci_array_t object to be destroyed
105  *
106  */
107 CI_DECLARE_FUNC(void) ci_array_destroy(ci_array_t *array);
108 
109 /**
110  * Add an name/value pair item to the array.
111  \ingroup SIMPLE_ARRAYS
112  \param array a pointer to the ci_array_t object
113  \param name the name part of the name/value pair item to add
114  \param value the value part of the name/value pair item to add
115  \param size the size of the value part of the new item.
116  \return a pointer to the new array item on success, NULL otherwise
117  */
118 CI_DECLARE_FUNC(const ci_array_item_t *) ci_array_add(ci_array_t *array, const char *name, const void *value, size_t size);
119 
120 /**
121  * Delete the last element of the array.
122  \ingroup SIMPLE_ARRAYS
123  \param array a pointer to the ci_array_t object
124  \return a pointer to the popped array item on success, NULL otherwise
125  */
126 CI_DECLARE_FUNC(const ci_array_item_t *)ci_array_pop(ci_array_t *array);
127 
128 /**
129  * Search in an array for an item with the given name
130  \ingroup SIMPLE_ARRAYS
131  \param array a pointer to the ci_array_t object
132  \param name the item to be search for.
133  \return pointer to the value pair of the array item if found, NULL otherwise
134  */
135 CI_DECLARE_FUNC(const void *) ci_array_search(ci_array_t *array, const char *name);
136 
137 /**
138  * Run the given function for each array item
139  \ingroup SIMPLE_ARRAYS
140  \param array a pointer to the ci_array_t object
141  \param data a pointer to data which will be passed on fn function
142  \param fn a pointer to the function which will be run for each array item. The iteration will stop if the fn function return non zero value
143  */
144 CI_DECLARE_FUNC(void) ci_array_iterate(const ci_array_t *array, void *data, int (*fn)(void *data, const char *name, const void *));
145 
146 /**
147  * Get an item of the array.
148  \ingroup SIMPLE_ARRAYS
149  \param array a pointer to the ci_array_t object
150  \param pos The position of the item in array
151  \return a pointer to the array item on success, NULL otherwise
152  */
153 CI_DECLARE_FUNC(const ci_array_item_t *) ci_array_get_item(ci_array_t *array, int pos);
154 
155 /**
156  \defgroup STR_ARRAYS   Arrays of strings related API
157  \ingroup SIMPLE_ARRAYS
158  * Arrays which store  name/value pair items
159 */
160 
161 /**
162  \typedef ci_str_array_t
163  \ingroup STR_ARRAYS
164  * An alias to the ci_array_t object. It is used to store items with string
165  * values to an array.
166  * The ci_str_array_new, ci_str_array_destroy, ci_str_array_add,
167  * ci_str_array_search and ci_str_array_iterate defines are similar to
168  * the equivalent ci_array_* functions with the required typecasting to
169  * work with strings.
170  */
171 typedef ci_array_t ci_str_array_t;
172 #define ci_str_array_new ci_array_new
173 #define ci_str_array_destroy ci_array_destroy
174 #define ci_str_array_add(array, name, value) ci_array_add((ci_array_t *)(array), name, value, (strlen(value)+1))
175 #define ci_str_array_pop(array) ci_array_pop((ci_array_t *)(array))
176 #define ci_str_array_get_item(array, pos) ci_array_get_item((ci_array_t *)(array), pos)
177 #define ci_str_array_search(array, name) (const char *)ci_array_search((ci_array_t *)(array), name)
178 #define ci_str_array_iterate ci_array_iterate
179 #define ci_str_array_value(array, pos) ci_array_value((ci_array_t *)(array), pos)
180 #define ci_str_array_name(array, pos) ci_array_name((ci_array_t *)(array), pos)
181 #define ci_str_array_size(array) ci_array_size((ci_array_t *)(array))
182 
183 
184 /**
185  \defgroup PTR_ARRAYS  Arrays of pointers
186  \ingroup SIMPLE_ARRAYS
187  * Arrays of name/pointers to objects pairs
188  */
189 
190 /**
191  \typedef ci_ptr_array_t
192  \ingroup PTR_ARRAYS
193  * The ci_ptr_array_t objects can store a list of name and pointer to object
194  * pairs. It is similar to the ci_array_t object but does not store the value
195  * but a pointer to the value.
196  */
197 typedef ci_array_t ci_ptr_array_t;
198 
199 /**
200  \def ci_ptr_array_value(ptr_array, pos)
201  \ingroup PTR_ARRAYS
202  * Return the value of item at position 'pos'
203  */
204 #define ci_ptr_array_value(array, pos) ci_array_value((ci_array_t *)(array), pos)
205 
206 /**
207  \def ci_ptr_array_value(ptr_array, pos)
208  \ingroup PTR_ARRAYS
209  * Return the name of item at position 'pos'
210  */
211 #define ci_ptr_array_name(array, pos) ci_array_name((ci_array_t *)(array), pos)
212 
213 /**
214  \def ci_ptr_array_value(ptr_array)
215  \ingroup PTR_ARRAYS
216  * Return the size of ptr_array
217  */
218 #define ci_ptr_array_size(array) ci_array_size((ci_array_t *)(array))
219 
220 /**
221  \def ci_ptr_array_new()
222  \ingroup PTR_ARRAYS
223  * Create a new ci_ptr_array_t object. Similar to the ci_array_new() function.
224  */
225 #define ci_ptr_array_new ci_array_new
226 
227 /**
228  * Create and initialize an ci_ptr_array_t object for the given number of items
229  \ingroup PTR_ARRAYS
230  \param items the maximum aray items
231  \return the allocated object on success, or NULL on failure
232  */
233 CI_DECLARE_FUNC(ci_ptr_array_t *) ci_ptr_array_new2(size_t items);
234 
235 /**
236  \def ci_ptr_array_destroy(ptr_array)
237  \ingroup PTR_ARRAYS
238  * Destroy a ci_ptr_array_t object. Similar to the ci_array_destroy function
239  */
240 #define ci_ptr_array_destroy(ptr_array) ci_array_destroy((ci_array_t *)(ptr_array))
241 
242 /**
243  * Search in an array for an item with the given name
244  \ingroup PTR_ARRAYS
245  \param array a pointer to the ci_ptr_array_t object
246  \param name the item to be search for.
247  \return pointer to the value pair of the array item if found, NULL otherwise
248  */
249 CI_DECLARE_FUNC(void *) ci_ptr_array_search(ci_ptr_array_t *array, const char *name);
250 
251 
252 /**
253  \def ci_ptr_array_iterate(ptr_array, data, fn)
254  \ingroup PTR_ARRAYS
255  * Run the function fn for each item of the ci_ptr_array_t object. Similar to
256  * the ci_array_iterate function
257  */
258 #define ci_ptr_array_iterate(ptr_array, data, fn) ci_array_iterate((ci_array_t *)(ptr_array), data, fn)
259 
260 /**
261  * Add an name/value pair item to the ci_ptr_array_t object.
262  \ingroup PTR_ARRAYS
263  \param ptr_array a pointer to the ci_ptr_array_t object
264  \param name the name part of the name/value pair item to be added
265  \param value a pointer to the value part of the name/value pair item to be
266  *      added
267  \return a pointer to the new array item on success, NULL otherwise
268  *
269  */
270 CI_DECLARE_FUNC(const ci_array_item_t *) ci_ptr_array_add(ci_ptr_array_t *ptr_array, const char *name, void *value);
271 
272 /**
273  * Pop and delete the last item of a  ci_ptr_array_t object.
274  \ingroup PTR_ARRAYS
275  \param ptr_array a pointer to the ci_ptr_array_t object
276  \return a pointer to the popped array item
277 */
278 CI_DECLARE_FUNC(const ci_array_item_t *) ci_ptr_array_pop(ci_ptr_array_t *ptr_array);
279 
280 /**
281  * Pop and delete the last item of a  ci_ptr_array_t object.
282  \ingroup PTR_ARRAYS
283  \param ptr_array a pointer to the ci_ptr_array_t object
284  \param name a pointer to a buffer where the name of the poped item will be
285  *      store, or NULL
286  \param name_size the size of name buffer
287  \return a pointer to the value of the popped item
288 */
289 CI_DECLARE_FUNC(void *) ci_ptr_array_pop_value(ci_ptr_array_t *ptr_array, char *name, size_t name_size);
290 
291 /**
292  \def ci_ptr_array_get_item()
293  \ingroup PTR_ARRAYS
294  * Get an array item. Wrapper to the ci_array_get_item() function.
295  */
296 #define ci_ptr_array_get_item(array, pos) ci_array_get_item((ci_array_t *)(array), pos)
297 
298 /**
299  \defgroup DYNAMIC_ARRAYS Dynamic arrays related API
300  \ingroup ARRAYS
301  * Arrays which store  name/value pair items, and can grow unlimited.
302  *
303  */
304 
305 /**
306  \typedef ci_dyn_array_t
307  \ingroup DYNAMIC_ARRAYS
308  * The ci_dyn_array_t objects can store a list of name/value pairs.
309  * The memory RAM space of dynamic array items can not be released
310  * before the ci_dyn_array destroyed.
311  */
312 typedef struct ci_dyn_array {
313     ci_array_item_t **items;
314     int count;
315     int max_items;
316     ci_mem_allocator_t *alloc;
317 } ci_dyn_array_t;
318 
319 /**
320  \def ci_dyn_array_get_item(array, pos)
321  \ingroup DYNAMIC_ARRAYS
322  * Return the ci_array_item_t item on position 'pos'
323  */
324 #define ci_dyn_array_get_item(array, pos) (pos < (array)->count ? (array)->items[pos] : NULL)
325 
326 /**
327  \def ci_dyn_array_value(array, pos)
328  \ingroup DYNAMIC_ARRAYS
329  * Return the value of item on position 'pos'
330  */
331 #define ci_dyn_array_value(array, pos) ((pos < (array)->count && (array)->items[pos] != NULL) ?  (array)->items[pos]->value : NULL)
332 
333 /**
334  \def ci_dyn_array_name(array, pos)
335  \ingroup DYNAMIC_ARRAYS
336  * Return the name of item on position 'pos'
337  */
338 #define ci_dyn_array_name(array, pos) ((pos < (array)->count && (array)->items[pos] != NULL) ?  (array)->items[pos]->name : NULL)
339 
340 /**
341  \def ci_dyn_array_size(array)
342  \ingroup DYNAMIC_ARRAYS
343  * Return the size of array 'array'
344  */
345 #define ci_dyn_array_size(array) ((array)->count)
346 
347 /**
348  * Allocate the required memory and initialize an ci_dyn_array_t object
349  \ingroup DYNAMIC_ARRAYS
350  \param mem_size the initial size to use for dyn_array
351  \return the allocated object on success, or NULL on failure
352  *
353  */
354 CI_DECLARE_FUNC(ci_dyn_array_t *) ci_dyn_array_new(size_t mem_size);
355 
356 /**
357  * Create and initialize an ci_dyn_array_t object for the given number of items
358  \ingroup DYNAMIC_ARRAYS
359  \param items the maximum aray items
360  \param item_size the items size
361  \return the allocated object on success, or NULL on failure
362  */
363 CI_DECLARE_FUNC(ci_dyn_array_t *) ci_dyn_array_new2(size_t items, size_t item_size);
364 
365 /**
366  * Destroy an ci_dyn_array_t object
367  \ingroup DYNAMIC_ARRAYS
368  \param array a pointer to ci_dyn_array_t object to be destroyed
369  */
370 CI_DECLARE_FUNC(void) ci_dyn_array_destroy(ci_dyn_array_t *array);
371 
372 /**
373  * Add an name/value pair item to a dynamic array.
374  \ingroup DYNAMIC_ARRAYS
375  \param array a pointer to the ci_dyn_array_t object
376  \param name the name part of the name/value pair item to be added
377  \param value the value part of the name/value pair item to be added
378  \param size the size of the value part of the new item.
379  \return a pointer to the new array item on success, NULL otherwise
380  */
381 CI_DECLARE_FUNC(const ci_array_item_t *) ci_dyn_array_add(ci_dyn_array_t *array, const char *name, const void *value, size_t size);
382 
383 /**
384  * Search in an dynamic array for an item with the given name
385  \ingroup DYNAMIC_ARRAYS
386  \param array a pointer to the ci_dyn_array_t object
387  \param name the item to be search for.
388  \return pointer to the value pair of the array item if found, NULL otherwise
389  */
390 CI_DECLARE_FUNC(const void *) ci_dyn_array_search(ci_dyn_array_t *array, const char *name);
391 
392 /**
393  * Run the given function for each dynamic array item
394  \ingroup DYNAMIC_ARRAYS
395  \param array a pointer to the ci_dyn_array_t object
396  \param data a pointer to data which will be passed on fn function
397  \param fn a pointer to the function which will be run for each array item.
398  *      The iteration will stop if the fn function return non zero value.
399  */
400 CI_DECLARE_FUNC(void) ci_dyn_array_iterate(const ci_dyn_array_t *array, void *data, int (*fn)(void *data, const char *name, const void *));
401 
402 /**
403  \defgroup PTR_DYNAMIC_ARRAYS   Dynamic arrays of pointers related API
404  \ingroup DYNAMIC_ARRAYS
405  * Arrays which store  name/value pair items
406 */
407 
408 /**
409  \typedef ci_ptr_dyn_array_t
410  \ingroup PTR_DYNAMIC_ARRAYS
411  * An alias to the ci_dyn_array_t object. It is used to store pointers
412  * to an array.
413  * The ci_ptr_dyn_array_new, ci_ptr_dyn_array_destroy, ci_ptr_dyn_array_search
414  * and ci_ptr_dyn_array_iterate defines are  equivalent to the ci_dyn_array_*
415  * functions with the required typecasting.
416  */
417 typedef ci_dyn_array_t ci_ptr_dyn_array_t;
418 #define ci_ptr_dyn_array_new(size) ci_dyn_array_new(size)
419 #define ci_ptr_dyn_array_new2(items, item_size) ci_dyn_array_new2(items, item_size)
420 #define ci_ptr_dyn_array_destroy(ptr_array) ci_dyn_array_destroy((ci_dyn_array_t *)(ptr_array))
421 #define ci_ptr_dyn_array_search(ptr_array, name) ci_dyn_array_search((ci_dyn_array_t *)(ptr_array), name)
422 #define ci_ptr_dyn_array_iterate(ptr_array, data, fn) ci_dyn_array_iterate((ci_dyn_array_t *)(ptr_array), data, fn)
423 
424 #define ci_ptr_dyn_array_get_item(ptr_array, pos) ci_dyn_array_get_item((ci_dyn_array_t *)(ptr_array), pos)
425 #define ci_ptr_dyn_array_value(ptr_array, pos) ci_dyn_array_value((ci_dyn_array_t *)(ptr_array), pos)
426 #define ci_ptr_dyn_array_name(ptr_array, pos) ci_dyn_array_name((ci_dyn_array_t *)(ptr_array), pos)
427 #define ci_ptr_dyn_array_size(ptr_array) ci_dyn_array_size((ci_dyn_array_t *)(ptr_array))
428 
429 /**
430  * Add an name/value pair item to the array.
431  \ingroup  PTR_DYNAMIC_ARRAYS
432  \param ptr_array a pointer to the ci_ptr_dyn_array_t object
433  \param name the name part of the name/pointer pair item to be added
434  \param pointer the pointer part of the name/value pair item to be added
435  \return a pointer to the new array item on success, NULL otherwise
436  */
437 CI_DECLARE_FUNC(const ci_array_item_t *) ci_ptr_dyn_array_add(ci_ptr_dyn_array_t *ptr_array, const char *name, void *pointer);
438 
439 
440 /**
441  \defgroup VECTORS  Simple vectors related API
442  \ingroup ARRAYS
443  * Structure which can store lists of objects
444  */
445 
446 /**
447  \typedef ci_vector_t
448  \ingroup VECTORS
449  * The ci_vector_t objects can store a list of objects. Currently can grow up
450  * to a fixed size.
451  */
452 typedef struct ci_vector {
453     void **items;
454     void **last;
455     char *mem;
456     size_t max_size;
457     int count;
458     ci_mem_allocator_t *alloc;
459 } ci_vector_t;
460 
461 /**
462  * Allocate the required memory and initialize a ci_vector_t object
463  \ingroup VECTORS
464  \param max_size the maximum memory to use
465  \return the allocated object on success, or NULL on failure
466  */
467 CI_DECLARE_FUNC(ci_vector_t *) ci_vector_create(size_t max_size);
468 
469 /**
470  * Destroy an ci_vector_t object
471  \ingroup VECTORS
472  \param vector a pointer to ci_vector_t object to be destroyed
473  */
474 CI_DECLARE_FUNC(void) ci_vector_destroy(ci_vector_t *vector);
475 
476 /**
477  * Add an  item to the vector.
478  \ingroup VECTORS
479  \param vector a pointer to the ci_vector_t object
480  \param obj pointer to the object to add in vector
481  \param size the size of the new item.
482  \return a pointer to the new  item on success, NULL otherwise
483  */
484 CI_DECLARE_FUNC(void *) ci_vector_add(ci_vector_t *vector, const void *obj, size_t size);
485 
486 /**
487  * Run the given function for each vector item
488  \ingroup VECTORS
489  \param vector a pointer to the ci_vector_t object
490  \param data a pointer to data which will be passed to the fn function
491  \param fn a pointer to the function which will be run for each vector item.
492  *      The iteration will stop if the fn function return non zero value.
493  */
494 CI_DECLARE_FUNC(void) ci_vector_iterate(const ci_vector_t *vector, void *data, int (*fn)(void *data, const void *));
495 
496 /**
497  * Delete the last element of a vector.
498  \ingroup VECTORS
499  \param vector a pointer to the ci_vector_t object
500  \return a pointer to the popped vector item on success, NULL otherwise
501  */
502 CI_DECLARE_FUNC(void *) ci_vector_pop(ci_vector_t *vector);
503 
504 /**
505  \def ci_vector_get(vector, i)
506  \ingroup VECTORS
507  * Return a pointer to the i item of the vector
508  */
509 #define ci_vector_get(vector, i) (i < vector->count ? (const void *)vector->items[i]:  (const void *)NULL)
510 
511 
512 CI_DECLARE_FUNC(const void **) ci_vector_cast_to_voidvoid(ci_vector_t *vector);
513 CI_DECLARE_FUNC(ci_vector_t *)ci_vector_cast_from_voidvoid(const void **p);
514 
515 /**
516  \defgroup STR_VECTORS  Vectors of strings
517  \ingroup VECTORS
518  *
519  */
520 
521 /**
522  \typedef ci_str_vector_t
523  \ingroup STR_VECTORS
524  * The ci_str_vector is used to implement string vectors.
525  * The  ci_str_vector_create, ci_str_vector_destroy,  ci_str_vector_add,
526  * and ci_str_vector_pop defines are similar and equivalent to the ci_vector_*
527  * functions.
528  */
529 typedef ci_vector_t ci_str_vector_t;
530 #define ci_str_vector_create ci_vector_create
531 #define ci_str_vector_destroy ci_vector_destroy
532 #define ci_str_vector_add(vect, string) ((const char *)ci_vector_add((ci_vector_t *)(vect), string, (strlen(string)+1)))
533 #define ci_str_vector_get(vector, i) (i < vector->count ? (const char *)vector->items[i]:  (const char *)NULL)
534 #define ci_str_vector_pop(vect)  ((const char *)ci_vector_pop((ci_vector_t *)(vect)))
535 #define ci_str_vector_cast_to_charchar(vector) ((const char **)ci_vector_cast_to_voidvoid((ci_vector_t *)(vector)))
536 #define ci_str_vector_cast_from_charchar(p) ((ci_str_vector_t *)ci_vector_cast_from_voidvoid((const void **)p))
537 
538 /**
539  * Run the given function for each string vector item
540  \ingroup STR_VECTORS
541  \param vector a pointer to the ci_vector_t object
542  \param data a pointer to data which will be passed to the fn function
543  \param fn a pointer to the function which will be run for each string vector
544  *      item. The iteration will stop if the fn function return non zero value.
545  */
546 CI_DECLARE_FUNC(void) ci_str_vector_iterate(const ci_str_vector_t *vector, void *data, int (*fn)(void *data, const char *));
547 
548 /**
549  * Search for a string in a string vector.
550  \ingroup STR_VECTORS
551  \param vector a pointer to the ci_vector_t object
552  \param str the string to search for
553  \return a pointer to the new  item on success, NULL otherwise
554  */
555 CI_DECLARE_FUNC(const char *) ci_str_vector_search(ci_str_vector_t *vector, const char *str);
556 
557 /**
558  \defgroup PTR_VECTORS  Vectors of pointers
559  \ingroup VECTORS
560  */
561 
562 /**
563  \typedef ci_ptr_vector_t
564  \ingroup PTR_VECTORS
565  * The ci_ptr_vector is used to implement vectors storing pointers.
566  * The ci_ptr_vector_create, ci_ptr_vector_destroy, ci_ptr_vector_iterate,
567  * and ci_ptr_vector_get defines are similar and equivalent to the ci_vector_* functions.
568  */
569 typedef ci_vector_t ci_ptr_vector_t;
570 #define ci_ptr_vector_create ci_vector_create
571 #define ci_ptr_vector_destroy ci_vector_destroy
572 #define ci_ptr_vector_iterate ci_vector_iterate
573 #define ci_ptr_vector_get ci_vector_get
574 
575 /**
576  * Add an  item to the vector.
577  \ingroup PTR_VECTORS
578  \param vector a pointer to the ci_vector_t object
579  \param pointer the pointer to store in vector
580  \return a pointer to the new  item on success, NULL otherwise
581  */
582 CI_DECLARE_FUNC(void *) ci_ptr_vector_add(ci_vector_t *vector, void *pointer);
583 
584 /**
585  \defgroup LISTS Lists API
586  \ingroup ARRAYS
587  * Lists for storing items, and can grow unlimited.
588  *
589  */
590 
591 typedef struct ci_list_item {
592     void *item;
593     struct ci_list_item *next;
594 } ci_list_item_t;
595 
596 /**
597  \typedef ci_list_t
598  \ingroup LISTS
599  * The ci_list_t objects can store a list of objects, with a predefined size.
600  * The list items can be removed.
601  * The memory RAM space of list can not be decreased before the
602  * ci_list destroyed. However the memory of removed items reused.
603  */
604 typedef struct ci_list {
605     ci_list_item_t *items;
606     ci_list_item_t *last;
607     ci_list_item_t *trash;
608     ci_list_item_t *cursor;
609     ci_list_item_t *tmp;
610     size_t obj_size;
611     ci_mem_allocator_t *alloc;
612 
613     int (*cmp_func)(const void *obj, const void *user_data, size_t user_data_size);
614     int (*copy_func)(void *newObj, const void *oldObj);
615     void (*free_func)(void *obj);
616 } ci_list_t;
617 
618 /**
619  * Allocate the required memory and initialize a ci_list_t object
620  \ingroup LISTS
621  \param init_size the initial memory size to use
622  \param obj_size the size of stored objects. If it is 0 then stores pointers
623  *      to objects.
624  \return the allocated object on success, or NULL on failure
625  */
626 CI_DECLARE_FUNC(ci_list_t *) ci_list_create(size_t init_size, size_t obj_size);
627 
628 /**
629  \def ci_list_first(ci_list_t *list)
630  * Gets the first item of the list and updates the list cursor to the next item.
631  * WARNING: do not mix this macro with ci_list_iterate. Use the ci_list_head
632  * and ci_list_tail macros instead
633  \ingroup LISTS
634  \param list  a pointer to the ci_list_t object
635  \return The first item if exist, NULL otherwise
636  */
637 #define ci_list_first(list) (list && (list)->items && (((list)->cursor = (list)->items->next) != NULL || 1) ? (list)->items->item : NULL)
638 
639 
640 /**
641  \def ci_list_next()
642  * Return the next item of the list and updates the list cursor to the next
643  * item.
644  * WARNING: It does not check for valid list object.
645  * WARNING: do not mix this macro with ci_list_iterate!
646  \ingroup LISTS
647  \param list  a pointer to the ci_list_t object
648  \return The next item if exist, NULL otherwise
649 */
650 #define ci_list_next(list) (((list)->tmp = (list)->cursor) != NULL && (((list)->cursor = (list)->cursor->next) != NULL || 1) ? (list)->tmp->item : NULL)
651 
652 
653 /**
654  \def ci_list_head(list)
655  \ingroup LISTS
656  * Return the head of the list
657  */
658 #define ci_list_head(list) (list && list->items != NULL ? list->items->item : NULL)
659 
660 /**
661  \def ci_list_tail(list)
662  \ingroup LISTS
663  * Return last item of the list.
664  */
665 #define ci_list_tail(list) (list && list->last != NULL ? list->last->item : NULL)
666 
667 /**
668  * Destroy an ci_list_t object
669  \ingroup LISTS
670  \param list a pointer to ci_list_t object to be destroyed
671  */
672 CI_DECLARE_FUNC(void) ci_list_destroy(ci_list_t *list);
673 
674 /**
675  * Run the given function for each list item
676  \ingroup LISTS
677  \param list a pointer to the ci_list_t object
678  \param data a pointer to data which will be passed to the fn function
679  \param fn a pointer to the function which will be run for each vector item.
680  *      The iteration will stop if the fn function return non zero value.
681  */
682 CI_DECLARE_FUNC(void) ci_list_iterate(ci_list_t *list, void *data, int (*fn)(void *data, const void *obj));
683 
684 /**
685  * Add an item to the head of list.
686  \ingroup LISTS
687  \param list a pointer to the ci_list_t object
688  \param obj pointer to the object to add in vector
689  \return a pointer to the new  item on success, NULL otherwise
690  */
691 CI_DECLARE_FUNC(const void *) ci_list_push(ci_list_t *list, const void *obj);
692 
693 /**
694  * Add an item to the tail of list.
695  \ingroup LISTS
696  \param list a pointer to the ci_list_t object
697  \param obj pointer to the object to add in vector
698  \return a pointer to the new  item on success, NULL otherwise
699  */
700 CI_DECLARE_FUNC(const void *) ci_list_push_back(ci_list_t *list, const void *data);
701 
702 /**
703  * Remove the first item of the list.
704  \ingroup LISTS
705  \param list a pointer to the ci_list_t object
706  \param obj pointer to an object to store removed item
707  \return a pointer to the obj on success, NULL otherwise
708  */
709 CI_DECLARE_FUNC(void *) ci_list_pop(ci_list_t *list, void *obj);
710 
711 /**
712  * Remove the last item of the list.
713  \ingroup LISTS
714  \param list a pointer to the ci_list_t object
715  \param obj pointer to an object to store removed item
716  \return a pointer to the obj on success, NULL otherwise
717  */
718 CI_DECLARE_FUNC(void *) ci_list_pop_back(ci_list_t *list, void *obj);
719 
720 /**
721  * Remove the first found item equal to the obj.
722  \ingroup LISTS
723  \param list a pointer to the ci_list_t object
724  \param obj pointer to an object to remove
725  \return not 0 on success, 0 otherwise
726  */
727 CI_DECLARE_FUNC(int) ci_list_remove(ci_list_t *list, const void *obj);
728 
729 /**
730  * Return the first found item equal to the obj.
731  \ingroup LISTS
732  \param list a pointer to the ci_list_t object
733  \param obj pointer to an object to remove
734  \return the found item on success, NULL otherwise
735  */
736 CI_DECLARE_FUNC(const void *) ci_list_search(ci_list_t *list, const void *data);
737 
738 /**
739  * Return the first found item equal to the obj, using the cmp_func as
740  * comparison function.
741  \ingroup LISTS
742  \param list a pointer to the ci_list_t object
743  \param obj pointer to an object to remove
744  \param cmp_func the comparison function to use
745  \return the found item on success, NULL otherwise
746  */
747 CI_DECLARE_FUNC(const void *) ci_list_search2(ci_list_t *list, const void *data, int (*cmp_func)(const void *obj, const void *user_data, size_t user_data_size));
748 
749 /**
750  * Sorts the list using as compare function the default.
751  \ingroup LISTS
752  \param list a pointer to the ci_list_t object
753  */
754 CI_DECLARE_FUNC(void) ci_list_sort(ci_list_t *list);
755 
756 /**
757  * Sorts the list using as compare function the cmp_func.
758  \ingroup LISTS
759  \param list a pointer to the ci_list_t object
760  \param cmp_func the compare function to use
761  */
762 CI_DECLARE_FUNC(void) ci_list_sort2(ci_list_t *list, int (*cmp_func)(const void *obj1, const void *obj2, size_t obj_size));
763 
764 /*
765   The following three functions are undocumented. Probably will be removed or replaced
766   by others.
767  */
768 CI_DECLARE_FUNC(void) ci_list_cmp_handler(ci_list_t *list, int (*cmp_func)(const void *obj, const void *user_data, size_t user_data_size));
769 CI_DECLARE_FUNC(void) ci_list_copy_handler(ci_list_t *list, int (*copy_func)(void *newObj, const void *oldObj));
770 CI_DECLARE_FUNC(void) ci_list_free_handler(ci_list_t *list, void (*free_func)(void *obj));
771 
772 #ifdef __cplusplus
773 }
774 #endif
775 
776 #endif /*__ARRAY_H*/
777