src/array_list.c

changeset 1626
a2565f9fc6de
parent 1622
27e7a4bf1a39
child 1632
f74e4fc496a2
--- a/src/array_list.c	Thu Dec 18 18:07:29 2025 +0100
+++ b/src/array_list.c	Fri Dec 19 12:40:58 2025 +0100
@@ -390,6 +390,50 @@
     return cxIteratorPtr(array->data, array->size);
 }
 
+void cx_array_remove_(CxArray *array, size_t elem_size, size_t index, size_t n, bool fast) {
+    if (n == 0) return;
+    if (index >= array->size) return;
+    if (index + n >= array->size) {
+        // only tail elements are removed
+        array->size = index;
+        return;
+    }
+    array->size -= n;
+    size_t remaining = array->size - index;
+    char *dest = ((char*)array->data) + index * elem_size;
+    if (fast) {
+        char *src = dest + remaining * elem_size;
+        if (n == 1 && elem_size <= CX_WORDSIZE/8) {
+            // try to optimize int-sized values
+            // (from likely to unlikely)
+            if (elem_size == sizeof(int32_t)) {
+                *(int32_t*)dest = *(int32_t*)src;
+                return;
+            }
+#if CX_WORDSIZE == 64
+            if (elem_size == sizeof(int64_t)) {
+                *(int64_t*)dest = *(int64_t*)src;
+                return;
+            }
+#endif
+            if (elem_size == sizeof(int8_t)) {
+                *(int8_t*)dest = *(int8_t*)src;
+                return;
+            }
+            if (elem_size == sizeof(int16_t)) {
+                *(int16_t*)dest = *(int16_t*)src;
+                return;
+            }
+            // note we cannot optimize the last branch, because
+            // the elem_size could be crazily misaligned
+        }
+        memcpy(dest, src, n * elem_size);
+    } else {
+        char *src = dest + n * elem_size;
+        memmove(dest, src, remaining * elem_size);
+    }
+}
+
 void cx_array_free_(const CxAllocator *allocator, CxArray *array) {
     cxFree(allocator, array->data);
     array->data = NULL;
@@ -785,10 +829,9 @@
     }
 
     // just move the elements to the left
-    char *first_remaining = arl->data;
-    first_remaining += (index + remove) * list->collection.elem_size;
     char *dst_move = arl->data;
     dst_move += index * list->collection.elem_size;
+    char *first_remaining = dst_move + remove * list->collection.elem_size;
     memmove(dst_move, first_remaining, remaining * list->collection.elem_size);
 
     // decrease the size

mercurial