From 9ccc66b90004a29c0790d58106857dc5e3377976 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Wed, 18 Dec 2019 17:15:09 +0100 Subject: [PATCH] eina_accessor: make carray accessor work properly a accessor is not really helpfull if it operates like the carray accessor before this commit. What it was doing is to fill the content of the "current line" into the data pointer. In a carray the "current line" is the content of its carray-member. However, accessors like for inarray array list or inlist do work completly differently. They are returning the pointer to the "current line" not the value of the current line. The only case where this worked is efl_ui_format.c which was only tested with this accessor, and this accessor also only worked with this accessor. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10908 --- src/lib/eina/eina_accessor.c | 38 ++++++++++++++++++++++++++--- src/lib/eina/eina_accessor.h | 36 +++++++++++++++++++++++++++ src/tests/eina/eina_test_accessor.c | 32 +++++++++++++++++++++++- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/lib/eina/eina_accessor.c b/src/lib/eina/eina_accessor.c index 1c5889f918..67494987a9 100644 --- a/src/lib/eina/eina_accessor.c +++ b/src/lib/eina/eina_accessor.c @@ -197,7 +197,6 @@ struct _Eina_Accessor_CArray_Length Eina_Accessor accessor; void** array; - void** current; void** end; unsigned int step; @@ -210,7 +209,16 @@ eina_carray_length_accessor_get_at(Eina_Accessor_CArray_Length *accessor, unsign return EINA_FALSE; memcpy(data, (void*) accessor->array + idx*accessor->step, accessor->step); - accessor->current += accessor->step; + + return EINA_TRUE; +} +static Eina_Bool +eina_carray_length_accessor_ptr_get_at(Eina_Accessor_CArray_Length *accessor, unsigned int idx, void **data) +{ + if (accessor->array + idx*accessor->step >= accessor->end) + return EINA_FALSE; + + *data = (((void*)accessor->array) + idx*accessor->step); return EINA_TRUE; } @@ -238,8 +246,7 @@ eina_carray_length_accessor_new(void** array, unsigned int step, unsigned int le EINA_MAGIC_SET(&accessor->accessor, EINA_MAGIC_ACCESSOR); accessor->array = array; - accessor->current = accessor->array; - accessor->end = accessor->current + length * step; + accessor->end = accessor->array + length * step; accessor->step = step; accessor->accessor.version = EINA_ACCESSOR_VERSION; @@ -250,3 +257,26 @@ eina_carray_length_accessor_new(void** array, unsigned int step, unsigned int le return &accessor->accessor; } + +EAPI Eina_Accessor * +eina_carray_length_ptr_accessor_new(void** array, unsigned int step, unsigned int length) +{ + Eina_Accessor_CArray_Length *accessor; + + accessor = calloc(1, sizeof (Eina_Accessor_CArray_Length)); + if (!accessor) return NULL; + + EINA_MAGIC_SET(&accessor->accessor, EINA_MAGIC_ACCESSOR); + + accessor->array = array; + accessor->end = accessor->array + length * step; + accessor->step = step; + + accessor->accessor.version = EINA_ACCESSOR_VERSION; + accessor->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_carray_length_accessor_ptr_get_at); + accessor->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER( + eina_carray_length_accessor_get_container); + accessor->accessor.free = FUNC_ACCESSOR_FREE(eina_carray_length_accessor_free); + + return &accessor->accessor; +} diff --git a/src/lib/eina/eina_accessor.h b/src/lib/eina/eina_accessor.h index 7b47d31a01..ccfccceba3 100644 --- a/src/lib/eina/eina_accessor.h +++ b/src/lib/eina/eina_accessor.h @@ -364,6 +364,26 @@ EAPI Eina_Bool eina_accessor_unlock(Eina_Accessor *accessor) EINA_ARG_NONNULL(1) * @since 1.23 */ EAPI Eina_Accessor* eina_carray_length_accessor_new(void** array, unsigned int step, unsigned int length); + + +/** + * @brief Creates an Eina_Accessor that wraps a plain fixed size C array + * + * @param[in] array The array + * @param[in] step The size of one element in the array + * @param[in] length The number of elements in the array + * @return The accessor that will give access to the passed array + * + * You can create it like this: + * int array[] = {1, 2, 3, 4, 1337, 42}; + * + * Eina_Accessor* accessor = eina_carray_length_accessor_new(array, sizeof(int), sizeof(array)/sizeof(int)); + * + * Note: The difference to eina_carray_length_accessor_new is that this will fill the pointer to the value into the data pointer. * + + * @since 1.24 + */ +EAPI Eina_Accessor* eina_carray_length_ptr_accessor_new(void** array, unsigned int step, unsigned int length); /** * @def EINA_C_ARRAY_ACCESSOR_NEW * @brief Creates an Eina_Accessor that wraps a plain fixed size C array @@ -379,6 +399,22 @@ EAPI Eina_Accessor* eina_carray_length_accessor_new(void** array, unsigned int s * @since 1.23 */ #define EINA_C_ARRAY_ACCESSOR_NEW(Array) eina_carray_length_accessor_new((void**) Array, sizeof (Array[0]), EINA_C_ARRAY_LENGTH(Array)) +/** + * @def EINA_C_ARRAY_ACCESSOR_NEW + * @brief Creates an Eina_Accessor that wraps a plain fixed size C array + * + * @param[in] array The array + * @return The accessor that will give access to the passed array + * + * You can create it like this: + * int array[] = {1, 2, 3, 4, 1337, 42}; + * + * Eina_Accessor* accessor = EINA_C_ARRAY_ACCESSOR_NEW(array) + * + * @since 1.23 + */ +#define EINA_C_ARRAY_ACCESSOR_PTR_NEW(Array) eina_carray_length_ptr_accessor_new((void**) Array, sizeof (Array[0]), EINA_C_ARRAY_LENGTH(Array)) + /** * @} diff --git a/src/tests/eina/eina_test_accessor.c b/src/tests/eina/eina_test_accessor.c index 734d833205..62e77e06ee 100644 --- a/src/tests/eina/eina_test_accessor.c +++ b/src/tests/eina/eina_test_accessor.c @@ -230,7 +230,7 @@ EFL_START_TEST(eina_accessor_list_simple) } EFL_END_TEST -EFL_START_TEST(eina_accessor_carray_simple) +EFL_START_TEST(eina_accessor_carray_simple_ptr) { Eina_Accessor *it; int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 }; @@ -257,11 +257,41 @@ EFL_START_TEST(eina_accessor_carray_simple) eina_accessor_free(it); } EFL_END_TEST + +EFL_START_TEST(eina_accessor_carray_simple) +{ + Eina_Accessor *it; + int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 }; + int *j, c; + + it = EINA_C_ARRAY_ACCESSOR_PTR_NEW(data); + + EINA_ACCESSOR_FOREACH(it, c, j) + { + ck_assert_int_eq(data[c], *j); + } + + fail_if(eina_accessor_data_get(it, 5, (void **)&j) != EINA_TRUE); + fail_if(*j != 1337); + fail_if(eina_accessor_data_get(it, 3, (void **)&j) != EINA_TRUE); + fail_if(*j != 1); + fail_if(eina_accessor_data_get(it, 3, (void **)&j) != EINA_TRUE); + fail_if(*j != 1); + fail_if(eina_accessor_data_get(it, 1, (void **)&j) != EINA_TRUE); + fail_if(*j != 9); + fail_if(eina_accessor_data_get(it, 5, (void **)&j) != EINA_TRUE); + fail_if(*j != 1337); + + eina_accessor_free(it); +} +EFL_END_TEST + void eina_test_accessor(TCase *tc) { tcase_add_test(tc, eina_accessor_array_simple); tcase_add_test(tc, eina_accessor_inlist_simple); tcase_add_test(tc, eina_accessor_list_simple); + tcase_add_test(tc, eina_accessor_carray_simple_ptr); tcase_add_test(tc, eina_accessor_carray_simple); }