rsys

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

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:
Msrc/dynamic_array.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_dynamic_array.c | 250+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
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; }