From 223a433be8ab02267c97069a271cf89c65856c42 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 1 Jul 2019 19:18:11 +0200 Subject: [PATCH] eina: add accessors for c arrays This adds a new API which can be used to get access to a carray via the eina_accessor API. --- src/lib/eina/eina_accessor.c | 61 +++++++++++++++++++++++++++++ src/lib/eina/eina_accessor.h | 32 +++++++++++++++ src/tests/eina/eina_test_accessor.c | 28 +++++++++++++ 3 files changed, 121 insertions(+) diff --git a/src/lib/eina/eina_accessor.c b/src/lib/eina/eina_accessor.c index 9506b86a80..1c5889f918 100644 --- a/src/lib/eina/eina_accessor.c +++ b/src/lib/eina/eina_accessor.c @@ -189,3 +189,64 @@ eina_accessor_unlock(Eina_Accessor *accessor) return accessor->unlock(accessor); return EINA_TRUE; } + +typedef struct _Eina_Accessor_CArray_Length Eina_Accessor_CArray_Length; + +struct _Eina_Accessor_CArray_Length +{ + Eina_Accessor accessor; + + void** array; + void** current; + + void** end; + unsigned int step; +}; + +static Eina_Bool +eina_carray_length_accessor_get_at(Eina_Accessor_CArray_Length *accessor, unsigned int idx, void **data) +{ + if (accessor->array + idx*accessor->step >= accessor->end) + return EINA_FALSE; + + memcpy(data, (void*) accessor->array + idx*accessor->step, accessor->step); + accessor->current += accessor->step; + + return EINA_TRUE; +} + +static void** +eina_carray_length_accessor_get_container(Eina_Accessor_CArray_Length *accessor) +{ + return accessor->array; +} + +static void +eina_carray_length_accessor_free(Eina_Accessor_CArray_Length *accessor) +{ + free(accessor); +} + +EAPI Eina_Accessor * +eina_carray_length_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->current = accessor->array; + accessor->end = accessor->current + length * step; + accessor->step = step; + + accessor->accessor.version = EINA_ACCESSOR_VERSION; + accessor->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_carray_length_accessor_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 3586d3c197..7b47d31a01 100644 --- a/src/lib/eina/eina_accessor.h +++ b/src/lib/eina/eina_accessor.h @@ -348,6 +348,38 @@ EAPI Eina_Bool eina_accessor_unlock(Eina_Accessor *accessor) EINA_ARG_NONNULL(1) eina_accessor_data_get((accessor), (counter), (void **)(void *)&(data)); \ (counter)++) +/** + * @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)); + * + * @since 1.23 + */ +EAPI Eina_Accessor* eina_carray_length_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 + * + * @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_NEW(Array) eina_carray_length_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 7a75de6bb6..734d833205 100644 --- a/src/tests/eina/eina_test_accessor.c +++ b/src/tests/eina/eina_test_accessor.c @@ -230,10 +230,38 @@ EFL_START_TEST(eina_accessor_list_simple) } 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_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); }