# HG changeset patch # User Mike Becker # Date 1668634066 -3600 # Node ID de5d3ee6435f0b4df7c38ed0d5bd90b38bfd6f52 # Parent 6ae8146d9f6289b7e0d46da6a13c37863a543f64 #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. diff -r 6ae8146d9f62 -r de5d3ee6435f src/array_list.c --- 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 +#include /* 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; } diff -r 6ae8146d9f62 -r de5d3ee6435f src/cx/array_list.h --- 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))); /** diff -r 6ae8146d9f62 -r de5d3ee6435f test/test_list.cpp --- 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()); }