rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit cf8953e8fd5933255a91560b2b4cad6431a05fba
parent c909127e0e285445f56bf730a3674a23eb102bd6
Author: vaplv <vaplv@free.fr>
Date:   Sun, 23 Feb 2014 14:04:13 +0100

Improve the dynamic array API

Add support of specific copy/init/release functors

Diffstat:
Msrc/dynamic_array.h | 222++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/test_dynamic_array.c | 2+-
2 files changed, 188 insertions(+), 36 deletions(-)

diff --git a/src/dynamic_array.h b/src/dynamic_array.h @@ -1,4 +1,4 @@ -#if !defined(DARRAY_NAME) || !defined(DARRAY_DATA_TYPE) +#if !defined(DARRAY_NAME) && !defined(DARRAY_DATA) #ifndef DYNAMIC_ARRAY_H #define DYNAMIC_ARRAY_H @@ -10,30 +10,80 @@ #endif /* DYNAMIC_ARRAY_H */ #else /* - * Dynamic array API generated with respect the DARRAY_<NAME|DATA_TYPE> macros - * The name of the generated type is darray_<DARRAY_NAME> and the naming - * convention of its functions is darray_<DARRAY_NAME>_<Function> + * Generate the dynamic array data type and functions with respect to the + * following macros: + * - DARRAY_NAME: prefix of the dynamic array functions & types; + * - DARRAY_DATA: type of the data registered into the array; + * - DARRAY_FUNCTOR_INIT: init functor on DARRAY_DATA. If not defined, no + * specific treatment is performed on the created data; + * - DARRAY_FUNCTOR_COPY: copy functor on DARRAY_DATA. If not defined a + * bitwise copy is used instead; + * - DARRAY_FUNCTOR_RELEASE: release functor on DARRAY_DATA. If not defined + * nothing is done on the release of an element; + * - DARRAY_FUNCTOR_COPY_AND_RELEASE: Copy and release of a DARRAY_DATA. If + * not defined the copy and the release functors is used. + * + * The name of the generated type is: struct darray_<DARRAY_NAME> + * + * while the generated functions are: darray_<DARRAY_NAME>_<FUNCTION_NAME> */ #ifndef DARRAY_NAME #error "Missing the DARRAY_NAME macro defining the structure name" #endif - -#ifndef DARRAY_DATA_TYPE - #error "Missing the DARRAY_DATA_TYPE macro defining the array data type" +#ifndef DARRAY_DATA + #error "Missing the DARRAY_DATA macro defining the array data type" #endif #define DARRAY_FUNC__(Func) CONCAT(CONCAT(CONCAT(darray_, DARRAY_NAME),_), Func) #define DARRAY_TYPE__ CONCAT(darray_, DARRAY_NAME) struct DARRAY_TYPE__ { - DARRAY_DATA_TYPE* data; - DARRAY_DATA_TYPE buf[16]; /* Static buffer. Avoid mem alloc on small arrays */ + DARRAY_DATA* data; + DARRAY_DATA buf[16]; /* Static buffer. Avoid mem alloc on small arrays */ size_t size; size_t capacity; struct mem_allocator* allocator; }; +/******************************************************************************* + * Internal default functors + ******************************************************************************/ +#ifndef DARRAY_FUNCTOR_INIT +static FINLINE void +DARRAY_FUNC__(functor_init__)(struct mem_allocator* alloc, DARRAY_DATA* data) +{ ASSERT(data); (void)alloc, (void)data; } +#define DARRAY_FUNCTOR_INIT DARRAY_FUNC__(functor_init__) +#endif + +#ifndef DARRAY_FUNCTOR_RELEASE static FINLINE void +DARRAY_FUNC__(functor_release__)(DARRAY_DATA* data) +{ ASSERT(data); (void)data; } +#define DARRAY_FUNCTOR_RELEASE DARRAY_FUNC__(functor_release__) +#endif + +#ifndef DARRAY_FUNCTOR_COPY +static FINLINE int +DARRAY_FUNC__(functor_cp__)(DARRAY_DATA* dst, DARRAY_DATA const* src) +{ ASSERT(dst && src); *dst = *src; return 0; } +#define DARRAY_FUNCTOR_COPY DARRAY_FUNC__(functor_cp__) +#endif + +#ifndef DARRAY_FUNCTOR_COPY_AND_RELEASE +static FINLINE int +DARRAY_FUNC__(functor_cp_and_release__)(DARRAY_DATA* dst, DARRAY_DATA* src) +{ + DARRAY_FUNCTOR_COPY(dst, src); + DARRAY_FUNCTOR_RELEASE(src); + return 0; +} +#define DARRAY_FUNCTOR_COPY_AND_RELEASE DARRAY_FUNC__(functor_cp_and_release__) +#endif + +/******************************************************************************* + * Dynamic array API + ******************************************************************************/ +static INLINE void DARRAY_FUNC__(init) (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ struct DARRAY_TYPE__* darray) @@ -41,29 +91,33 @@ DARRAY_FUNC__(init) ASSERT(darray); darray->data = darray->buf; darray->size = 0; - darray->capacity = sizeof(darray->buf)/sizeof(DARRAY_DATA_TYPE); + darray->capacity = sizeof(darray->buf)/sizeof(DARRAY_DATA); darray->allocator = allocator ? allocator : &mem_default_allocator; } -static FINLINE void -DARRAY_FUNC__(release)(struct DARRAY_TYPE__* darray) +static INLINE void +DARRAY_FUNC__(clear)(struct DARRAY_TYPE__* darray) { + size_t i; ASSERT(darray); - if( darray->data != darray->buf ) - MEM_FREE(darray->allocator, darray->data); + FOR_EACH(i, 0, darray->size) + DARRAY_FUNCTOR_RELEASE(darray->data + i); + darray->size = 0; } -static FINLINE void -DARRAY_FUNC__(clear)(struct DARRAY_TYPE__* darray) +static INLINE void +DARRAY_FUNC__(release)(struct DARRAY_TYPE__* darray) { ASSERT(darray); - darray->size = 0; + DARRAY_FUNC__(clear)(darray); + if( darray->data != darray->buf ) + MEM_FREE(darray->allocator, darray->data); } -static FINLINE char +static INLINE int DARRAY_FUNC__(reserve)(struct DARRAY_TYPE__* darray, const size_t sz) { - DARRAY_DATA_TYPE* data = NULL; + DARRAY_DATA* data = NULL; size_t sz_adjusted; ASSERT(darray); @@ -73,13 +127,21 @@ DARRAY_FUNC__(reserve)(struct DARRAY_TYPE__* darray, const size_t sz) sz_adjusted = round_up_pow2(sz); data = MEM_ALLOC_ALIGNED (darray->allocator, - sz_adjusted * sizeof(DARRAY_DATA_TYPE), - ALIGNOF(DARRAY_DATA_TYPE)); + sz_adjusted * sizeof(DARRAY_DATA), + ALIGNOF(DARRAY_DATA)); if(!data) return -1; - if(darray->size) - memcpy(data, darray->data, darray->size * sizeof(DARRAY_DATA_TYPE)); + if(darray->size) { + size_t i = 0; + FOR_EACH(i, 0, darray->size) { + const int err = DARRAY_FUNCTOR_COPY_AND_RELEASE(data+i, darray->data+i); + if(err) { + MEM_FREE(darray->allocator, data); + return err; + } + } + } if(darray->data != darray->buf) MEM_FREE(darray->allocator, darray->data); @@ -88,54 +150,144 @@ DARRAY_FUNC__(reserve)(struct DARRAY_TYPE__* darray, const size_t sz) return 0; } -static FINLINE char +static INLINE int DARRAY_FUNC__(resize)(struct DARRAY_TYPE__* darray, const size_t sz) { + size_t i; ASSERT(darray); + if(DARRAY_FUNC__(reserve)(darray, sz)) return -1; + + FOR_EACH(i, sz, darray->size) + DARRAY_FUNCTOR_RELEASE(darray->data+i); + FOR_EACH(i, darray->size, sz) + DARRAY_FUNCTOR_INIT(darray->allocator, darray->data+i); darray->size = sz; return 0; } -static FINLINE char +static INLINE char DARRAY_FUNC__(push_back) (struct DARRAY_TYPE__* darray, - DARRAY_DATA_TYPE* const data) + DARRAY_DATA const* data) { - size_t i = 0; + size_t sz = 0; ASSERT(darray && data); - i = darray->size + 1; - if(DARRAY_FUNC__(reserve)(darray, i)) + sz = darray->size; + if(DARRAY_FUNC__(resize)(darray, sz+1)) return -1; - darray->data[darray->size] = *data; - darray->size = i; + DARRAY_FUNCTOR_COPY(darray->data+sz, data); return 0; } -static FINLINE size_t +static INLINE size_t DARRAY_FUNC__(size_get)(const struct DARRAY_TYPE__* darray) { ASSERT(darray); return darray->size; } -static FINLINE DARRAY_DATA_TYPE* +static INLINE DARRAY_DATA* DARRAY_FUNC__(data_get)(struct DARRAY_TYPE__* darray) { ASSERT(darray); return darray->data; } -static FINLINE DARRAY_DATA_TYPE const* +static INLINE DARRAY_DATA const* DARRAY_FUNC__(cdata_get)(const struct DARRAY_TYPE__* darray) { ASSERT(darray); return darray->data; } +static INLINE int +DARRAY_FUNC__(copy)(struct DARRAY_TYPE__* dst, const struct DARRAY_TYPE__* src) +{ + DARRAY_DATA const* src_data = NULL; + size_t i, src_sz; + int res; + ASSERT(dst && src); + + if(dst == src) + return 0; + + DARRAY_FUNC__(clear)(dst); + src_sz = DARRAY_FUNC__(size_get)(src); + res = DARRAY_FUNC__(reserve)(dst, src_sz); + if(res) return res; + + src_data = DARRAY_FUNC__(cdata_get)(src); + FOR_EACH(i, 0, src_sz) + DARRAY_FUNC__(push_back)(dst, src_data+i); + return 0; +} + +static INLINE int +DARRAY_FUNC__(copy_and_clear) + (struct DARRAY_TYPE__* dst, + struct DARRAY_TYPE__* src) +{ + int res = 0; + ASSERT(dst && src); + if( dst == src ) { + DARRAY_FUNC__(clear)(dst); + return 0; + } + + if(src->data != src->buf && src->allocator == dst->allocator) { + /* Give the ownership of src->m_Data to dst */ + if(dst->data != dst->buf) + MEM_FREE(dst->allocator, dst->data); + dst->data = src->data; + dst->capacity = src->capacity; + dst->size = src->size; + DARRAY_FUNC__(init)(src->allocator, src); /* Reset src */ + } else { + DARRAY_DATA* src_data = NULL; + DARRAY_DATA* dst_data = NULL; + const size_t src_sz = DARRAY_FUNC__(size_get)(src); + size_t i = 0; + + DARRAY_FUNC__(clear)(dst); + res = DARRAY_FUNC__(resize)(dst, src_sz); + if(res) return res; + + src_data = DARRAY_FUNC__(data_get)(src); + dst_data = DARRAY_FUNC__(data_get)(dst); + FOR_EACH(i, 0, src_sz) { + res = DARRAY_FUNCTOR_COPY_AND_RELEASE(dst_data+i, src_data+i); + if(res) return res; + } + DARRAY_FUNC__(clear)(src); + } + return res; +} + +static INLINE int +DARRAY_FUNC__(copy_and_release) + (struct DARRAY_TYPE__* dst, + struct DARRAY_TYPE__* src) +{ + int res = 0; + ASSERT(dst && src); + if(dst == src) { + DARRAY_FUNC__(release)(dst); + } else { + res = DARRAY_FUNC__(copy_and_clear)(dst, src); + if(!res) + DARRAY_FUNC__(release)(src); + } + return res; +} + #undef DARRAY_NAME -#undef DARRAY_DATA_TYPE +#undef DARRAY_DATA +#undef DARRAY_FUNCTOR_INIT +#undef DARRAY_FUNCTOR_RELEASE +#undef DARRAY_FUNCTOR_COPY +#undef DARRAY_FUNCTOR_COPY_AND_RELEASE #undef DARRAY_FUNC__ #undef DARRAY_TYPE__ diff --git a/src/test_dynamic_array.c b/src/test_dynamic_array.c @@ -1,7 +1,7 @@ #include "dynamic_array.h" #define DARRAY_NAME str -#define DARRAY_DATA_TYPE const char* +#define DARRAY_DATA const char* #include "dynamic_array.h" int