1 /* EINA - EFL data type library
2 * Copyright (C) 2012 ProFUSION embedded systems
4 * This library 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.
9 * This library 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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
19 #ifndef EINA_INARRAY_H_
20 #define EINA_INARRAY_H_
22 #include "eina_types.h"
23 #include "eina_iterator.h"
24 #include "eina_accessor.h"
27 * @page eina_inarray_example_01 Eina inline array usage
28 * @dontinclude eina_inarray_01.c
30 * This example will create an inline array of chars, add some elements, print
31 * it, re-purpose the array to store ints, add some elements and print that.
33 * We'll start with a function to compare ints we need this because the '>'
34 * operator is not a function and can't be used where Eina_Compare_Cb is needed.
38 * And then move on to the code we actually care about, starting with variable
39 * declarations and eina initialization:
42 * Creating an inline array is very simple, we just need to know what type we
45 * @note The second parameter(the step) is left at zero which means that eina
46 * will choose an appropriate value, this should @b only be changed if it's
47 * known, beforehand, how many elements the array will have.
49 * Once we have an array we can start adding elements to it. Because the
50 * insertion function expect a memory address we have to put the value we want
51 * to store in a variable(this should be no problem since in real world usage
52 * that's usually where the value will be anyways):
54 * @note Because the inline array copies the value given to it we can later
55 * change @c ch, which we do, without affecting the contents of the array.
57 * So let's add some more elements:
62 * We will then iterate over our array and print every position of it. The thing
63 * to note here is not so much the values which will be the expected 'a', 'b',
64 * 'c' and 'd', but rather the memory address of these values, they are
69 * We'll now use our array to store ints, so we need to first erase every member
70 * currently on the array:
73 * And then to be able to store a different type on the same array we use the
74 * eina_inarray_step_set() function, which is just like the eina_inarray_new()
75 * function except it receives already allocated memory. This time we're going
76 * to ask eina to use a step of size 4 because that's how many elements we'll be
77 * putting on the array:
79 * @note Strictly speaking the reason to call eina_inarray_step_set() is not
80 * because we're storing different type, but rather because our types have
81 * different sizes. Eina inline arrays don't actually know anything about types,
82 * they only deal in blocks of memory of a given size.
83 * @note Since eina_inarray_step_set() receives already allocated memory you can(and
84 * it is in fact good practice) use inline arrays not declared as pointers:
87 * eina_inarray_step_set(&arr, sizeof(arr), sizeof(int), 4);
90 * And now to add our integer values to the array:
95 * Just to change things up a bit we've left out the 99 value, but will still
96 * add it in such a way to keep the array ordered. There are many ways to do
97 * this, we could use eina_inarray_insert_at(), or we could change the value
98 * of the last member using eina_inarray_replace_at() and then append the values
99 * in the right order, but for no particular reason we're going to use
100 * eina_inarray_insert_sorted() instead:
101 * @until insert_sorted
103 * We then print the size of our array, and the array itself, much like last
104 * time the values are not surprising, and neither should it be that the memory
105 * addresses are contiguous:
109 * Once done we free our array and shutdown eina:
112 * The source for this example: @ref eina_inarray_01_c
116 * @page eina_inarray_01_c eina_inarray_01.c
117 * @include eina_inarray_01.c
118 * @example eina_inarray_01.c
122 * @page eina_inarray_example_02 Eina inline array of strings
123 * @dontinclude eina_inarray_02.c
125 * This example will create an inline array of strings, add some elements and
126 * then print them. This example is based on @ref eina_array_01_example_page and
127 * @ref eina_inarray_example_01.
129 * We start with some variable declarations and eina initialization:
133 * We then create the array much like we did on @ref eina_inarray_example_01 :
136 * The point were this example significantly differs from the first eina inline
137 * array example. We'll not be adding the strings themselves to the array since
138 * their size varies, we'll store pointer to the strings instead. We therefore
139 * use @c char** to populate our inline array:
142 * The source for this example: @ref eina_inarray_02_c
146 * @page eina_inarray_02_c eina_inarray_02.c
147 * @include eina_inarray_02.c
148 * @example eina_inarray_02.c
152 * @addtogroup Eina_Data_Types_Group Data Types
160 * @addtogroup Eina_Containers_Group Containers
166 * @defgroup Eina_Inline_Array_Group Inline Array
168 * Inline array is a container that stores the data itself not pointers to data,
169 * this means there is no memory fragmentation, also for small data types(such
170 * as char, short, int, etc.) it's more memory efficient.
172 * Usage of the inline array is very similar to that of other
173 * @ref Eina_Containers_Group, like all arrays adding elements to the beginning
174 * of the array is a lot more costly than appending, so those operations should
178 * @li @ref eina_inarray_example_01
179 * @li @ref eina_inarray_example_02
186 * @typedef Eina_Inarray
187 * Inlined array type.
191 typedef struct _Eina_Inarray Eina_Inarray;
194 * Inline array structure, use #Eina_Inarray typedef instead.
196 * Do not modify these fields directly, use eina_inarray_step_set() or
197 * eina_inarray_new() instead.
203 #define EINA_ARRAY_VERSION 1
204 int version; /**< Should match EINA_ARRAY_VERSION used when compiled your apps, provided for ABI compatibility */
206 unsigned int member_size; /**< byte size of each entry in members */
207 unsigned int len; /**< number of elements used in members */
208 unsigned int max; /**< number of elements allocated in members */
209 unsigned int step; /**< amount to grow number of members allocated */
210 void *members; /**< actual array of elements */
215 * @brief Create new inline array.
217 * @param member_size size of each member in the array.
218 * @param step when resizing the array, do this using the following
220 * @return The new inline array table or @c NULL on failure.
222 * Create a new array where members are inlined in a sequence. Each
223 * member has @a member_size bytes.
225 * If the @a step is 0, then a safe default is chosen.
227 * On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is
228 * set. If @a member_size is zero, then @c NULL is returned.
230 * @see eina_inarray_free()
234 EAPI Eina_Inarray *eina_inarray_new(unsigned int member_size,
235 unsigned int step) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
238 * @brief Free array and its members.
239 * @param array array object
241 * @see eina_inarray_flush()
245 EAPI void eina_inarray_free(Eina_Inarray *array) EINA_ARG_NONNULL(1);
248 * @brief Initialize inline array.
249 * @param array array object to initialize.
250 * @param member_size size of each member in the array.
251 * @param step when resizing the array, do this using the following
254 * Initialize array. If the @a step is @c 0, then a safe default is
257 * This is useful for arrays inlined into other structures or
258 * allocated at stack.
260 * @see eina_inarray_flush()
264 EAPI void eina_inarray_step_set(Eina_Inarray *array,
265 unsigned int sizeof_eina_inarray,
266 unsigned int member_size,
267 unsigned int step) EINA_ARG_NONNULL(1);
270 * @brief Remove every member from array.
271 * @param array array object
275 EAPI void eina_inarray_flush(Eina_Inarray *array) EINA_ARG_NONNULL(1);
278 * @brief Copy the data as the last member of the array.
279 * @param array array object
280 * @param data data to be copied at the end
281 * @return the index of the new member or -1 on errors.
283 * Copies the given pointer contents at the end of the array. The
284 * pointer is not referenced, instead it's contents is copied to the
285 * members array using the previously defined @c member_size.
287 * @see eina_inarray_insert_at().
291 EAPI int eina_inarray_push(Eina_Inarray *array,
292 const void *data) EINA_ARG_NONNULL(1, 2);
295 * @brief Copy the data to array at position found by comparison function
296 * @param array array object
297 * @param data data to be copied
298 * @param compare compare function
299 * @return the index of the new member or @c -1 on errors.
301 * Copies the given pointer contents at the array position defined by
302 * given @a compare function. The pointer is not referenced, instead
303 * it's contents is copied to the members array using the previously
304 * defined @c member_size.
306 * The data given to @a compare function are the pointer to member
307 * memory itself, do no change it.
309 * @see eina_inarray_insert_sorted()
310 * @see eina_inarray_insert_at()
311 * @see eina_inarray_push()
315 EAPI int eina_inarray_insert(Eina_Inarray *array,
317 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
320 * @brief Copy the data to array at position found by comparison function
321 * @param array array object
322 * @param data data to be copied
323 * @param compare compare function
324 * @return the index of the new member or @c -1 on errors.
326 * Copies the given pointer contents at the array position defined by
327 * given @a compare function. The pointer is not referenced, instead
328 * it's contents is copied to the members array using the previously
329 * defined @c member_size.
331 * The data given to @a compare function are the pointer to member
332 * memory itself, do no change it.
334 * This variation will optimize insertion position assuming the array
335 * is already sorted by doing binary search.
337 * @see eina_inarray_sort()
341 EAPI int eina_inarray_insert_sorted(Eina_Inarray *array,
343 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
346 * @brief Find data and remove matching member
347 * @param array array object
348 * @param data data to be found and removed
349 * @return the index of the removed member or @c -1 on errors.
351 * Find data in the array and remove it. Data may be an existing
352 * member of array (then optimized) or the contents will be matched
355 * @see eina_inarray_pop()
356 * @see eina_inarray_remove_at()
360 EAPI int eina_inarray_remove(Eina_Inarray *array,
361 const void *data) EINA_ARG_NONNULL(1, 2);
364 * @brief Removes the last member of the array
365 * @param array array object
366 * @return the data poped out of the array.
368 * Note: The data could be considered valid only until any other operation touch the Inarray.
372 EAPI void *eina_inarray_pop(Eina_Inarray *array) EINA_ARG_NONNULL(1);
375 * @brief Get the member at given position
376 * @param array array object
377 * @param position member position
378 * @return pointer to current member memory.
380 * Gets the member given its position in the array. It is a pointer to
381 * its current memory, then it can be invalidated with functions that
382 * changes the array such as eina_inarray_push(),
383 * eina_inarray_insert_at() or eina_inarray_remove_at() or variants.
385 * See also eina_inarray_lookup() and eina_inarray_lookup_sorted().
389 EAPI void *eina_inarray_nth(const Eina_Inarray *array,
390 unsigned int position) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
393 * @brief Copy the data at given position in the array
394 * @param array array object
395 * @param position where to insert the member
396 * @param data data to be copied at position
397 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
399 * Copies the given pointer contents at the given @a position in the
400 * array. The pointer is not referenced, instead it's contents is
401 * copied to the members array using the previously defined
404 * All the members from @a position to the end of the array are
405 * shifted to the end.
407 * If @a position is equal to the end of the array (equals to
408 * eina_inarray_count()), then the member is appended.
410 * If @a position is bigger than the array length, it will fail.
414 EAPI Eina_Bool eina_inarray_insert_at(Eina_Inarray *array,
415 unsigned int position,
416 const void *data) EINA_ARG_NONNULL(1, 3);
419 * @brief Opens a space at given position, returning its pointer.
420 * @param array array object
421 * @param position where to insert first member (open/allocate space)
422 * @param member_count how many times member_size bytes will be allocated.
423 * @return pointer to first member memory allocated or @c NULL on errors.
425 * This is similar to eina_inarray_insert_at(), but useful if the
426 * members contents are still unknown or unallocated. It will make
427 * room for the required number of items and return the pointer to the
428 * first item, similar to malloc(member_count * member_size), with the
429 * guarantee all memory is within members array.
431 * The new member memory is undefined, it's not automatically zeroed.
433 * All the members from @a position to the end of the array are
434 * shifted to the end.
436 * If @a position is equal to the end of the array (equals to
437 * eina_inarray_count()), then the member is appended.
439 * If @a position is bigger than the array length, it will fail.
443 EAPI void *eina_inarray_alloc_at(Eina_Inarray *array,
444 unsigned int position,
445 unsigned int member_count) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
448 * @brief Copy the data over the given position.
449 * @param array array object
450 * @param position where to replace the member
451 * @param data data to be copied at position
452 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
454 * Copies the given pointer contents at the given @a position in the
455 * array. The pointer is not referenced, instead it's contents is
456 * copied to the members array using the previously defined
459 * If @a position does not exist, it will fail.
463 EAPI Eina_Bool eina_inarray_replace_at(Eina_Inarray *array,
464 unsigned int position,
465 const void *data) EINA_ARG_NONNULL(1, 3);
468 * @brief Remove member at given position
469 * @param array array object
470 * @param position position to be removed
471 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
473 * The member is removed from array and any members after it are moved
474 * towards the array head.
476 * See also eina_inarray_pop() and eina_inarray_remove().
480 EAPI Eina_Bool eina_inarray_remove_at(Eina_Inarray *array,
481 unsigned int position) EINA_ARG_NONNULL(1);
484 * @brief Reverse members in the array.
485 * @param array array object
487 * If you do not want to change the array, just walk its elements
488 * backwards, then use EINA_INARRAY_REVERSE_FOREACH() macro.
490 * @see EINA_INARRAY_REVERSE_FOREACH()
494 EAPI void eina_inarray_reverse(Eina_Inarray *array) EINA_ARG_NONNULL(1);
497 * @brief Applies quick sort to array
498 * @param array array object
499 * @param compare compare function
501 * Applies quick sort to the @a array.
503 * The data given to @a compare function are the pointer to member
504 * memory itself, do no change it.
506 * @see eina_inarray_insert_sorted()
510 EAPI void eina_inarray_sort(Eina_Inarray *array,
511 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2);
514 * @brief Search member (linear walk)
515 * @param array array object
516 * @param data member to search using @a compare function.
517 * @param compare compare function
518 * @return the member index or -1 if not found.
520 * Walks array linearly looking for given data as compared by
521 * @a compare function.
523 * The data given to @a compare function are the pointer to member
524 * memory itself, do no change it.
526 * See also eina_inarray_lookup_sorted().
530 EAPI int eina_inarray_search(const Eina_Inarray *array,
532 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
535 * @brief Search member (binary search walk)
536 * @param array array object
537 * @param data member to search using @a compare function.
538 * @param compare compare function
539 * @return the member index or @c -1 if not found.
541 * Uses binary search for given data as compared by @a compare function.
543 * The data given to @a compare function are the pointer to member
544 * memory itself, do no change it.
548 EAPI int eina_inarray_search_sorted(const Eina_Inarray *array,
550 Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
553 * @brief Call function for each array member
554 * @param array array object
555 * @param function callback function
556 * @param user_data user data given to callback @a function
557 * @return #EINA_TRUE if it successfully iterate all items of the array.
559 * Call @a function for every given data in @a array.
561 * Safe way to iterate over an array. @p function should return #EINA_TRUE
562 * as long as you want the function to continue iterating, by
563 * returning #EINA_FALSE it will stop and return #EINA_FALSE as a result.
565 * The data given to @a function are the pointer to member memory
568 * @see EINA_INARRAY_FOREACH()
572 EAPI Eina_Bool eina_inarray_foreach(const Eina_Inarray *array,
573 Eina_Each_Cb function,
574 const void *user_data) EINA_ARG_NONNULL(1, 2);
577 * @brief Remove all members that matched.
578 * @param array array object
579 * @param match match function
580 * @param user_data user data given to callback @a match.
581 * @return number of removed entries or -1 on error.
583 * Remove all entries in the @a array where @a match function
584 * returns #EINA_TRUE.
588 EAPI int eina_inarray_foreach_remove(Eina_Inarray *array,
590 const void *user_data) EINA_ARG_NONNULL(1, 2);
593 * @brief number of members in array.
594 * @param array array object
595 * @return number of members in array.
599 EAPI unsigned int eina_inarray_count(const Eina_Inarray *array) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
602 * @brief Returned a new iterator associated to an array.
603 * @param array array object
604 * @return A new iterator.
606 * This function returns a newly allocated iterator associated to
609 * If the memory can not be allocated, @c NULL is returned
610 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
613 * @warning if the array structure changes then the iterator becomes
614 * invalid! That is, if you add or remove members this
615 * iterator behavior is undefined and your program may crash!
619 EAPI Eina_Iterator *eina_inarray_iterator_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
622 * @brief Returned a new reversed iterator associated to an array.
623 * @param array array object
624 * @return A new iterator.
626 * This function returns a newly allocated iterator associated to
629 * Unlike eina_inarray_iterator_new(), this will walk the array backwards.
631 * If the memory can not be allocated, @c NULL is returned
632 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
635 * @warning if the array structure changes then the iterator becomes
636 * invalid! That is, if you add or remove nodes this iterator
637 * behavior is undefined and your program may crash!
641 EAPI Eina_Iterator *eina_inarray_iterator_reversed_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
644 * @brief Returned a new accessor associated to an array.
645 * @param array array object
646 * @return A new accessor.
648 * This function returns a newly allocated accessor associated to
651 * If the memory can not be allocated, @c NULL is returned
652 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid accessor is
657 EAPI Eina_Accessor *eina_inarray_accessor_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
660 * @def EINA_INARRAY_FOREACH
661 * @brief walks array linearly from head to tail
662 * @param array array object
663 * @param itr the iterator pointer
665 * @a itr must be a pointer with sizeof(itr*) == array->member_size.
667 * @warning This is fast as it does direct pointer access, but it will
668 * not check for @c NULL pointers or invalid array object!
669 * See eina_inarray_foreach() to do that.
671 * @warning Do not modify array as you walk it! If that is desired,
672 * then use eina_inarray_foreach_remove()
676 #define EINA_INARRAY_FOREACH(array, itr) \
677 for ((itr) = (array)->members; \
678 (itr) < (((typeof(*itr)*)(array)->members) + (array)->len); \
682 * @def EINA_INARRAY_REVERSE_FOREACH
683 * @brief walks array linearly from tail to head
684 * @param array array object
685 * @param itr the iterator pointer
687 * @a itr must be a pointer with sizeof(itr*) == array->member_size.
689 * @warning This is fast as it does direct pointer access, but it will
690 * not check for @c NULL pointers or invalid array object!
692 * @warning Do not modify array as you walk it! If that is desired,
693 * then use eina_inarray_foreach_remove()
697 #define EINA_INARRAY_REVERSE_FOREACH(array, itr) \
698 for ((itr) = ((((typeof(*(itr))*)(array)->members) + (array)->len) - 1); \
699 (((itr) >= (typeof(*(itr))*)(array)->members) \
700 && ((array)->members != NULL)); \
715 #endif /*EINA_INARRAY_H_*/