src/array_list.c

changeset 953
581ad4fd01e9
parent 926
8fdd8d78c14b
--- 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;
 }

mercurial