* Detect fault during access to Eina_File mmap memory, use eina_file_map_faulted
to learn if it happens.
* Add eina_file_xattr_get and eina_file_xattr_value_get.
+
+2012-01-09 Gustavo Barbieri
+
+ * Add eina_inarray data type.
* Eina_Xattr iterator : eina_xattr_value_fd_ls and eina_xattr_value_ls API
* eina_file_map_faulted API
* Xattr iterator for Eina_File : eina_file_xattr_get and eina_file_xattr_value_get API
+ * Added eina_inarray data type
Eina 1.1.0
* Linux, BSD, Opensolaris and Windows (XP and CE).
*
* The data types that are available are (see @ref Eina_Data_Types_Group):
+ * @li @ref Eina_Inarray_Group standard array of inlined members.
* @li @ref Eina_Array_Group standard array of @c void* data.
* @li @ref Eina_Hash_Group standard hash of @c void* data.
* @li @ref Eina_Inline_List_Group list with nodes inlined into user type.
#include "eina_mempool.h"
#include "eina_error.h"
#include "eina_log.h"
+#include "eina_inarray.h"
#include "eina_array.h"
#include "eina_binshare.h"
#include "eina_stringshare.h"
eina_lalloc.h \
eina_clist.h \
eina_inline_clist.x \
+eina_inarray.h \
eina_inlist.h \
eina_list.h \
eina_file.h \
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EINA_INARRAY_H_
+#define EINA_INARRAY_H_
+
+#include "eina_types.h"
+#include "eina_iterator.h"
+#include "eina_accessor.h"
+
+/**
+ * @addtogroup Eina_Data_Types_Group Data Types
+ *
+ * @{
+ */
+
+/**
+ * @addtogroup Eina_Containers_Group Containers
+ *
+ * @{
+ */
+
+/**
+ * @defgroup Eina_Inline_Array_Group Inline Array
+ *
+ * @{
+ */
+
+
+/**
+ * @typedef Eina_Inarray
+ * Inlined array type.
+ */
+typedef struct _Eina_Inarray Eina_Inarray;
+
+/**
+ * Inline array structure, use #Eina_Inarray typedef instead.
+ *
+ * Do not modify these fields directly, use eina_inarray_setup() or
+ * eina_inarray_new() instead.
+ */
+struct _Eina_Inarray
+{
+ unsigned int member_size; /**< byte size of each entry in members */
+ unsigned int len; /**< number of elements used in members */
+ unsigned int max; /**< number of elements allocated in members */
+ unsigned int step; /**< amount to grow number of members allocated */
+ void *members; /**< actual array of elements */
+ EINA_MAGIC
+};
+
+/**
+ * @brief Create new inline array.
+ *
+ * @param member_size size of each member in the array.
+ * @param step when resizing the array, do this using the following
+ * extra amount.
+ * @return The new inline array table or @c NULL on failure.
+ *
+ * Create a new array where members are inlined in a sequence. Each
+ * member has @a member_size bytes.
+ *
+ * If the @a step is 0, then a safe default is chosen.
+ *
+ * On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is
+ * set. If @a member_size is zero, then @c NULL is returned.
+ *
+ * @see eina_inarray_free()
+ */
+EAPI Eina_Inarray *eina_inarray_new(unsigned int member_size,
+ unsigned int step) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Free array and its members.
+ * @param array array object
+ *
+ * @see eina_inarray_flush()
+ */
+EAPI void eina_inarray_free(Eina_Inarray *array) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Initialize inline array.
+ * @param array array object to initialize.
+ * @param member_size size of each member in the array.
+ * @param step when resizing the array, do this using the following
+ * extra amount.
+ *
+ * Initialize array. If the @a step is 0, then a safe default is
+ * chosen.
+ *
+ * This is useful for arrays inlined into other structures or
+ * allocated at stack.
+ *
+ * @see eina_inarray_flush()
+ */
+EAPI void eina_inarray_setup(Eina_Inarray *array,
+ unsigned int member_size,
+ unsigned int step) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Remove every member from array.
+ * @param array array object
+ */
+EAPI void eina_inarray_flush(Eina_Inarray *array) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Copy the data as the last member of the array.
+ * @param array array object
+ * @param data data to be copied at the end
+ * @return the index of the new member or -1 on errors.
+ *
+ * Copies the given pointer contents at the end of the array. The
+ * pointer is not referenced, instead it's contents is copied to the
+ * members array using the previously defined @c member_size.
+ *
+ * @see eina_inarray_insert_at().
+ */
+EAPI int eina_inarray_append(Eina_Inarray *array,
+ const void *data) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief Copy the data to array at position found by comparison function
+ * @param array array object
+ * @param data data to be copied
+ * @param compare compare function
+ * @return the index of the new member or -1 on errors.
+ *
+ * Copies the given pointer contents at the array position defined by
+ * given @a compare function. The pointer is not referenced, instead
+ * it's contents is copied to the members array using the previously
+ * defined @c member_size.
+ *
+ * The data given to @a compare function are the pointer to member
+ * memory itself, do no change it.
+ *
+ * @see eina_inarray_insert_sorted()
+ * @see eina_inarray_insert_at()
+ * @see eina_inarray_append()
+ */
+EAPI int eina_inarray_insert(Eina_Inarray *array,
+ const void *data,
+ Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
+
+/**
+ * @brief Copy the data to array at position found by comparison function
+ * @param array array object
+ * @param data data to be copied
+ * @param compare compare function
+ * @return the index of the new member or -1 on errors.
+ *
+ * Copies the given pointer contents at the array position defined by
+ * given @a compare function. The pointer is not referenced, instead
+ * it's contents is copied to the members array using the previously
+ * defined @c member_size.
+ *
+ * The data given to @a compare function are the pointer to member
+ * memory itself, do no change it.
+ *
+ * This variation will optimize insertion position assuming the array
+ * is already sorted by doing binary search.
+ *
+ * @see eina_inarray_sort()
+ */
+EAPI int eina_inarray_insert_sorted(Eina_Inarray *array,
+ const void *data,
+ Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
+
+/**
+ * @brief Find data and remove matching member
+ * @param array array object
+ * @param data data to be found and removed
+ * @return the index of the removed member or -1 on errors.
+ *
+ * Find data in the array and remove it. Data may be an existing
+ * member of array (then optimized) or the contents will be matched
+ * using memcmp().
+ *
+ * @see eina_inarray_pop()
+ * @see eina_inarray_remove_at()
+ */
+EAPI int eina_inarray_remove(Eina_Inarray *array,
+ const void *data) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief Removes the last member of the array
+ * @param array array object
+ * @return the index of the removed member or -1 on errors.
+ */
+EAPI int eina_inarray_pop(Eina_Inarray *array) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Get the member at given position
+ * @param array array object
+ * @param position member position
+ * @return pointer to current member memory.
+ *
+ * Gets the member given its position in the array. It is a pointer to
+ * its current memory, then it can be invalidated with functions that
+ * changes the array such as eina_inarray_append(),
+ * eina_inarray_insert_at() or eina_inarray_remove_at() or variants.
+ *
+ * See also eina_inarray_lookup() and eina_inarray_lookup_sorted().
+ */
+EAPI void *eina_inarray_nth(const Eina_Inarray *array,
+ unsigned int position) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Copy the data at given position in the array
+ * @param array array object
+ * @param position where to insert the member
+ * @param data data to be copied at position
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * Copies the given pointer contents at the given @a position in the
+ * array. The pointer is not referenced, instead it's contents is
+ * copied to the members array using the previously defined
+ * @c member_size.
+ *
+ * All the members from @a position to the end of the array are
+ * shifted to the end.
+ *
+ * If @a position is equal to the end of the array (equals to
+ * eina_inarray_count()), then the member is appended.
+ *
+ * If @a position is bigger than the array length, it will fail.
+ */
+EAPI Eina_Bool eina_inarray_insert_at(Eina_Inarray *array,
+ unsigned int position,
+ const void *data) EINA_ARG_NONNULL(1, 3);
+
+/**
+ * @brief Remove member at given position
+ * @param array array object
+ * @param position position to be removed
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * The member is removed from array and any members after it are moved
+ * towards the array head.
+ *
+ * See also eina_inarray_pop() and eina_inarray_remove().
+ */
+EAPI Eina_Bool eina_inarray_remove_at(Eina_Inarray *array,
+ unsigned int position) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Reverse members in the array.
+ * @param array array object
+ *
+ * If you do not want to change the array, just walk its elements
+ * backwards, then use EINA_INARRAY_REVERSE_FOREACH() macro.
+ *
+ * @see EINA_INARRAY_REVERSE_FOREACH()
+ */
+EAPI void eina_inarray_reverse(Eina_Inarray *array) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Applies quick sort to array
+ * @param array array object
+ * @param compare compare function
+ *
+ * Applies quick sort to the @a array.
+ *
+ * The data given to @a compare function are the pointer to member
+ * memory itself, do no change it.
+ *
+ * @see eina_inarray_insert_sorted()
+ */
+EAPI void eina_inarray_sort(Eina_Inarray *array,
+ Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief Search member (linear walk)
+ * @param array array object
+ * @param data member to search using @a compare function.
+ * @param compare compare function
+ * @return the member index or -1 if not found.
+ *
+ * Walks array linearly looking for given data as compared by
+ * @a compare function.
+ *
+ * The data given to @a compare function are the pointer to member
+ * memory itself, do no change it.
+ *
+ * See also eina_inarray_lookup_sorted().
+ */
+EAPI int eina_inarray_search(const Eina_Inarray *array,
+ const void *data,
+ Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
+
+/**
+ * @brief Search member (binary search walk)
+ * @param array array object
+ * @param data member to search using @a compare function.
+ * @param compare compare function
+ * @return the member index or -1 if not found.
+ *
+ * Uses binary search for given data as compared by @a compare function.
+ *
+ * The data given to @a compare function are the pointer to member
+ * memory itself, do no change it.
+ */
+EAPI int eina_inarray_search_sorted(const Eina_Inarray *array,
+ const void *data,
+ Eina_Compare_Cb compare) EINA_ARG_NONNULL(1, 2, 3);
+
+/**
+ * @brief Call function for each array member
+ * @param array array object
+ * @param function callback function
+ * @param user_data user data given to callback @a function
+ * @return #EINA_TRUE if it successfully iterate all items of the array.
+ *
+ * Call @a function for every given data in @a array.
+ *
+ * Safe way to iterate over an array. @p function should return
+ * #EINA_TRUE as long as you want the function to continue iterating,
+ * by returning #EINA_FALSE it will stop and return #EINA_FALSE as a
+ * result.
+ *
+ * The data given to @a function are the pointer to member memory
+ * itself.
+ *
+ * @see EINA_INARRAY_FOREACH()
+ */
+EAPI Eina_Bool eina_inarray_foreach(const Eina_Inarray *array,
+ Eina_Each_Cb function,
+ const void *user_data) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief Remove all members that matched.
+ * @param array array object
+ * @param match match function
+ * @param user_data user data given to callback @a match.
+ * @return number of removed entries or -1 on error.
+ *
+ * Remove all entries in the @a array where @a match function
+ * returns #EINA_TRUE.
+ */
+EAPI int eina_inarray_foreach_remove(Eina_Inarray *array,
+ Eina_Each_Cb match,
+ const void *user_data) EINA_ARG_NONNULL(1, 2);
+
+/**
+ * @brief number of members in array.
+ * @param array array object
+ * @return number of members in array.
+ */
+EAPI unsigned int eina_inarray_count(const Eina_Inarray *array) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @brief Returned a new iterator associated to an array.
+ * @param array array object
+ * @return A new iterator.
+ *
+ * This function returns a newly allocated iterator associated to
+ * @p array.
+ *
+ * If the memory can not be allocated, NULL is returned and
+ * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
+ * returned.
+ *
+ * @warning if the array structure changes then the iterator becomes
+ * invalid! That is, if you add or remove members this
+ * iterator behavior is undefined and your program may crash!
+ */
+EAPI Eina_Iterator *eina_inarray_iterator_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Returned a new reversed iterator associated to an array.
+ * @param array array object
+ * @return A new iterator.
+ *
+ * This function returns a newly allocated iterator associated to
+ * @p array.
+ *
+ * Unlike eina_inarray_iterator_new(), this will walk the array backwards.
+ *
+ * If the memory can not be allocated, NULL is returned and
+ * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
+ * returned.
+ *
+ * @warning if the array structure changes then the iterator becomes
+ * invalid! That is, if you add or remove nodes this iterator
+ * behavior is undefined and your program may crash!
+ */
+EAPI Eina_Iterator *eina_inarray_iterator_reversed_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Returned a new accessor associated to an array.
+ * @param array array object
+ * @return A new accessor.
+ *
+ * This function returns a newly allocated accessor associated to
+ * @p array.
+ *
+ * If the memory can not be allocated, NULL is returned and
+ * #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid accessor is
+ * returned.
+ */
+EAPI Eina_Accessor *eina_inarray_accessor_new(const Eina_Inarray *array) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+
+/**
+ * @def EINA_INARRAY_FOREACH
+ * @brief walks array linearly from head to tail
+ * @param array array object
+ * @param itr the iterator pointer
+ *
+ * @a itr must be a pointer with sizeof(itr*) == array->member_size.
+ *
+ * @warning This is fast as it does direct pointer access, but it will
+ * not check for @c NULL pointers or invalid array object!
+ * See eina_inarray_foreach() to do that.
+ *
+ * @warning Do not modify array as you walk it! If that is desired,
+ * then use eina_inarray_foreach_remove()
+ */
+#define EINA_INARRAY_FOREACH(array, itr) \
+ for ((itr) = array->members; \
+ (itr) < (((typeof(*itr)*)array->members) + array->len); \
+ (itr)++)
+
+/**
+ * @def EINA_INARRAY_REVERSE_FOREACH
+ * @brief walks array linearly from tail to head
+ * @param array array object
+ * @param itr the iterator pointer
+ *
+ * @a itr must be a pointer with sizeof(itr*) == array->member_size.
+ *
+ * @warning This is fast as it does direct pointer access, but it will
+ * not check for @c NULL pointers or invalid array object!
+ *
+ * @warning Do not modify array as you walk it! If that is desired,
+ * then use eina_inarray_foreach_remove()
+ */
+#define EINA_INARRAY_REVERSE_FOREACH(array, itr) \
+ for ((itr) = ((((typeof(*(itr))*)array->members) + array->len) - 1); \
+ (((itr) >= (typeof(*(itr))*)array->members) \
+ && (array->members != NULL)); \
+ (itr)--)
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /*EINA_INARRAY_H_*/
eina_fp.c \
eina_hamster.c \
eina_hash.c \
+eina_inarray.c \
eina_inlist.c \
eina_iterator.c \
eina_lalloc.c \
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2012 - ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "eina_config.h"
+#include "eina_private.h"
+#include "eina_error.h"
+#include "eina_log.h"
+
+/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
+#include "eina_safety_checks.h"
+#include "eina_inarray.h"
+
+/*============================================================================*
+* Local *
+*============================================================================*/
+
+/**
+ * @cond LOCAL
+ */
+
+static const char EINA_MAGIC_INARRAY_STR[] = "Eina Inline Array";
+static const char EINA_MAGIC_INARRAY_ITERATOR_STR[] = "Eina Inline Array Iterator";
+static const char EINA_MAGIC_INARRAY_ACCESSOR_STR[] = "Eina Inline Array Accessor";
+
+typedef struct _Eina_Iterator_Inarray Eina_Iterator_Inarray;
+typedef struct _Eina_Accessor_Inarray Eina_Accessor_Inarray;
+
+struct _Eina_Iterator_Inarray
+{
+ Eina_Iterator iterator;
+ const Eina_Inarray *array;
+ unsigned int pos;
+ EINA_MAGIC
+};
+
+struct _Eina_Accessor_Inarray
+{
+ Eina_Accessor accessor;
+ const Eina_Inarray *array;
+ EINA_MAGIC
+};
+
+static int _eina_inarray_log_dom = -1;
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_eina_inarray_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_eina_inarray_log_dom, __VA_ARGS__)
+
+#define EINA_MAGIC_CHECK_INARRAY(d, ...) \
+ do \
+ { \
+ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY)) \
+ { \
+ EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY); \
+ return __VA_ARGS__; \
+ } \
+ eina_error_set(0); \
+ } \
+ while(0)
+
+#define EINA_MAGIC_CHECK_INARRAY_ITERATOR(d, ...) \
+ do \
+ { \
+ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ITERATOR)) \
+ { \
+ EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ITERATOR); \
+ return __VA_ARGS__; \
+ } \
+ eina_error_set(0); \
+ } \
+ while(0)
+
+#define EINA_MAGIC_CHECK_INARRAY_ACCESSOR(d, ...) \
+ do \
+ { \
+ if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ACCESSOR)) \
+ { \
+ EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ACCESSOR); \
+ return __VA_ARGS__; \
+ } \
+ eina_error_set(0); \
+ } \
+ while(0)
+
+static void
+_eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step)
+{
+ EINA_MAGIC_SET(array, EINA_MAGIC_INARRAY);
+ array->member_size = member_size;
+ array->len = 0;
+ array->max = 0;
+ array->step = (step > 0) ? step : 32;
+ array->members = NULL;
+}
+
+static Eina_Bool
+_eina_inarray_resize(Eina_Inarray *array, unsigned int new_size)
+{
+ unsigned int new_max;
+ void *tmp;
+
+ if (new_size < array->max)
+ return EINA_TRUE;
+
+ if (new_size % array->step == 0)
+ new_max = new_size;
+ else
+ new_max = ((new_size / array->step) + 1) * array->step;
+
+ tmp = realloc(array->members, new_max * array->member_size);
+ if ((!tmp) && (new_max > 0))
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return EINA_FALSE;
+ }
+
+ array->members = tmp;
+ array->max = new_max;
+ return EINA_TRUE;
+}
+
+static inline void *
+_eina_inarray_get(const Eina_Inarray *array, unsigned int position)
+{
+ unsigned int offset = position * array->member_size;
+ return (unsigned char *)array->members + offset;
+}
+
+static int
+_eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
+{
+ const unsigned char *start, *found;
+ start = array->members;
+ found = bsearch(data, start, array->len, array->member_size, compare);
+ if (!found)
+ return -1;
+ return (found - start) / array->member_size;
+}
+
+static unsigned int
+_eina_inarray_search_sorted_near(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare, int *cmp)
+{
+ unsigned int start, last, middle;
+
+ if (array->len == 0)
+ {
+ *cmp = -1;
+ return 0;
+ }
+ else if (array->len == 1)
+ {
+ *cmp = compare(data, array->members);
+ return 0;
+ }
+
+ start = 0;
+ last = array->len - 1; /* inclusive */
+ do
+ {
+ void *p;
+ middle = start + (last - start) / 2; /* avoid overflow */
+ p = _eina_inarray_get(array, middle);
+ *cmp = compare(data, p);
+ if (*cmp == 0)
+ return middle;
+ else if (*cmp > 0)
+ start = middle + 1;
+ else if (middle > 0)
+ last = middle - 1;
+ else
+ break;
+ }
+ while (start <= last);
+ return middle;
+}
+
+
+static Eina_Bool
+_eina_inarray_iterator_next(Eina_Iterator_Inarray *it, void **data)
+{
+ EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE);
+
+ if (it->pos >= it->array->len)
+ return EINA_FALSE;
+
+ *data = _eina_inarray_get(it->array, it->pos);
+ it->pos++;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_eina_inarray_iterator_prev(Eina_Iterator_Inarray *it, void **data)
+{
+ EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE);
+
+ if (it->pos == 0)
+ return EINA_FALSE;
+
+ it->pos--;
+ *data = _eina_inarray_get(it->array, it->pos);
+
+ return EINA_TRUE;
+}
+
+static Eina_Inarray *
+_eina_inarray_iterator_get_container(Eina_Iterator_Inarray *it)
+{
+ EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, NULL);
+ return (Eina_Inarray *)it->array;
+}
+
+static void
+_eina_inarray_iterator_free(Eina_Iterator_Inarray *it)
+{
+ EINA_MAGIC_CHECK_INARRAY_ITERATOR(it);
+ MAGIC_FREE(it);
+}
+
+static Eina_Bool
+_eina_inarray_accessor_get_at(Eina_Accessor_Inarray *it, unsigned int pos, void **data)
+{
+ EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, EINA_FALSE);
+
+ if (pos >= it->array->len)
+ return EINA_FALSE;
+
+ *data = _eina_inarray_get(it->array, pos);
+ return EINA_TRUE;
+}
+
+static Eina_Inarray *
+_eina_inarray_accessor_get_container(Eina_Accessor_Inarray *it)
+{
+ EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, NULL);
+ return (Eina_Inarray *)it->array;
+}
+
+static void
+_eina_inarray_accessor_free(Eina_Accessor_Inarray *it)
+{
+ EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it);
+ MAGIC_FREE(it);
+}
+
+/**
+ * @endcond
+ */
+
+
+/*============================================================================*
+* Global *
+*============================================================================*/
+
+/**
+ * @internal
+ * @brief Initialize the inline array module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function sets up the inline array module of Eina. It is called
+ * by eina_init().
+ *
+ * @see eina_init()
+ */
+Eina_Bool
+eina_inarray_init(void)
+{
+ _eina_inarray_log_dom = eina_log_domain_register("eina_inarray",
+ EINA_LOG_COLOR_DEFAULT);
+ if (_eina_inarray_log_dom < 0)
+ {
+ EINA_LOG_ERR("Could not register log domain: eina_inarray");
+ return EINA_FALSE;
+ }
+
+#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
+ EMS(EINA_MAGIC_INARRAY);
+ EMS(EINA_MAGIC_INARRAY_ITERATOR);
+ EMS(EINA_MAGIC_INARRAY_ACCESSOR);
+#undef EMS
+
+ return EINA_TRUE;
+}
+
+/**
+ * @internal
+ * @brief Shut down the inline array module.
+ *
+ * @return #EINA_TRUE on success, #EINA_FALSE on failure.
+ *
+ * This function shuts down the inline array module set up by
+ * eina_inarray_init(). It is called by eina_shutdown().
+ *
+ * @see eina_shutdown()
+ */
+Eina_Bool
+eina_inarray_shutdown(void)
+{
+ eina_log_domain_unregister(_eina_inarray_log_dom);
+ _eina_inarray_log_dom = -1;
+ return EINA_TRUE;
+}
+
+/*============================================================================*
+* API *
+*============================================================================*/
+EAPI Eina_Inarray *
+eina_inarray_new(unsigned int member_size, unsigned int step)
+{
+ Eina_Inarray *ret;
+
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(member_size == 0, NULL);
+
+ ret = malloc(sizeof(*ret));
+ if (!ret)
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+ eina_error_set(0);
+ _eina_inarray_setup(ret, member_size, step);
+ return ret;
+}
+
+EAPI void
+eina_inarray_free(Eina_Inarray *array)
+{
+ EINA_MAGIC_CHECK_INARRAY(array);
+ free(array->members);
+ free(array);
+}
+
+EAPI void
+eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step)
+{
+ EINA_SAFETY_ON_NULL_RETURN(array);
+ EINA_SAFETY_ON_TRUE_RETURN(member_size == 0);
+ _eina_inarray_setup(array, member_size, step);
+}
+
+EAPI void
+eina_inarray_flush(Eina_Inarray *array)
+{
+ EINA_MAGIC_CHECK_INARRAY(array);
+ free(array->members);
+ array->len = 0;
+ array->max = 0;
+ array->members = NULL;
+}
+
+EAPI int
+eina_inarray_append(Eina_Inarray *array, const void *data)
+{
+ void *p;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+
+ if (!_eina_inarray_resize(array, array->len + 1))
+ return -1;
+
+ p = _eina_inarray_get(array, array->len);
+ memcpy(p, data, array->member_size);
+
+ array->len++;
+ return array->len - 1;
+}
+
+EAPI int
+eina_inarray_insert(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
+{
+ const unsigned char *itr, *itr_end;
+ unsigned int sz;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
+
+ sz = array->member_size;
+ itr = array->members;
+ itr_end = itr + array->len * sz;
+ for (; itr < itr_end; itr += sz)
+ {
+ unsigned int offset, position;
+ int cmp = compare(itr, data);
+ if (cmp <= 0)
+ continue;
+
+ offset = itr - (unsigned char *)array->members;
+ position = offset / sz;
+ if (!eina_inarray_insert_at(array, position, data))
+ return -1;
+ return position;
+ }
+ return eina_inarray_append(array, data);
+}
+
+EAPI int
+eina_inarray_insert_sorted(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
+{
+ unsigned int pos;
+ int cmp;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
+
+ pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp);
+ if (cmp > 0)
+ pos++;
+
+ if (!eina_inarray_insert_at(array, pos, data))
+ return -1;
+ return pos;
+}
+
+EAPI int
+eina_inarray_remove(Eina_Inarray *array, const void *data)
+{
+ const unsigned char *itr, *itr_end;
+ unsigned int position, sz;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+
+ sz = array->member_size;
+ if ((data >= array->members) &&
+ (data < _eina_inarray_get(array, array->len)))
+ {
+ unsigned int offset = ((unsigned char *)data -
+ (unsigned char *)array->members);
+ position = offset / sz;
+ goto found;
+ }
+
+ itr = array->members;
+ itr_end = itr + array->len * sz;
+ for (; itr < itr_end; itr += sz)
+ {
+ if (memcmp(data, itr, sz) == 0)
+ {
+ unsigned int offset = itr - (unsigned char *)array->members;
+ position = offset / sz;
+ goto found;
+ }
+ }
+ return -1;
+
+found:
+ if (!eina_inarray_remove_at(array, position))
+ return -1;
+ return position;
+}
+
+EAPI int
+eina_inarray_pop(Eina_Inarray *array)
+{
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(array->len == 0, -1);
+ if (!_eina_inarray_resize(array, array->len - 1))
+ return -1;
+ array->len--;
+ return array->len + 1;
+}
+
+EAPI void *
+eina_inarray_nth(const Eina_Inarray *array, unsigned int position)
+{
+ EINA_MAGIC_CHECK_INARRAY(array, NULL);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, NULL);
+ return _eina_inarray_get(array, position);
+}
+
+EAPI Eina_Bool
+eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data)
+{
+ unsigned int sz;
+ unsigned char *p;
+
+ EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, EINA_FALSE);
+
+ if (!_eina_inarray_resize(array, array->len + 1))
+ return EINA_FALSE;
+
+ p = _eina_inarray_get(array, position);
+ sz = array->member_size;
+ if (array->len > position)
+ memmove(p + sz, p, (array->len - position) * sz);
+ memcpy(p, data, sz);
+
+ array->len++;
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+eina_inarray_remove_at(Eina_Inarray *array, unsigned int position)
+{
+ EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE);
+
+ if (position + 1 < array->len)
+ {
+ unsigned int sz = array->member_size;
+ unsigned char *p = _eina_inarray_get(array, position);
+ memmove(p, p + sz, (array->len - position - 1) * sz);
+ }
+
+ _eina_inarray_resize(array, array->len - 1);
+ array->len--;
+ return EINA_TRUE;
+}
+
+EAPI void
+eina_inarray_reverse(Eina_Inarray *array)
+{
+ size_t sz;
+ unsigned char *fwd, *rev, *fwd_end;
+ void *tmp;
+
+ EINA_MAGIC_CHECK_INARRAY(array);
+
+ if (array->len < 2)
+ return;
+
+ sz = array->member_size;
+
+ tmp = alloca(sz);
+ EINA_SAFETY_ON_NULL_RETURN(tmp);
+
+ fwd = array->members;
+ fwd_end = fwd + (array->len / 2) * sz;
+
+ rev = fwd + (array->len - 1) * sz;
+
+ for (; fwd < fwd_end; fwd += sz, rev -= sz)
+ {
+ memcpy(tmp, fwd, sz);
+ memcpy(fwd, rev, sz);
+ memcpy(rev, tmp, sz);
+ }
+}
+
+EAPI void
+eina_inarray_sort(Eina_Inarray *array, Eina_Compare_Cb compare)
+{
+ EINA_MAGIC_CHECK_INARRAY(array);
+ EINA_SAFETY_ON_NULL_RETURN(compare);
+ qsort(array->members, array->len, array->member_size, compare);
+}
+
+EAPI int
+eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
+{
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
+ return _eina_inarray_search(array, data, compare);
+}
+
+EAPI int
+eina_inarray_search_sorted(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
+{
+ unsigned int pos;
+ int cmp;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
+
+ pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp);
+ if (cmp == 0)
+ return pos;
+ return -1;
+}
+
+EAPI Eina_Bool
+eina_inarray_foreach(const Eina_Inarray *array, Eina_Each_Cb function, const void *user_data)
+{
+ unsigned char *itr, *itr_end;
+ unsigned int sz;
+ Eina_Bool ret = EINA_TRUE;
+
+ EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(function, EINA_FALSE);
+
+ sz = array->member_size;
+ itr = array->members;
+ itr_end = itr + array->len * sz;
+ for (; (itr < itr_end) && (ret); itr += sz)
+ ret = function(array, itr, (void *)user_data);
+ return ret;
+}
+
+EAPI int
+eina_inarray_foreach_remove(Eina_Inarray *array, Eina_Each_Cb match, const void *user_data)
+{
+ unsigned int i = 0, count = 0;
+
+ EINA_MAGIC_CHECK_INARRAY(array, -1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
+
+ while (i < array->len)
+ {
+ void *p = _eina_inarray_get(array, i);
+ if (match(array, p, (void *)user_data) == EINA_FALSE)
+ {
+ i++;
+ continue;
+ }
+
+ eina_inarray_remove_at(array, i);
+ count++;
+ }
+
+ return count;
+}
+
+EAPI unsigned int
+eina_inarray_count(const Eina_Inarray *array)
+{
+ EINA_MAGIC_CHECK_INARRAY(array, 0);
+ return array->len;
+}
+
+EAPI Eina_Iterator *
+eina_inarray_iterator_new(const Eina_Inarray *array)
+{
+ Eina_Iterator_Inarray *it;
+
+ EINA_MAGIC_CHECK_INARRAY(array, NULL);
+
+ eina_error_set(0);
+ it = calloc(1, sizeof(Eina_Iterator_Inarray));
+ if (!it)
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR);
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+ it->array = array;
+
+ it->iterator.version = EINA_ITERATOR_VERSION;
+ it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_next);
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER
+ (_eina_inarray_iterator_get_container);
+ it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free);
+
+ return &it->iterator;
+}
+
+EAPI Eina_Iterator *
+eina_inarray_iterator_reversed_new(const Eina_Inarray *array)
+{
+ Eina_Iterator_Inarray *it;
+
+ EINA_MAGIC_CHECK_INARRAY(array, NULL);
+
+ eina_error_set(0);
+ it = calloc(1, sizeof(Eina_Iterator_Inarray));
+ if (!it)
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ EINA_MAGIC_SET(it, EINA_MAGIC_INARRAY_ITERATOR);
+ EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+ it->array = array;
+ it->pos = array->len;
+
+ it->iterator.version = EINA_ITERATOR_VERSION;
+ it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_prev);
+ it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER
+ (_eina_inarray_iterator_get_container);
+ it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free);
+
+ return &it->iterator;
+}
+
+EAPI Eina_Accessor *
+eina_inarray_accessor_new(const Eina_Inarray *array)
+{
+ Eina_Accessor_Inarray *ac;
+
+ EINA_MAGIC_CHECK_INARRAY(array, NULL);
+
+ eina_error_set(0);
+ ac = calloc(1, sizeof(Eina_Accessor_Inarray));
+ if (!ac)
+ {
+ eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ EINA_MAGIC_SET(ac, EINA_MAGIC_INARRAY_ACCESSOR);
+ EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
+
+ ac->array = array;
+
+ ac->accessor.version = EINA_ACCESSOR_VERSION;
+ ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(_eina_inarray_accessor_get_at);
+ ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER
+ (_eina_inarray_accessor_get_container);
+ ac->accessor.free = FUNC_ACCESSOR_FREE(_eina_inarray_accessor_free);
+
+ return &ac->accessor;
+}
#include "eina_rectangle.h"
#include "eina_safety_checks.h"
#include "eina_inlist.h"
+#include "eina_inarray.h"
/*============================================================================*
* Local *
S(magic_string);
S(iterator);
S(accessor);
+ S(inarray);
S(array);
S(module);
S(mempool);
S(magic_string),
S(iterator),
S(accessor),
+ S(inarray),
S(array),
S(module),
S(mempool),
#define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261
#define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262
+#define EINA_MAGIC_INARRAY 0x98761270
+#define EINA_MAGIC_INARRAY_ITERATOR 0x98761271
+#define EINA_MAGIC_INARRAY_ACCESSOR 0x98761272
+
#define EINA_MAGIC_CLASS 0x9877CB30
/* undef the following, we want out version */
eina_test_ustr.c \
eina_test_binshare.c \
eina_test_binbuf.c \
+eina_test_inarray.c \
eina_test_array.c \
eina_test_clist.c \
eina_test_error.c \
static const Eina_Test_Case etc[] = {
{ "FixedPoint", eina_test_fp },
+ { "Inarray", eina_test_inarray },
{ "Array", eina_test_array },
{ "Binary Share", eina_test_binshare },
{ "String Share", eina_test_stringshare },
void eina_test_stringshare(TCase *tc);
void eina_test_ustringshare(TCase *tc);
void eina_test_binshare(TCase *tc);
+void eina_test_inarray(TCase *tc);
void eina_test_array(TCase *tc);
void eina_test_log(TCase *tc);
void eina_test_error(TCase *tc);
--- /dev/null
+/* EINA - EFL data type library
+ * Copyright (C) 2012 ProFUSION embedded systems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "eina_suite.h"
+#include "Eina.h"
+
+START_TEST(eina_inarray_test_simple)
+{
+ const int test_members = 5;
+ Eina_Inarray *array;
+ int i, pos, *member;
+ const struct spec {
+ int pos, value;
+ } *s, specs[] = {
+ {test_members, 1234},
+ {5, 0x1337},
+ {0, 0xbeef},
+ {-1, -1}
+ };
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(int), 2);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < test_members; i++)
+ {
+ pos = eina_inarray_append(array, &i);
+ fail_unless(pos == i);
+ }
+ fail_unless(eina_inarray_count(array) == (unsigned)test_members);
+
+ for (i = 0; i < test_members; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+
+ for (s = specs; s->pos >= 0; s++)
+ {
+ fail_unless(eina_inarray_insert_at(array, s->pos, &s->value));
+
+ for (i = 0; i < s->pos; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+ member = eina_inarray_nth(array, s->pos);
+ fail_unless(*member == s->value);
+ for (i = s->pos + 1; i < test_members + 1; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i - 1);
+ }
+
+ fail_unless(eina_inarray_remove_at(array, s->pos));
+ for (i = 0; i < test_members; i++)
+ {
+ member = eina_inarray_nth(array, i);
+ fail_unless(*member == i);
+ }
+ }
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+static const short rand_numbers[] = {
+ 9, 0, 2, 3, 6, 5, 4, 7, 8, 1, 10
+};
+static const int numbers_count = sizeof(rand_numbers)/sizeof(rand_numbers[0]);
+
+static void
+show_sort_array(const Eina_Inarray *array)
+{
+ int i, len = eina_inarray_count(array);
+ printf("array with %d members:\n", len);
+ for (i = 0; i < len; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ printf("\tarray[%2d]=%5hd\n", i, *member);
+ }
+}
+
+static Eina_Bool
+check_short_sorted(const Eina_Inarray *array)
+{
+ int i;
+ for (i = 0; i < numbers_count; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ if (*member != (short)i)
+ {
+ show_sort_array(array);
+ fprintf(stderr, "not sorted at %d: %hd\n", i, *member);
+ return EINA_FALSE;
+ }
+ }
+ return EINA_TRUE;
+}
+
+static int
+short_cmp(const void *pa, const void *pb)
+{
+ const short *a = pa, *b = pb;
+ return *a - *b;
+}
+
+START_TEST(eina_inarray_test_insert_sort)
+{
+ Eina_Inarray *array;
+ int i, pos;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ /* insert sorted and already sorted sequence */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ pos = eina_inarray_insert(array, &val, short_cmp);
+ fail_unless(pos == (int)val);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ pos = eina_inarray_insert_sorted(array, &val, short_cmp);
+ fail_unless(pos == (int)val);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ /* insert sorted the reverse sequence */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = numbers_count - i - 1;
+ pos = eina_inarray_insert(array, &val, short_cmp);
+ fail_unless(pos == 0);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = numbers_count - i - 1;
+ pos = eina_inarray_insert_sorted(array, &val, short_cmp);
+ fail_unless(pos == 0);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ /* insert sorted random numbers */
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_insert(array, &val, short_cmp);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_insert_sorted(array, &val, short_cmp);
+ }
+ fail_unless(check_short_sorted(array));
+ eina_inarray_flush(array);
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_inarray_test_sort)
+{
+ Eina_Inarray *array;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = rand_numbers[i];
+ eina_inarray_append(array, &val);
+ }
+ eina_inarray_sort(array, short_cmp);
+ fail_unless(check_short_sorted(array));
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_inarray_test_reverse)
+{
+ Eina_Inarray *array;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ eina_inarray_append(array, &val);
+ }
+ eina_inarray_reverse(array);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short *member = eina_inarray_nth(array, i);
+ fail_unless(*member == (numbers_count - i - 1));
+ }
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+array_foreach(const void *array __UNUSED__, void *p, void *user_data __UNUSED__)
+{
+ short *member = p;
+ int *i = user_data;
+ fail_unless(*i == *member);
+ (*i)++;
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+array_foreach_stop_2nd(const void *array __UNUSED__, void *p, void *user_data __UNUSED__)
+{
+ short *member = p;
+ int *i = user_data;
+ fail_unless(*i == *member);
+ if (*i == 1)
+ return EINA_FALSE;
+ (*i)++;
+ return EINA_TRUE;
+}
+
+START_TEST(eina_inarray_test_itr)
+{
+ Eina_Inarray *array;
+ Eina_Iterator *it;
+ Eina_Accessor *ac;
+ short *member;
+ int i;
+
+ eina_init();
+
+ array = eina_inarray_new(sizeof(short), 1);
+ fail_unless(array != NULL);
+
+ for (i = 0; i < numbers_count; i++)
+ {
+ short val = i;
+ eina_inarray_append(array, &val);
+ }
+ i = 0;
+ EINA_INARRAY_FOREACH(array, member)
+ {
+ fail_unless(*member == i);
+ i++;
+ }
+ fail_unless(i == numbers_count);
+
+ i--;
+ EINA_INARRAY_REVERSE_FOREACH(array, member)
+ {
+ fail_unless(*member == i);
+ i--;
+ }
+ fail_unless(i == -1);
+
+ i = 0;
+ fail_unless(eina_inarray_foreach(array, array_foreach, &i));
+ fail_unless(i == numbers_count);
+
+ i = 0;
+ fail_if(eina_inarray_foreach(array, array_foreach_stop_2nd, &i));
+ fail_unless(i == 1);
+
+ it = eina_inarray_iterator_new(array);
+ fail_unless(it != NULL);
+ i = 0;
+ EINA_ITERATOR_FOREACH(it, member)
+ {
+ fail_unless(*member == i);
+ i++;
+ }
+ fail_unless(i == numbers_count);
+ eina_iterator_free(it);
+
+ it = eina_inarray_iterator_reversed_new(array);
+ fail_unless(it != NULL);
+ i--;
+ EINA_ITERATOR_FOREACH(it, member)
+ {
+ fail_unless(*member == i);
+ i--;
+ }
+ fail_unless(i == -1);
+ eina_iterator_free(it);
+
+ ac = eina_inarray_accessor_new(array);
+ fail_unless(ac != NULL);
+ for (i = 0; i < numbers_count; i++)
+ {
+ fail_unless(eina_accessor_data_get(ac, i, (void **)&member));
+ fail_unless(*member == i);
+ }
+ fail_unless(i == numbers_count);
+ eina_accessor_free(ac);
+
+ eina_inarray_free(array);
+ eina_shutdown();
+}
+END_TEST
+
+void
+eina_test_inarray(TCase *tc)
+{
+ tcase_add_test(tc, eina_inarray_test_simple);
+ tcase_add_test(tc, eina_inarray_test_insert_sort);
+ tcase_add_test(tc, eina_inarray_test_sort);
+ tcase_add_test(tc, eina_inarray_test_reverse);
+ tcase_add_test(tc, eina_inarray_test_itr);
+}