ucx/array_list.c

branch
dav-2
changeset 886
da79af4baec8
parent 854
1c8401ece69e
child 889
42cdbf9bbd49
--- a/ucx/array_list.c	Tue Sep 09 16:01:30 2025 +0200
+++ b/ucx/array_list.c	Tue Sep 09 20:56:47 2025 +0200
@@ -36,16 +36,17 @@
 
 static void *cx_array_default_realloc(
         void *array,
-        size_t capacity,
+        cx_attr_unused size_t old_capacity,
+        size_t new_capacity,
         size_t elem_size,
         cx_attr_unused CxArrayReallocator *alloc
 ) {
     size_t n;
-    if (cx_szmul(capacity, elem_size, &n)) {
+    if (cx_szmul(new_capacity, elem_size, &n)) {
         errno = EOVERFLOW;
         return NULL;
     }
-    return realloc(array, n);
+    return cxReallocDefault(array, n);
 }
 
 CxArrayReallocator cx_array_default_reallocator_impl = {
@@ -58,13 +59,14 @@
 
 static void *cx_array_advanced_realloc(
         void *array,
-        size_t capacity,
+        size_t old_capacity,
+        size_t new_capacity,
         size_t elem_size,
         cx_attr_unused CxArrayReallocator *alloc
 ) {
     // check for overflow
     size_t n;
-    if (cx_szmul(capacity, elem_size, &n)) {
+    if (cx_szmul(new_capacity, elem_size, &n)) {
         errno = EOVERFLOW;
         return NULL;
     }
@@ -77,7 +79,7 @@
     if (array == alloc->ptr2) {
         newmem = cxMalloc(al, n);
         if (newmem != NULL && array != NULL) {
-            memcpy(newmem, array, n);
+            memcpy(newmem, array, old_capacity*elem_size);
         }
     } else {
         newmem = cxRealloc(al, array, n);
@@ -180,7 +182,7 @@
 
         // perform reallocation
         void *newmem = reallocator->realloc(
-                *array, newcap, elem_size, reallocator
+                *array, oldcap, newcap, elem_size, reallocator
         );
         if (newmem == NULL) {
             return 1; // LCOV_EXCL_LINE
@@ -286,7 +288,7 @@
 
         // perform reallocation
         void *newmem = reallocator->realloc(
-                *target, newcap, elem_size, reallocator
+                *target, oldcap, newcap, elem_size, reallocator
         );
         if (newmem == NULL) {
             return 1;
@@ -366,13 +368,14 @@
 
     // store some counts
     size_t old_size = *size;
+    size_t old_capacity = *capacity;
     size_t needed_capacity = old_size + elem_count;
 
     // if we need more than we have, try a reallocation
-    if (needed_capacity > *capacity) {
+    if (needed_capacity > old_capacity) {
         size_t new_capacity = cx_array_align_capacity(needed_capacity, 16, SIZE_MAX);
         void *new_mem = reallocator->realloc(
-                *target, new_capacity, elem_size, reallocator
+                *target, old_capacity, new_capacity, elem_size, reallocator
         );
         if (new_mem == NULL) {
             // give it up right away, there is no contract
@@ -572,7 +575,7 @@
 
     // decide if we can use the local buffer
     if (elem_size > CX_ARRAY_SWAP_SBO_SIZE) {
-        tmp = malloc(elem_size);
+        tmp = cxMallocDefault(elem_size);
         // we don't want to enforce error handling
         if (tmp == NULL) abort();
     } else {
@@ -591,7 +594,7 @@
 
     // free dynamic memory, if it was needed
     if (tmp != sbo_mem) {
-        free(tmp);
+        cxFreeDefault(tmp);
     }
 }
 
@@ -638,50 +641,38 @@
     // get a correctly typed pointer to the list
     cx_array_list *arl = (cx_array_list *) list;
 
-    // do we need to move some elements?
-    if (index < list->collection.size) {
-        const char *first_to_move = (const char *) arl->data;
-        first_to_move += index * list->collection.elem_size;
-        size_t elems_to_move = list->collection.size - index;
-        size_t start_of_moved = index + n;
-
-        if (cx_array_copy(
-                &arl->data,
-                &list->collection.size,
-                &arl->capacity,
-                0,
-                start_of_moved,
-                first_to_move,
-                list->collection.elem_size,
-                elems_to_move,
-                &arl->reallocator
-        )) {
-            // if moving existing elems is unsuccessful, abort
+    // guarantee enough capacity
+    if (arl->capacity < list->collection.size + n) {
+        size_t new_capacity = list->collection.size + n;
+        new_capacity = new_capacity - (new_capacity % 16) + 16;
+        if (cxReallocateArray(
+                list->collection.allocator,
+                &arl->data, new_capacity,
+                list->collection.elem_size)
+        ) {
             return 0;
         }
+        arl->capacity = new_capacity;
     }
 
-    // note that if we had to move the elements, the following operation
-    // is guaranteed to succeed, because we have the memory already allocated
-    // therefore, it is impossible to leave this function with an invalid array
+    // determine insert position
+    char *arl_data = arl->data;
+    char *insert_pos = arl_data + index * list->collection.elem_size;
 
-    // place the new elements
-    if (cx_array_copy(
-            &arl->data,
-            &list->collection.size,
-            &arl->capacity,
-            0,
-            index,
-            array,
-            list->collection.elem_size,
-            n,
-            &arl->reallocator
-    )) {
-        // array list implementation is "all or nothing"
-        return 0;
-    } else {
-        return n;
+    // do we need to move some elements?
+    if (index < list->collection.size) {
+        size_t elems_to_move = list->collection.size - index;
+        char *target = insert_pos + n * list->collection.elem_size;
+        memmove(target, insert_pos, elems_to_move * list->collection.elem_size);
     }
+
+    // place the new elements, if any
+    if (array != NULL) {
+        memcpy(insert_pos, array, n * list->collection.elem_size);
+    }
+    list->collection.size += n;
+
+    return n;
 }
 
 static size_t cx_arl_insert_sorted(
@@ -709,12 +700,16 @@
     }
 }
 
-static int cx_arl_insert_element(
+static void *cx_arl_insert_element(
         struct cx_list_s *list,
         size_t index,
         const void *element
 ) {
-    return 1 != cx_arl_insert_array(list, index, element, 1);
+    if (cx_arl_insert_array(list, index, element, 1) == 1) {
+        return ((char*)((cx_array_list *) list)->data) + index * list->collection.elem_size;
+    } else {
+        return NULL;
+    }
 }
 
 static int cx_arl_insert_iter(
@@ -724,26 +719,23 @@
 ) {
     struct cx_list_s *list = iter->src_handle.m;
     if (iter->index < list->collection.size) {
-        int result = cx_arl_insert_element(
-                list,
-                iter->index + 1 - prepend,
-                elem
-        );
-        if (result == 0) {
-            iter->elem_count++;
-            if (prepend != 0) {
-                iter->index++;
-                iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
-            }
+        if (cx_arl_insert_element(list,
+                iter->index + 1 - prepend, elem) == NULL) {
+            return 1;
+        }
+        iter->elem_count++;
+        if (prepend != 0) {
+            iter->index++;
+            iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
         }
-        return result;
+        return 0;
     } else {
-        int result = cx_arl_insert_element(list, list->collection.size, elem);
-        if (result == 0) {
-            iter->elem_count++;
-            iter->index = list->collection.size;
+        if (cx_arl_insert_element(list, list->collection.size, elem) == NULL) {
+            return 1;
         }
-        return result;
+        iter->elem_count++;
+        iter->index = list->collection.size;
+        return 0;
     }
 }
 

mercurial