diff --git a/legacy/eina/src/include/eina_inarray.h b/legacy/eina/src/include/eina_inarray.h index 08edb4a8a4..d37c76b3ad 100644 --- a/legacy/eina/src/include/eina_inarray.h +++ b/legacy/eina/src/include/eina_inarray.h @@ -271,6 +271,35 @@ EAPI Eina_Bool eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data) EINA_ARG_NONNULL(1, 3); +/** + * @brief Opens a space at given position, returning its pointer. + * @param array array object + * @param position where to insert first member (open/allocate space) + * @param member_count how many times member_size bytes will be allocated. + * @return pointer to first member memory allocated or @c NULL on errors. + * + * This is similar to eina_inarray_insert_at(), but useful if the + * members contents are still unknown or unallocated. It will make + * room for the required number of items and return the pointer to the + * first item, similar to malloc(member_count * member_size), with the + * guarantee all memory is within members array. + * + * The new member memory is undefined, it's not automatically zeroed. + * + * 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. + * + * @since 1.2 + */ +EAPI void *eina_inarray_alloc_at(Eina_Inarray *array, + unsigned int position, + unsigned int member_count) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + /** * @brief Copy the data over the given position. * @param array array object diff --git a/legacy/eina/src/lib/eina_inarray.c b/legacy/eina/src/lib/eina_inarray.c index 8e5268852d..dc95bc600f 100644 --- a/legacy/eina/src/lib/eina_inarray.c +++ b/legacy/eina/src/lib/eina_inarray.c @@ -522,6 +522,28 @@ eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *d return EINA_TRUE; } +EAPI void * +eina_inarray_alloc_at(Eina_Inarray *array, unsigned int position, unsigned int member_count) +{ + unsigned int sz; + unsigned char *p; + + EINA_MAGIC_CHECK_INARRAY(array, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL(member_count == 0, NULL); + + if (!_eina_inarray_resize(array, array->len + member_count)) + return NULL; + + p = _eina_inarray_get(array, position); + sz = array->member_size; + if (array->len > position) + memmove(p + member_count * sz, p, (array->len - position) * sz); + + array->len += member_count; + return p; +} + EAPI Eina_Bool eina_inarray_replace_at(Eina_Inarray *array, unsigned int position, const void *data) { diff --git a/legacy/eina/src/tests/eina_test_inarray.c b/legacy/eina/src/tests/eina_test_inarray.c index 574db1ac4a..22ba763770 100644 --- a/legacy/eina/src/tests/eina_test_inarray.c +++ b/legacy/eina/src/tests/eina_test_inarray.c @@ -87,6 +87,46 @@ START_TEST(eina_inarray_test_simple) } END_TEST + +START_TEST(eina_inarray_test_alloc_at) +{ + Eina_Inarray *array; + int *member; + int i; + + eina_init(); + + array = eina_inarray_new(sizeof(int), 2); + fail_unless(array != NULL); + + member = eina_inarray_alloc_at(array, 0, 4); + fail_unless(member != NULL); + fail_unless(eina_inarray_count(array) == 4); + + for (i = 0; i < 4; i++) + member[i] = i + 2; + + member = eina_inarray_alloc_at(array, 0, 2); + fail_unless(member != NULL); + fail_unless(eina_inarray_count(array) == 6); + for (i = 0; i < 2; i++) + member[i] = i; + + member = eina_inarray_alloc_at(array, 6, 2); + fail_unless(member != NULL); + fail_unless(eina_inarray_count(array) == 8); + for (i = 0; i < 2; i++) + member[i] = i + 6; + + member = array->members; + for (i = 0; i < 8; i++) + fail_unless(member[i] == 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 }; @@ -353,6 +393,7 @@ void eina_test_inarray(TCase *tc) { tcase_add_test(tc, eina_inarray_test_simple); + tcase_add_test(tc, eina_inarray_test_alloc_at); 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);