diff -r dc53362bc5a7 -r 581ad4fd01e9 src/array_list.c --- a/src/array_list.c Tue Oct 29 16:53:00 2024 +0100 +++ b/src/array_list.c Tue Oct 29 18:14:02 2024 +0100 @@ -37,16 +37,54 @@ void *array, size_t capacity, size_t elem_size, - __attribute__((__unused__)) struct cx_array_reallocator_s *alloc + __attribute__((__unused__)) CxArrayReallocator *alloc ) { return realloc(array, capacity * elem_size); } -struct cx_array_reallocator_s cx_array_default_reallocator_impl = { +CxArrayReallocator cx_array_default_reallocator_impl = { cx_array_default_realloc, NULL, NULL, 0, 0 }; -struct cx_array_reallocator_s *cx_array_default_reallocator = &cx_array_default_reallocator_impl; +CxArrayReallocator *cx_array_default_reallocator = &cx_array_default_reallocator_impl; + +// Stack-aware array reallocator + +static void *cx_array_advanced_realloc( + void *array, + size_t capacity, + size_t elem_size, + __attribute__((__unused__)) CxArrayReallocator *alloc +) { + // retrieve the pointer to the actual allocator + const CxAllocator *al = alloc->ptr1; + + // check if the array is still located on the stack + void *newmem; + if (array == alloc->ptr2) { + newmem = cxMalloc(al, capacity * elem_size); + if (newmem != NULL) { + memcpy(newmem, array, capacity * elem_size); + } + } else { + newmem = cxRealloc(al, array, capacity * elem_size); + } + return newmem; +} + +struct cx_array_reallocator_s cx_array_reallocator( + const struct cx_allocator_s *allocator, + const void *stackmem +) { + if (allocator == NULL) { + allocator = cxDefaultAllocator; + } + return (struct cx_array_reallocator_s) { + cx_array_advanced_realloc, + (void*) allocator, (void*) stackmem, + 0, 0 + }; +} // LOW LEVEL ARRAY LIST FUNCTIONS @@ -58,7 +96,7 @@ const void *src, size_t elem_size, size_t elem_count, - struct cx_array_reallocator_s *reallocator + CxArrayReallocator *reallocator ) { // assert pointers assert(target != NULL); @@ -128,7 +166,7 @@ const void *sorted_data, size_t elem_size, size_t elem_count, - struct cx_array_reallocator_s *reallocator + CxArrayReallocator *reallocator ) { // assert pointers assert(target != NULL); @@ -337,22 +375,9 @@ struct cx_list_s base; void *data; size_t capacity; - struct cx_array_reallocator_s reallocator; + CxArrayReallocator 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 - const CxAllocator *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; @@ -783,8 +808,7 @@ } // configure the reallocator - list->reallocator.realloc = cx_arl_realloc; - list->reallocator.ptr1 = (void *) allocator; + list->reallocator = cx_array_reallocator(allocator, NULL); return (CxList *) list; }