diff -r 89a2d53308e4 -r a2565f9fc6de src/array_list.c --- 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