2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4 /* EINA - EFL data type library
5 * Copyright (C) 2008 Cedric Bail
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library;
19 * if not, see <http://www.gnu.org/licenses/>.
24 * @page tutorial_array_page Array Tutorial
26 * The Array data type is allow the storage of data like a C array.
27 * It is designed such that the access to its element is very fast.
28 * But the addition or removal can be done only at the end of the
29 * array. To add or remove an element at any location, the Eina
30 * @ref Eina_List_Group is the correct container is the correct one.
32 * @section tutorial_error_basic_usage Basic Usage
34 * An array must created with eina_array_new(). That function
35 * takes an integer as parameter, which is the count of pointers to
36 * add when increasing the array size. Once the array is not used
37 * anymore, it must be destroyed with eina_array_free().
39 * To append data at the end of the array, the function
40 * eina_array_push() must be used. To remove the data at the end of
41 * the array, eina_array_pop() must be used. Once the array is filled,
42 * one can check its elements by iterating over it. A while loop and
43 * eina_array_data_get() can be used, or else one can use the
44 * predefined macro EINA_ARRAY_ITER_NEXT(). To free all the elements,
45 * a while loop can be used with eina_array_count_get(). Here is an
53 * #include <eina_array.h>
57 * const char *strings[] = {
65 * Eina_Array_Iterator iterator;
70 * printf ("Error during the initialization of eina\n");
71 * return EXIT_FAILURE;
74 * array = eina_array_new(16);
78 * for (i = 0; i < 4; i++)
80 * eina_array_push(array, strdup(strings[i]));
83 * printf("array count: %d\n", eina_array_count_get(array));
84 * EINA_ARRAY_ITER_NEXT(array, i, item, iterator)
86 * printf("item #%d: %s\n", i, item);
89 * while (eina_array_count_get(array))
93 * data = eina_array_pop(array);
97 * eina_array_free(array);
100 * return EXIT_SUCCESS;
105 * return EXIT_FAILURE;
121 #include "eina_config.h"
122 #include "eina_private.h"
123 #include "eina_error.h"
125 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
126 #include "eina_safety_checks.h"
127 #include "eina_array.h"
129 /*============================================================================*
131 *============================================================================*/
137 #define EINA_MAGIC_CHECK_ARRAY(d) \
139 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY)) \
140 EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY); \
143 #define EINA_MAGIC_CHECK_ARRAY_ITERATOR(d, ...) \
145 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ITERATOR)) \
147 EINA_MAGIC_FAIL(d, EINA_MAGIC_ARRAY_ITERATOR); \
148 return __VA_ARGS__; \
152 #define EINA_MAGIC_CHECK_ARRAY_ACCESSOR(d, ...) \
154 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_ARRAY_ACCESSOR)) \
156 EINA_MAGIC_FAIL(d, EINA_MAGIC_ACCESSOR); \
157 return __VA_ARGS__; \
162 typedef struct _Eina_Iterator_Array Eina_Iterator_Array;
163 struct _Eina_Iterator_Array
165 Eina_Iterator iterator;
167 const Eina_Array *array;
173 typedef struct _Eina_Accessor_Array Eina_Accessor_Array;
174 struct _Eina_Accessor_Array
176 Eina_Accessor accessor;
177 const Eina_Array *array;
181 static int _eina_array_log_dom = -1;
182 #define ERR(...) EINA_LOG_DOM_ERR(_eina_array_log_dom, __VA_ARGS__)
183 #define DBG(...) EINA_LOG_DOM_DBG(_eina_array_log_dom, __VA_ARGS__)
185 static void eina_array_iterator_free(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
186 static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
187 static Eina_Bool eina_array_iterator_next(Eina_Iterator_Array *it, void **data) EINA_ARG_NONNULL(1);
189 static Eina_Bool eina_array_accessor_get_at(Eina_Accessor_Array *it, unsigned int index, void **data) EINA_ARG_NONNULL(1);
190 static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
191 static void eina_array_accessor_free(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
194 eina_array_iterator_next(Eina_Iterator_Array *it, void **data)
196 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
198 if (!(it->index < eina_array_count_get(it->array)))
201 *data = eina_array_data_get(it->array, it->index);
207 eina_array_iterator_get_container(Eina_Iterator_Array *it)
209 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, NULL);
210 return (Eina_Array *) it->array;
214 eina_array_iterator_free(Eina_Iterator_Array *it)
216 EINA_MAGIC_CHECK_ARRAY_ITERATOR(it);
221 eina_array_accessor_get_at(Eina_Accessor_Array *it, unsigned int index, void **data)
223 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, EINA_FALSE);
225 if (!(index < eina_array_count_get(it->array)))
228 *data = eina_array_data_get(it->array, index);
233 eina_array_accessor_get_container(Eina_Accessor_Array *it)
235 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it, NULL);
236 return (Eina_Array *) it->array;
240 eina_array_accessor_free(Eina_Accessor_Array *it)
242 EINA_MAGIC_CHECK_ARRAY_ACCESSOR(it);
247 eina_array_grow(Eina_Array *array)
252 EINA_MAGIC_CHECK_ARRAY(array);
253 EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
255 total = array->total + array->step;
257 tmp = realloc(array->data, sizeof (void*) * total);
258 if (UNLIKELY(!tmp)) {
259 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
263 array->total = total;
274 /*============================================================================*
276 *============================================================================*/
278 /*============================================================================*
280 *============================================================================*/
283 * @addtogroup Eina_Array_Group Array
285 * @brief These functions provide array management.
287 * The Array data type in Eina is designed to have a very fast access to
288 * its data (compared to the Eina @ref Eina_List_Group). On the other hand,
289 * data can be added or removed only at the end of the array. To insert
290 * data at any place, the Eina @ref Eina_List_Group is the correct container
293 * To use the array data type, eina_init() must be called before any
294 * other array functions. When eina is no more array function is used,
295 * eina_shutdown() must be called to free all the resources.
297 * An array must be created with eina_array_new(). It allocated all
298 * the necessary data for an array. When not needed anymore, an array
299 * is freed with eina_array_free(). This function does not free any
300 * allocated memory used to store the data of each element. For that,
301 * just iterate over the array to free them. A convenient way to do
302 * that is by using #EINA_ARRAY_ITER_NEXT. An example of code is given
303 * in the description of this macro.
305 * @warning All the other functions do not check if the used array is
306 * valid or not. It's up to the user to be sure of that. It is
307 * designed like that for performance reasons.
309 * The usual features of an array are classic ones: to append an
310 * element, use eina_array_push() and to remove the last element, use
311 * eina_array_pop(). To retrieve the element at a given positin, use
312 * eina_array_data_get(). The number of elements can be retrieved with
313 * eina_array_count_get().
315 * For more information, you can look at the @ref tutorial_array_page.
322 * @brief Initialize the array module.
324 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
326 * This function sets up the error and magic modules or Eina. It is
327 * called by eina_init().
332 eina_array_init(void)
334 _eina_array_log_dom = eina_log_domain_register("eina_array", EINA_LOG_COLOR_DEFAULT);
335 if (_eina_array_log_dom < 0)
337 EINA_LOG_ERR("Could not register log domain: eina_array");
341 eina_magic_string_set(EINA_MAGIC_ARRAY, "Eina Array");
342 eina_magic_string_set(EINA_MAGIC_ARRAY_ITERATOR, "Eina Array Iterator");
343 eina_magic_string_set(EINA_MAGIC_ARRAY_ACCESSOR, "Eina Array Accessor");
349 * @brief Shut down the array module.
351 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
353 * This function shuts down the array module set up by
354 * eina_array_init(). It is called by eina_shutdown().
356 * @see eina_shutdown()
359 eina_array_shutdown(void)
361 eina_log_domain_unregister(_eina_array_log_dom);
362 _eina_array_log_dom = -1;
367 * @brief Create a new array.
369 * @param step The count of pointers to add when increasing the array size.
370 * @return @c NULL on failure, non @c NULL otherwise.
372 * This function creates a new array. When adding an element, the array
373 * allocates @p step elements. When that buffer is full, then adding
374 * another element will increase the buffer of @p step elements again.
376 * This function return a valid array on success, or @c NULL if memory
377 * allocation fails. In that case, the error is set to
378 * #EINA_ERROR_OUT_OF_MEMORY.
381 eina_array_new(unsigned int step)
386 array = malloc(sizeof (Eina_Array));
388 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
392 EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
399 DBG("array=%p", array);
405 * @brief Free an array.
407 * @param array The array to free.
409 * This function frees @p array. It calls first eina_array_flush() then
410 * free the memory of the pointeur. It does not free the memory
411 * allocated for the elements of @p array. To free them, use
412 * #EINA_ARRAY_ITER_NEXT. For performance reasons, there is no check
416 eina_array_free(Eina_Array *array)
418 eina_array_flush(array);
420 EINA_MAGIC_CHECK_ARRAY(array);
421 EINA_SAFETY_ON_NULL_RETURN(array);
422 DBG("array=%p", array);
427 * @brief Set the step of an array.
429 * @param array The array.
430 * @param step The count of pointers to add when increasing the array size.
432 * This function sets the step of @p array to @p step. For performance
433 * reasons, there is no check of @p array. If it is @c NULL or
434 * invalid, the program may crash.
437 eina_array_step_set(Eina_Array *array, unsigned int step)
439 EINA_SAFETY_ON_NULL_RETURN(array);
444 EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
445 DBG("array=%p, step=%u", array, step);
449 * @brief Clean an array.
451 * @param array The array to clean.
453 * This function sets the count member of @p array to 0. For
454 * performance reasons, there is no check of @p array. If it is
455 * @c NULL or invalid, the program may crash.
458 eina_array_clean(Eina_Array *array)
460 EINA_MAGIC_CHECK_ARRAY(array);
461 EINA_SAFETY_ON_NULL_RETURN(array);
463 DBG("array=%p", array);
467 * @brief Flush an array.
469 * @param array The array to flush.
471 * This function sets the count and total members of @p array to 0,
472 * frees and set to NULL its data member. For performance reasons,
473 * there is no check of @p array. If it is @c NULL or invalid, the
477 eina_array_flush(Eina_Array *array)
479 EINA_MAGIC_CHECK_ARRAY(array);
480 EINA_SAFETY_ON_NULL_RETURN(array);
481 DBG("array=%p", array);
485 if (!array->data) return;
491 * @brief Rebuild an array by specifying the data to keep.
493 * @param array The array.
494 * @param keep The functions which selects the data to keep.
495 * @param gdata The data to pass to the function keep.
496 * @return #EINA_TRUE on success, #EINA_FALSE oterwise.
498 * This function rebuilds @p array be specifying the elements to keep
499 * with the function @p keep. @p gdata is an additional data to pass
500 * to @p keep. For performance reasons, there is no check of @p
501 * array. If it is @c NULL or invalid, the program may crash.
503 * This function always return a valid array. If it wasn't able to
504 * remove items due to an allocation failure, it will return #EINA_FALSE
505 * and the error is set to #EINA_ERROR_OUT_OF_MEMORY.
508 eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data, void *gdata), void *gdata)
512 unsigned int total = 0;
516 EINA_MAGIC_CHECK_ARRAY(array);
517 EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
518 EINA_SAFETY_ON_NULL_RETURN_VAL(keep, EINA_FALSE);
520 DBG("array=%p, keep=%p, gdata=%p", array, keep, gdata);
522 if (array->total == 0) return EINA_TRUE;
524 for (i = 0; i < array->count; ++i)
526 data = eina_array_data_get(array, i);
528 if (keep(data, gdata) == EINA_FALSE) break;
531 if (i < array->count) ++i;
532 for (; i < array->count; ++i)
534 data = eina_array_data_get(array, i);
536 if (keep(data, gdata) == EINA_TRUE) break;
538 /* Special case all objects that need to stay are at the beginning of the array. */
539 if (i == array->count)
541 array->count = limit;
542 if (array->count == 0)
553 tmp = malloc(sizeof (void*) * array->total);
555 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
559 memcpy(tmp, array->data, limit * sizeof(void*));
562 if (i < array->count)
569 for (; i < array->count; ++i)
571 data = eina_array_data_get(array, i);
573 if (keep(data, gdata))
582 /* If we do not keep any object in the array, we should have exited
583 earlier in test (i == array->count). */
587 array->count = total;
593 * @brief Returned a new iterator asociated to an array.
595 * @param array The array.
596 * @return A new iterator.
598 * This function returns a newly allocated iterator associated to
599 * @p array. If @p array is @c NULL or the count member of @p array is
600 * less or equal than 0, this function returns NULL. If the memory can
601 * not be allocated, NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is
602 * set. Otherwise, a valid iterator is returned.
605 eina_array_iterator_new(const Eina_Array *array)
607 Eina_Iterator_Array *it;
609 EINA_MAGIC_CHECK_ARRAY(array);
610 EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
613 it = calloc(1, sizeof (Eina_Iterator_Array));
615 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
619 EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ITERATOR);
620 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
624 it->iterator.next = FUNC_ITERATOR_NEXT(eina_array_iterator_next);
625 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(eina_array_iterator_get_container);
626 it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free);
628 DBG("array=%p, iterator=%p", array, it);
630 return &it->iterator;
634 * @brief Returned a new accessor asociated to an array.
636 * @param array The array.
637 * @return A new accessor.
639 * This function returns a newly allocated accessor associated to
640 * @p array. If @p array is @c NULL or the count member of @p array is
641 * less or equal than 0, this function returns NULL. If the memory can
642 * not be allocated, NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is
643 * set. Otherwise, a valid accessor is returned.
646 eina_array_accessor_new(const Eina_Array *array)
648 Eina_Accessor_Array *it;
650 EINA_MAGIC_CHECK_ARRAY(array);
651 EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
654 it = calloc(1, sizeof (Eina_Accessor_Array));
656 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
660 EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ACCESSOR);
661 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
665 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_array_accessor_get_at);
666 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(eina_array_accessor_get_container);
667 it->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free);
669 DBG("array=%p, accessor=%p", array, it);
671 return &it->accessor;