commit 53e79630e5f6774c81d9a5dc9fbbd601c3f11144
parent 7dfb050571902cf50d03a517b954990522f4f6a6
Author: vaplv <vaplv@free.fr>
Date: Sun, 16 Oct 2016 16:55:47 +0200
Add and test the swap function on dynamic arrays
Swap the data of 2 dynamic arrays.
Diffstat:
2 files changed, 255 insertions(+), 51 deletions(-)
diff --git a/src/dynamic_array.h b/src/dynamic_array.h
@@ -329,6 +329,62 @@ DARRAY_FUNC__(copy_and_release)
return res;
}
+static INLINE res_T
+DARRAY_FUNC__(swap)(struct DARRAY_TYPE__* a, struct DARRAY_TYPE__* b)
+{
+ int a_buf, b_buf;
+ res_T res = RES_OK;
+ ASSERT(a && b);
+
+ /* Ensure that `a' point toward the smallest array */
+ if(DARRAY_FUNC__(size_get)(a) > DARRAY_FUNC__(size_get)(b)) {
+ SWAP(struct DARRAY_TYPE__*, a, b);
+ }
+
+ /* Define if the data are stored in the local buffer */
+ a_buf = (a->data == (DARRAY_DATA*)a->buf);
+ b_buf = (b->data == (DARRAY_DATA*)b->buf);
+
+ if(a->allocator != b->allocator || (a_buf && b_buf)) {
+ struct DARRAY_TYPE__ tmp;
+ DARRAY_FUNC__(init)(a->allocator, &tmp);
+
+ res = DARRAY_FUNC__(copy_and_clear)(&tmp, b);
+ if(res != RES_OK) return res;
+ res = DARRAY_FUNC__(copy_and_clear)(b, a);
+ if(res != RES_OK) return res;
+ res = DARRAY_FUNC__(copy_and_release)(a, &tmp);
+ if(res != RES_OK) return res;
+
+ } else {
+ /* `b' cannot be buffered since at most one array is buffered and that `b'
+ * is greater than `a' */
+ ASSERT(!b_buf);
+
+ if(!a_buf) { /* `a' is not buffered => swap data ownership */
+ SWAP(DARRAY_DATA*, a->data, b->data);
+ SWAP(size_t, a->capacity, b->capacity);
+ SWAP(size_t, a->size, b->size);
+ } else {
+ /* Back-up the data of `b' */
+ DARRAY_DATA* b_data = b->data;
+ const size_t b_capacity = b->capacity;
+ const size_t b_size = b->size;
+
+ /* Reset `b' and copy `a' into `b' */
+ DARRAY_FUNC__(init)(b->allocator, b);
+ res = DARRAY_FUNC__(copy_and_clear)(b, a);
+ ASSERT(res == RES_OK);
+
+ /* Give the ownership of `b' data to `a' */
+ a->data = b_data;
+ a->capacity = b_capacity;
+ a->size = b_size;
+ }
+ }
+ return RES_OK;
+}
+
#undef DARRAY_NAME
#undef DARRAY_DATA
#undef DARRAY_FUNCTOR_INIT
diff --git a/src/test_dynamic_array.c b/src/test_dynamic_array.c
@@ -16,11 +16,7 @@
#include "dynamic_array.h"
#include "test_utils.h"
-#define DARRAY_NAME str
-#define DARRAY_DATA const char*
-#include "dynamic_array.h"
-
-const char* strs[] = {
+static const char* strs[] = {
"Rcvfbqr", "1,", "XARR-QRRC", "VA", "GUR", "QRNQ:\n",
"---------------------------------", "BAPR", "LBH", "ORNG", "GUR", "OVT",
"ONQNFFRF", "NAQ", "PYRNA", "BHG", "GUR", "ZBBA", "ONFR", "LBH'ER",
@@ -48,16 +44,17 @@ const char* strs[] = {
ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB."
};
+#define DARRAY_NAME str
+#define DARRAY_DATA const char*
+#include "dynamic_array.h"
+
static void
-test_primitive_type(void)
+test_cstr(struct mem_allocator* allocator)
{
- struct mem_allocator allocator_proxy;
struct darray_str darray;
const size_t nstrs = sizeof(strs)/sizeof(const char*);
size_t i = 0;
- mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
-
darray_str_init(NULL, &darray);
CHECK(darray_str_size_get(&darray), 0);
darray_str_clear(&darray);
@@ -71,7 +68,7 @@ test_primitive_type(void)
CHECK(darray_str_size_get(&darray), 0);
darray_str_release(&darray);
- darray_str_init(&allocator_proxy, &darray);
+ darray_str_init(allocator, &darray);
FOR_EACH(i, 0, nstrs) {
darray_str_push_back(&darray, strs + i);
}
@@ -82,7 +79,7 @@ test_primitive_type(void)
CHECK(darray_str_size_get(&darray), 0);
darray_str_release(&darray);
- darray_str_init(&allocator_proxy, &darray);
+ darray_str_init(allocator, &darray);
CHECK(darray_str_size_get(&darray), 0);
darray_str_resize(&darray, 8);
CHECK(darray_str_size_get(&darray), 8);
@@ -91,13 +88,10 @@ test_primitive_type(void)
darray_str_resize(&darray, 33);
CHECK(darray_str_size_get(&darray), 33);
darray_str_release(&darray);
-
- check_memory_allocator(&allocator_proxy);
- mem_shutdown_proxy_allocator(&allocator_proxy);
}
#include "str.h"
-#define DARRAY_NAME struct_str
+#define DARRAY_NAME string
#define DARRAY_DATA struct str
#define DARRAY_FUNCTOR_INIT str_init
#define DARRAY_FUNCTOR_COPY str_copy
@@ -106,83 +100,237 @@ test_primitive_type(void)
#include "dynamic_array.h"
static void
-test_struct(void)
+test_string
+ (struct mem_allocator* allocator0,
+ struct mem_allocator* allocator1)
{
- struct mem_allocator allocator_proxy;
- struct darray_struct_str darray, darray2;
+ struct darray_string darray, darray2;
const size_t nstrs = sizeof(strs)/sizeof(const char*);
size_t i = 0;
- mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
-
- darray_struct_str_init(&allocator_proxy, &darray);
- darray_struct_str_init(&allocator_proxy, &darray2);
- CHECK(darray_struct_str_size_get(&darray), 0);
- CHECK(darray_struct_str_size_get(&darray2), 0);
+ darray_string_init(allocator0, &darray);
+ darray_string_init(allocator1, &darray2);
+ CHECK(darray_string_size_get(&darray), 0);
+ CHECK(darray_string_size_get(&darray2), 0);
- darray_struct_str_resize(&darray, nstrs);
+ darray_string_resize(&darray, nstrs);
FOR_EACH(i, 0, nstrs) {
- str_set(darray_struct_str_data_get(&darray) + i, strs[i]);
+ str_set(darray_string_data_get(&darray) + i, strs[i]);
}
- CHECK(darray_struct_str_size_get(&darray), nstrs);
+ CHECK(darray_string_size_get(&darray), nstrs);
FOR_EACH(i, 0, nstrs) {
- const struct str* str = darray_struct_str_cdata_get(&darray) + i;
+ const struct str* str = darray_string_cdata_get(&darray) + i;
CHECK(strcmp(str_cget(str), strs[i]), 0);
}
- darray_struct_str_copy(&darray, &darray2);
- CHECK(darray_struct_str_size_get(&darray), 0);
+ darray_string_copy(&darray, &darray2);
+ CHECK(darray_string_size_get(&darray), 0);
FOR_EACH(i, 0, nstrs) {
struct str str;
- str_init(&allocator_proxy, &str);
+ str_init(allocator1, &str);
str_set(&str, strs[i]);
- darray_struct_str_push_back(&darray, &str);
+ darray_string_push_back(&darray, &str);
str_release(&str);
}
- CHECK(darray_struct_str_size_get(&darray), nstrs);
+ CHECK(darray_string_size_get(&darray), nstrs);
FOR_EACH(i, 0, nstrs) {
- const struct str* str = darray_struct_str_cdata_get(&darray) + i;
+ const struct str* str = darray_string_cdata_get(&darray) + i;
CHECK(strcmp(str_cget(str), strs[i]), 0);
}
- darray_struct_str_copy(&darray2, &darray);
- CHECK(darray_struct_str_size_get(&darray2), nstrs);
+ darray_string_copy(&darray2, &darray);
+ CHECK(darray_string_size_get(&darray2), nstrs);
FOR_EACH(i, 0, nstrs) {
- const struct str* str = darray_struct_str_cdata_get(&darray) + i;
- const struct str* str2 = darray_struct_str_cdata_get(&darray2) + i;
+ const struct str* str = darray_string_cdata_get(&darray) + i;
+ const struct str* str2 = darray_string_cdata_get(&darray2) + i;
CHECK(strcmp(str_cget(str), strs[i]), 0);
CHECK(strcmp(str_cget(str2), strs[i]), 0);
}
- darray_struct_str_clear(&darray2);
- CHECK(darray_struct_str_size_get(&darray2), 0);
+ darray_string_clear(&darray2);
+ CHECK(darray_string_size_get(&darray2), 0);
- darray_struct_str_copy_and_clear(&darray2, &darray);
- CHECK(darray_struct_str_size_get(&darray2), nstrs);
- CHECK(darray_struct_str_size_get(&darray), 0);
+ darray_string_copy_and_clear(&darray2, &darray);
+ CHECK(darray_string_size_get(&darray2), nstrs);
+ CHECK(darray_string_size_get(&darray), 0);
FOR_EACH(i, 0, nstrs) {
- const struct str* str = darray_struct_str_cdata_get(&darray2) + i;
+ const struct str* str = darray_string_cdata_get(&darray2) + i;
CHECK(strcmp(str_cget(str), strs[i]), 0);
}
- darray_struct_str_copy_and_release(&darray, &darray2);
+ darray_string_copy_and_release(&darray, &darray2);
FOR_EACH(i, 0, nstrs) {
- const struct str* str = darray_struct_str_cdata_get(&darray) + i;
+ const struct str* str = darray_string_cdata_get(&darray) + i;
CHECK(strcmp(str_cget(str), strs[i]), 0);
}
- darray_struct_str_release(&darray);
+ darray_string_release(&darray);
+}
- check_memory_allocator(&allocator_proxy);
- mem_shutdown_proxy_allocator(&allocator_proxy);
+#define DARRAY_NAME int
+#define DARRAY_DATA int
+#include "dynamic_array.h"
+
+static void
+test_swap_int
+ (struct mem_allocator* allocator0,
+ struct mem_allocator* allocator1)
+{
+ struct darray_int a;
+ struct darray_int b;
+ int i;
+
+ #define PUSH_BACK(V, E) { \
+ const int i__ = (E); \
+ CHECK(darray_int_push_back(&(V), &i__), RES_OK); \
+ } (void)0
+
+ darray_int_init(allocator0, &a);
+ darray_int_init(allocator1, &b);
+
+ PUSH_BACK(a, 1);
+ PUSH_BACK(a, 2);
+ PUSH_BACK(a, 3);
+ PUSH_BACK(b,-1);
+ PUSH_BACK(b,-2);
+
+ CHECK(darray_int_swap(&a, &b), RES_OK);
+ CHECK(darray_int_size_get(&a), 2);
+ CHECK(darray_int_size_get(&b), 3);
+
+ CHECK(darray_int_cdata_get(&a)[0],-1);
+ CHECK(darray_int_cdata_get(&a)[1],-2);
+ CHECK(darray_int_cdata_get(&b)[0], 1);
+ CHECK(darray_int_cdata_get(&b)[1], 2);
+ CHECK(darray_int_cdata_get(&b)[2], 3);
+
+ darray_int_clear(&a);
+ darray_int_clear(&b);
+
+ FOR_EACH(i, 0, 128) PUSH_BACK(a, i);
+ FOR_EACH(i, 0, 112) PUSH_BACK(b,-i);
+
+ CHECK(darray_int_swap(&a, &b), RES_OK);
+ CHECK(darray_int_size_get(&a), 112);
+ CHECK(darray_int_size_get(&b), 128);
+ FOR_EACH(i, 0, 112) CHECK(darray_int_cdata_get(&a)[i],-i);
+ FOR_EACH(i, 0, 128) CHECK(darray_int_cdata_get(&b)[i], i);
+
+ darray_int_release(&b);
+ darray_int_init(allocator1, &b);
+ PUSH_BACK(b, -1);
+ PUSH_BACK(b, -314);
+
+ CHECK(darray_int_swap(&a, &b), RES_OK);
+ CHECK(darray_int_size_get(&a), 2);
+ CHECK(darray_int_size_get(&b), 112);
+ FOR_EACH(i, 0, 112) CHECK(darray_int_cdata_get(&b)[i],-i);
+ CHECK(darray_int_cdata_get(&a)[0],-1);
+ CHECK(darray_int_cdata_get(&a)[1],-314);
+
+ darray_int_release(&a);
+ darray_int_release(&b);
+
+ #undef PUSH_BACK
+}
+
+static void
+test_swap_string
+ (struct mem_allocator* allocator0,
+ struct mem_allocator* allocator1)
+{
+ struct darray_string a;
+ struct darray_string b;
+ const size_t nstrs = sizeof(strs)/sizeof(const char*);
+ size_t i;
+
+ #define PUSH_BACK(V, CStr) { \
+ struct str str__; \
+ str_init(allocator1, &str__); \
+ CHECK(str_set(&str__, CStr), RES_OK); \
+ CHECK(darray_string_push_back(&(V), &str__), RES_OK); \
+ str_release(&str__); \
+ } (void)0
+
+ darray_string_init(allocator0, &a);
+ darray_string_init(allocator1, &b);
+
+ CHECK(nstrs >= 3, 1);
+ PUSH_BACK(a, strs[0]);
+ PUSH_BACK(a, strs[1]);
+ PUSH_BACK(a, strs[2]);
+ PUSH_BACK(b, strs[3]);
+ PUSH_BACK(b, strs[4]);
+
+ CHECK(darray_string_swap(&a, &b), RES_OK);
+ CHECK(darray_string_size_get(&a), 2);
+ CHECK(darray_string_size_get(&b), 3);
+
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&a)+0), strs[3]), 0);
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&a)+1), strs[4]), 0);
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&b)+0), strs[0]), 0);
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&b)+1), strs[1]), 0);
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&b)+2), strs[2]), 0);
+
+ darray_string_clear(&a);
+ darray_string_clear(&b);
+
+ FOR_EACH(i, 0, nstrs/2) PUSH_BACK(a, strs[i]);
+ FOR_EACH(i, nstrs/2, nstrs) PUSH_BACK(b, strs[i]);
+
+ CHECK(darray_string_swap(&a, &b), RES_OK);
+ CHECK(darray_string_size_get(&a), nstrs/2);
+ CHECK(darray_string_size_get(&b), nstrs - nstrs/2);
+
+ FOR_EACH(i, 0, nstrs/2) {
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&b)+i), strs[i]), 0);
+ }
+ FOR_EACH(i, 0, nstrs - nstrs/2) {
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&a)+i), strs[i+nstrs/2]), 0);
+ }
+
+ darray_string_release(&b);
+ darray_string_init(allocator1, &b);
+ PUSH_BACK(b, strs[0]);
+ PUSH_BACK(b, strs[1]);
+
+ CHECK(darray_string_swap(&a, &b), RES_OK);
+ CHECK(darray_string_size_get(&a), 2);
+ CHECK(darray_string_size_get(&b), nstrs - nstrs/2);
+ FOR_EACH(i, 0, nstrs - nstrs/2) {
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&b)+i), strs[i+nstrs/2]), 0);
+ }
+
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&a)+0), strs[0]), 0);
+ CHECK(strcmp(str_cget(darray_string_cdata_get(&a)+1), strs[1]), 0);
+
+ darray_string_release(&a);
+ darray_string_release(&b);
+
+ #undef PUSH_BACK
}
int
main(int argc, char** argv)
{
+ struct mem_allocator allocator_proxy;
(void)argc, (void)argv;
- test_primitive_type();
- test_struct();
+
+ mem_init_proxy_allocator(&allocator_proxy, &mem_default_allocator);
+
+ test_cstr(&allocator_proxy);
+
+ test_string(&allocator_proxy, &allocator_proxy);
+ test_string(&allocator_proxy, &mem_default_allocator);
+
+ test_swap_int(&mem_default_allocator, &allocator_proxy);
+ test_swap_int(&allocator_proxy, &allocator_proxy);
+
+ test_swap_string(&mem_default_allocator, &allocator_proxy);
+ test_swap_string(&allocator_proxy, &allocator_proxy);
+
+ check_memory_allocator(&allocator_proxy);
+ mem_shutdown_proxy_allocator(&allocator_proxy);
CHECK(mem_allocated_size(), 0);
return 0;
}