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:
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