Wed, 16 Nov 2022 22:27:46 +0100
#219 array list: implement add and at
Add uses the low level cx_array_copy function which is
now also implemented, but not tested by individual unit
tests.
src/array_list.c | file | annotate | diff | comparison | revisions | |
src/cx/array_list.h | file | annotate | diff | comparison | revisions | |
test/test_list.cpp | file | annotate | diff | comparison | revisions |
--- a/src/array_list.c Sun Nov 13 13:29:15 2022 +0100 +++ b/src/array_list.c Wed Nov 16 22:27:46 2022 +0100 @@ -27,20 +27,91 @@ */ #include "cx/array_list.h" +#include <assert.h> +#include <string.h> /* LOW LEVEL ARRAY LIST FUNCTIONS */ +enum cx_array_coppy_result cx_array_copy( + void **target, + size_t *size, + size_t *capacity, + size_t index, + void const *src, + size_t elem_size, + size_t elem_count, + struct cx_array_reallocator_s *reallocator +) { + /* assert pointers */ + assert(target != NULL); + assert(size != NULL); + assert(src != NULL); + /* determine capacity */ + size_t cap = capacity == NULL ? *size : *capacity; + + /* check if resize is required */ + size_t newsize = index + elem_count; + bool needrealloc = newsize > cap; + + /* reallocate if possible */ + if (needrealloc) { + /* a reallocator and a capacity variable must be available */ + if (reallocator == NULL || capacity == NULL) { + return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED; + } + + /* increase capacity linearly */ + cap += 16; + + /* perform reallocation */ + void *newmem = reallocator->realloc( + *target, cap, elem_size, reallocator + ); + if (newmem == NULL) { + return CX_ARRAY_COPY_REALLOC_FAILED; + } + + /* store new pointer and capacity */ + *target = newmem; + *capacity = cap; + } + + /* determine target pointer */ + char *start = *target; + start += index * elem_size; + + /* copy elements and set new size */ + memcpy(start, src, elem_count * elem_size); + *size = newsize; + + /* return successfully */ + return CX_ARRAY_COPY_SUCCESS; +} /* HIGH LEVEL ARRAY LIST FUNCTIONS */ typedef struct { struct cx_list_s base; void *data; + struct cx_array_reallocator_s reallocator; } cx_array_list; +static void *cx_arl_realloc( + void *array, + size_t capacity, + size_t elem_size, + struct cx_array_reallocator_s *alloc +) { + /* retrieve the pointer to the list allocator */ + CxAllocator const *al = alloc->ptr1; + + /* use the list allocator to reallocate the memory */ + return cxRealloc(al, array, capacity * elem_size); +} + static void cx_arl_destructor(struct cx_list_s *list) { - cx_array_list *arl = (cx_array_list*) list; + cx_array_list *arl = (cx_array_list *) list; cxFree(list->allocator, arl->data); } @@ -48,7 +119,17 @@ struct cx_list_s *list, void const *elem ) { - return 1; + cx_array_list *arl = (cx_array_list *) list; + return cx_array_copy( + &arl->data, + &list->size, + &list->capacity, + list->size, + elem, + list->itemsize, + 1, + &arl->reallocator + ); } static int cx_arl_insert( @@ -74,11 +155,17 @@ return 1; } -static void * cx_arl_at( +static void *cx_arl_at( struct cx_list_s const *list, size_t index ) { - return NULL; + if (index < list->size) { + cx_array_list const *arl = (cx_array_list const *) list; + char *space = arl->data; + return space + index * list->itemsize; + } else { + return NULL; + } } static size_t cx_arl_find( @@ -147,5 +234,9 @@ list->base.itemsize = item_size; list->base.capacity = initial_capacity; + /* configure the reallocator */ + list->reallocator.realloc = cx_arl_realloc; + list->reallocator.ptr1 = (void *) allocator; + return (CxList *) list; }
--- a/src/cx/array_list.h Sun Nov 13 13:29:15 2022 +0100 +++ b/src/cx/array_list.h Wed Nov 16 22:27:46 2022 +0100 @@ -89,6 +89,15 @@ }; /** + * Return codes for cx_array_copy(). + */ +enum cx_array_coppy_result { + CX_ARRAY_COPY_SUCCESS, + CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED, + CX_ARRAY_COPY_REALLOC_FAILED, +}; + +/** * Copies elements from one array to another. * * The elements are copied to the \p target array at the specified \p index, @@ -110,9 +119,9 @@ * @param elem_count the number of elements to copy * @param reallocator the array re-allocator to use, or \c NULL * if re-allocation shall not happen - * @return zero on success, non-zero on failure + * @return zero on success, non-zero error code on failure */ -int cx_array_copy( +enum cx_array_coppy_result cx_array_copy( void **target, size_t *size, size_t *capacity, @@ -120,7 +129,7 @@ void const *src, size_t elem_size, size_t elem_count, - struct cx_array_reallocator_s const *reallocator + struct cx_array_reallocator_s *reallocator ) __attribute__((__nonnull__(1, 2, 5))); /**
--- a/test/test_list.cpp Sun Nov 13 13:29:15 2022 +0100 +++ b/test/test_list.cpp Wed Nov 16 22:27:46 2022 +0100 @@ -827,7 +827,6 @@ } TEST_F(ArrayList, cxListAdd) { - ASSERT_EQ(1,0); // TODO: remove when implemented CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); verifyAdd(list, false); } @@ -867,7 +866,6 @@ } TEST_F(ArrayList, cxListAt) { - ASSERT_EQ(1,0); // TODO: remove when implemented verifyAt(arrayListFromTestData()); }