1.1 --- a/src/array_list.c Sun Nov 13 13:29:15 2022 +0100 1.2 +++ b/src/array_list.c Wed Nov 16 22:27:46 2022 +0100 1.3 @@ -27,20 +27,91 @@ 1.4 */ 1.5 1.6 #include "cx/array_list.h" 1.7 +#include <assert.h> 1.8 +#include <string.h> 1.9 1.10 /* LOW LEVEL ARRAY LIST FUNCTIONS */ 1.11 1.12 +enum cx_array_coppy_result cx_array_copy( 1.13 + void **target, 1.14 + size_t *size, 1.15 + size_t *capacity, 1.16 + size_t index, 1.17 + void const *src, 1.18 + size_t elem_size, 1.19 + size_t elem_count, 1.20 + struct cx_array_reallocator_s *reallocator 1.21 +) { 1.22 + /* assert pointers */ 1.23 + assert(target != NULL); 1.24 + assert(size != NULL); 1.25 + assert(src != NULL); 1.26 1.27 + /* determine capacity */ 1.28 + size_t cap = capacity == NULL ? *size : *capacity; 1.29 + 1.30 + /* check if resize is required */ 1.31 + size_t newsize = index + elem_count; 1.32 + bool needrealloc = newsize > cap; 1.33 + 1.34 + /* reallocate if possible */ 1.35 + if (needrealloc) { 1.36 + /* a reallocator and a capacity variable must be available */ 1.37 + if (reallocator == NULL || capacity == NULL) { 1.38 + return CX_ARRAY_COPY_REALLOC_NOT_SUPPORTED; 1.39 + } 1.40 + 1.41 + /* increase capacity linearly */ 1.42 + cap += 16; 1.43 + 1.44 + /* perform reallocation */ 1.45 + void *newmem = reallocator->realloc( 1.46 + *target, cap, elem_size, reallocator 1.47 + ); 1.48 + if (newmem == NULL) { 1.49 + return CX_ARRAY_COPY_REALLOC_FAILED; 1.50 + } 1.51 + 1.52 + /* store new pointer and capacity */ 1.53 + *target = newmem; 1.54 + *capacity = cap; 1.55 + } 1.56 + 1.57 + /* determine target pointer */ 1.58 + char *start = *target; 1.59 + start += index * elem_size; 1.60 + 1.61 + /* copy elements and set new size */ 1.62 + memcpy(start, src, elem_count * elem_size); 1.63 + *size = newsize; 1.64 + 1.65 + /* return successfully */ 1.66 + return CX_ARRAY_COPY_SUCCESS; 1.67 +} 1.68 1.69 /* HIGH LEVEL ARRAY LIST FUNCTIONS */ 1.70 1.71 typedef struct { 1.72 struct cx_list_s base; 1.73 void *data; 1.74 + struct cx_array_reallocator_s reallocator; 1.75 } cx_array_list; 1.76 1.77 +static void *cx_arl_realloc( 1.78 + void *array, 1.79 + size_t capacity, 1.80 + size_t elem_size, 1.81 + struct cx_array_reallocator_s *alloc 1.82 +) { 1.83 + /* retrieve the pointer to the list allocator */ 1.84 + CxAllocator const *al = alloc->ptr1; 1.85 + 1.86 + /* use the list allocator to reallocate the memory */ 1.87 + return cxRealloc(al, array, capacity * elem_size); 1.88 +} 1.89 + 1.90 static void cx_arl_destructor(struct cx_list_s *list) { 1.91 - cx_array_list *arl = (cx_array_list*) list; 1.92 + cx_array_list *arl = (cx_array_list *) list; 1.93 cxFree(list->allocator, arl->data); 1.94 } 1.95 1.96 @@ -48,7 +119,17 @@ 1.97 struct cx_list_s *list, 1.98 void const *elem 1.99 ) { 1.100 - return 1; 1.101 + cx_array_list *arl = (cx_array_list *) list; 1.102 + return cx_array_copy( 1.103 + &arl->data, 1.104 + &list->size, 1.105 + &list->capacity, 1.106 + list->size, 1.107 + elem, 1.108 + list->itemsize, 1.109 + 1, 1.110 + &arl->reallocator 1.111 + ); 1.112 } 1.113 1.114 static int cx_arl_insert( 1.115 @@ -74,11 +155,17 @@ 1.116 return 1; 1.117 } 1.118 1.119 -static void * cx_arl_at( 1.120 +static void *cx_arl_at( 1.121 struct cx_list_s const *list, 1.122 size_t index 1.123 ) { 1.124 - return NULL; 1.125 + if (index < list->size) { 1.126 + cx_array_list const *arl = (cx_array_list const *) list; 1.127 + char *space = arl->data; 1.128 + return space + index * list->itemsize; 1.129 + } else { 1.130 + return NULL; 1.131 + } 1.132 } 1.133 1.134 static size_t cx_arl_find( 1.135 @@ -147,5 +234,9 @@ 1.136 list->base.itemsize = item_size; 1.137 list->base.capacity = initial_capacity; 1.138 1.139 + /* configure the reallocator */ 1.140 + list->reallocator.realloc = cx_arl_realloc; 1.141 + list->reallocator.ptr1 = (void *) allocator; 1.142 + 1.143 return (CxList *) list; 1.144 }