ucx/cx/array_list.h

changeset 1040
473d8cb58a6c
parent 1034
330b415910bd
--- a/ucx/cx/array_list.h	Wed Dec 31 12:37:09 2025 +0100
+++ b/ucx/cx/array_list.h	Wed Dec 31 16:40:12 2025 +0100
@@ -39,10 +39,6 @@
 
 #include "list.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * The maximum item size in an array list that fits into
  * a stack buffer when swapped.
@@ -88,8 +84,8 @@
  * @retval zero allocation was successful
  * @retval non-zero allocation failed
  */
-cx_attr_nonnull
-CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
+CX_EXTERN CX_NONNULL
+int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
 
 /**
  * Initializes an array by allocating memory.
@@ -131,8 +127,8 @@
  * @param capacity the capacity of the fixed size array
  * @param size the number of initialized elements in the fixed size array
  */
-cx_attr_nonnull
-CX_EXPORT void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size);
+CX_EXTERN CX_NONNULL
+void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size);
 
 /**
  * Initializes an array with fixed size memory.
@@ -173,8 +169,8 @@
  * @retval zero allocation was successful
  * @retval non-zero allocation failed
  */
-cx_attr_nonnull
-CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
+CX_EXTERN CX_NONNULL
+int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
 
 /**
  * Changes the capacity of an array.
@@ -215,8 +211,8 @@
  * @retval zero allocation was successful
  * @retval non-zero allocation failed
  */
-cx_attr_nonnull
-CX_EXPORT int cx_array_copy_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
+CX_EXTERN CX_NONNULL
+int cx_array_copy_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
 
 /**
  * Copies the array to a new memory region.
@@ -269,8 +265,8 @@
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-cx_attr_nonnull_arg(1, 2)
-CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
+CX_EXTERN CX_NONNULL_ARG(1, 2)
+int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
         size_t elem_size, size_t index, const void *other, size_t n);
 
 /**
@@ -397,17 +393,17 @@
  * @param allocator the allocator to use for a possible reallocation
  * @param array a pointer to the array structure
  * @param elem_size the size of one element
- * @param cmp_func
  * @param sorted_data a pointer to an array of data that shall be inserted
  * @param n the number of elements that shall be inserted
+ * @param cmp_func the compare function
  * @param allow_duplicates @c false if duplicates shall be skipped during insertion
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-cx_attr_nonnull
-CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
-        size_t elem_size, cx_compare_func cmp_func, const void *sorted_data, size_t n,
-        bool allow_duplicates);
+CX_EXTERN CX_NONNULL
+int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
+        size_t elem_size, const void *sorted_data, size_t n,
+        cx_compare_func cmp_func, bool allow_duplicates);
 
 /**
  * Inserts an element into a sorted array.
@@ -418,13 +414,13 @@
  *
  * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
  * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
  * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
- * @param element (@c void*) a pointer to element that shall be inserted
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_sorted_a(allocator, array, cmp_func, element) \
-        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, true)
+#define cx_array_insert_sorted_a(allocator, array, element, cmp_func) \
+        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, true)
 
 /**
  * Inserts an element into a sorted array.
@@ -434,13 +430,13 @@
  * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
  *
  * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
  * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
- * @param element (@c void*) a pointer to element that shall be inserted
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_sorted(array, cmp_func, element) \
-        cx_array_insert_sorted_a(cxDefaultAllocator, array, cmp_func, element)
+#define cx_array_insert_sorted(array, element, cmp_func) \
+        cx_array_insert_sorted_a(cxDefaultAllocator, array, element, cmp_func)
 
 /**
  * Inserts sorted data into a sorted array.
@@ -451,14 +447,14 @@
  *
  * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
  * @param array the name of the array where the elements shall be inserted
- * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
  * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_sorted_array_a(allocator, array, cmp_func, sorted_data, n) \
-        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, true)
+#define cx_array_insert_sorted_array_a(allocator, array, sorted_data, n, cmp_func) \
+        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, true)
 
 /**
  * Inserts sorted data into a sorted array.
@@ -468,14 +464,14 @@
  * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
  *
  * @param array the name of the array where the elements shall be inserted
- * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
  * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_sorted_array(array, cmp_func, sorted_data, n) \
-        cx_array_insert_sorted_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n)
+#define cx_array_insert_sorted_array(array, sorted_data, n, cmp_func) \
+        cx_array_insert_sorted_array_a(cxDefaultAllocator, array, sorted_data, n, cmp_func)
 
 /**
  * Inserts an element into a sorted array if it is not already contained.
@@ -486,13 +482,13 @@
  *
  * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
  * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
  * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
- * @param element (@c void*) a pointer to element that shall be inserted
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_unique_a(allocator, array, cmp_func, element) \
-        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, false)
+#define cx_array_insert_unique_a(allocator, array, element, cmp_func) \
+        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, false)
 
 /**
  * Inserts an element into a sorted array if it is not already contained.
@@ -502,13 +498,13 @@
  * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
  *
  * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
  * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
- * @param element (@c void*) a pointer to element that shall be inserted
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_unique(array, cmp_func, element) \
-        cx_array_insert_unique_a(cxDefaultAllocator, array, cmp_func, element)
+#define cx_array_insert_unique(array, element, cmp_func) \
+        cx_array_insert_unique_a(cxDefaultAllocator, array, element, cmp_func)
 
 /**
  * Inserts sorted data into a sorted array, skipping duplicates.
@@ -519,14 +515,14 @@
  *
  * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
  * @param array the name of the array where the elements shall be inserted
- * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
  * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_unique_array_a(allocator, array, cmp_func, sorted_data, n) \
-        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, false)
+#define cx_array_insert_unique_array_a(allocator, array, sorted_data, n, cmp_func) \
+        cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, false)
 
 /**
  * Inserts sorted data into a sorted array, skipping duplicates.
@@ -536,14 +532,240 @@
  * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
  *
  * @param array the name of the array where the elements shall be inserted
- * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
  * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
  * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_unique_array(array, sorted_data, n, cmp_func) \
+        cx_array_insert_unique_array_a(cxDefaultAllocator, array, sorted_data, n, cmp_func)
+
+/**
+ * Inserts sorted data into a sorted array.
+ *
+ * Internal function - do not use.
+ *
+ * @param allocator the allocator to use for a possible reallocation
+ * @param array a pointer to the array structure
+ * @param elem_size the size of one element
+ * @param sorted_data a pointer to an array of data that shall be inserted
+ * @param n the number of elements that shall be inserted
+ * @param cmp_func the compare function
+ * @param context additional context for the compare function
+ * @param allow_duplicates @c false if duplicates shall be skipped during insertion
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+CX_EXTERN CX_NONNULL_ARG(1, 2, 4, 6)
+int cx_array_insert_sorted_c_(const CxAllocator *allocator, CxArray *array,
+        size_t elem_size, const void *sorted_data, size_t n,
+        cx_compare_func2 cmp_func, void *context, bool allow_duplicates);
+
+/**
+ * Inserts an element into a sorted array.
+ *
+ * When the capacity is not enough to hold the new element, a re-allocation is attempted.
+ *
+ * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
+ * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_sorted_ca(allocator, array, element, cmp_func, context) \
+        cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, context, true)
+
+/**
+ * Inserts an element into a sorted array.
+ *
+ * When the capacity is not enough to hold the new element, a re-allocation is attempted.
+ *
+ * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_sorted_c(array, element, cmp_func, context) \
+        cx_array_insert_sorted_ca(cxDefaultAllocator, array, element, cmp_func, context)
+
+/**
+ * Inserts sorted data into a sorted array.
+ *
+ * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
+ *
+ * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
+ * @param array the name of the array where the elements shall be inserted
+ * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
+ * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_sorted_array_ca(allocator, array, sorted_data, n, cmp_func, context) \
+        cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, context, true)
+
+/**
+ * Inserts sorted data into a sorted array.
+ *
+ * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
+ *
+ * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param array the name of the array where the elements shall be inserted
+ * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
+ * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_sorted_array_c(array, sorted_data, n, cmp_func, context) \
+        cx_array_insert_sorted_array_ca(cxDefaultAllocator, array, sorted_data, n, cmp_func, context)
+
+/**
+ * Inserts an element into a sorted array if it is not already contained.
+ *
+ * When the capacity is not enough to hold the new element, a re-allocation is attempted.
+ *
+ * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
+ * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
  * @retval zero success
  * @retval non-zero a re-allocation was necessary but failed
  */
-#define cx_array_insert_unique_array(array, cmp_func, sorted_data, n) \
-        cx_array_insert_unique_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n)
+#define cx_array_insert_unique_ca(allocator, array, element, cmp_func, context) \
+        cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, context, false)
+
+/**
+ * Inserts an element into a sorted array if it is not already contained.
+ *
+ * When the capacity is not enough to hold the new element, a re-allocation is attempted.
+ *
+ * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param array the name of the array where the elements shall be inserted
+ * @param element the element that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_unique_c(array, element, cmp_func, context) \
+        cx_array_insert_unique_ca(cxDefaultAllocator, array, element, cmp_func, context)
+
+/**
+ * Inserts sorted data into a sorted array, skipping duplicates.
+ *
+ * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
+ *
+ * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
+ * @param array the name of the array where the elements shall be inserted
+ * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
+ * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_unique_array_ca(allocator, array, sorted_data, n, cmp_func, context) \
+        cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, context, false)
+
+/**
+ * Inserts sorted data into a sorted array, skipping duplicates.
+ *
+ * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
+ *
+ * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
+ *
+ * @param array the name of the array where the elements shall be inserted
+ * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
+ * @param n (@c size_t) the number of elements that shall be inserted
+ * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
+ * @param context (@c void*) additional context for the compare function
+ * @retval zero success
+ * @retval non-zero a re-allocation was necessary but failed
+ */
+#define cx_array_insert_unique_array_c(array, sorted_data, n, cmp_func, context) \
+        cx_array_insert_unique_array_ca(cxDefaultAllocator, array, sorted_data, n, cmp_func, context)
+
+/**
+ * An alternative to qsort_r() when that is not available on your platform.
+ *
+ * If it is available, qsort_r() is used directly.
+ *
+ * @param array the array that shall be sorted
+ * @param nmemb the number of elements in the array
+ * @param size the size of one element
+ * @param fn the compare function
+ * @param context the context for the compare function
+ */
+CX_EXTERN CX_NONNULL
+void cx_array_qsort_c(void *array, size_t nmemb, size_t size,
+        cx_compare_func2 fn, void *context);
+
+/**
+ * Sorts an array.
+ *
+ * Internal function - do not use.
+ *
+ * @param array a pointer to the array structure
+ * @param elem_size the size of one element
+ * @param fn the compare function
+ */
+CX_EXTERN CX_NONNULL
+void cx_array_sort_(CxArray *array, size_t elem_size,
+        cx_compare_func fn);
+
+/**
+ * Sorts an array.
+ *
+ * Internal function - do not use.
+ *
+ * @param array a pointer to the array structure
+ * @param elem_size the size of one element
+ * @param fn the compare function
+ * @param context the context for the compare function
+ */
+CX_EXTERN CX_NONNULL
+void cx_array_sort_c_(CxArray *array, size_t elem_size,
+        cx_compare_func2 fn, void *context);
+
+/**
+ * Sorts an array.
+ *
+ * @param array the name of the array
+ * @param fn (@c cx_compare_func) the compare function
+ */
+#define cx_array_sort(array, fn) \
+        cx_array_sort_((CxArray*)&(array), sizeof((array).data[0]), fn)
+
+/**
+ * Sorts an array.
+ *
+ * @param array the name of the array
+ * @param fn (@c cx_compare_func2) the compare function
+ * @param context (@c void*) the context for the compare function
+ */
+#define cx_array_sort_c(array, fn, context) \
+        cx_array_sort_c_((CxArray*)&(array), sizeof((array).data[0]), fn, context)
 
 /**
  * Creates an iterator over the elements of an array.
@@ -554,14 +776,17 @@
  * @param elem_size the size of one element
  * @return an iterator over the elements
  */
-cx_attr_nodiscard cx_attr_nonnull
-CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size);
+CX_EXTERN CX_NODISCARD CX_NONNULL
+CxIterator cx_array_iterator_(CxArray *array, size_t elem_size);
 
 /**
  * Creates an iterator over the elements of an array.
  *
  * The iterator will yield pointers to the elements.
  *
+ * This iterator cannot be used to remove elements
+ * because it does not get a modifiable reference to the array's size.
+ *
  * @param array the name of the array
  * @return an iterator over the elements
  * @see cx_array_iterator_ptr()
@@ -577,8 +802,8 @@
  * @param array the name of the array
  * @return an iterator over the elements
  */
-cx_attr_nodiscard cx_attr_nonnull
-CX_EXPORT CxIterator cx_array_iterator_ptr_(CxArray *array);
+CX_EXTERN CX_NODISCARD CX_NONNULL
+CxIterator cx_array_iterator_ptr_(CxArray *array);
 
 /**
  * Creates an iterator over the elements of an array containing pointers.
@@ -586,6 +811,9 @@
  * The iterator will yield the elements themselves, which are supposed to
  * be pointers.
  *
+ * This iterator cannot be used to remove elements
+ * because it does not get a modifiable reference to the array's size.
+ *
  * @param array the name of the array
  * @return an iterator over the elements
  * @see cx_array_iterator()
@@ -593,6 +821,87 @@
 #define cx_array_iterator_ptr(array) \
         cx_array_iterator_ptr_((CxArray*)&(array))
 
+
+/**
+ * Removes elements from the array.
+ *
+ * Internal function - do not use.
+ *
+ * @param array a pointer to the array structure
+ * @param elem_size the size of one element
+ * @param index the index of the first element to remove
+ * @param n the number of elements to remove
+ * @param fast indicates whether tail elements should be copied into the gap
+ */
+CX_EXTERN CX_NONNULL
+void cx_array_remove_(CxArray *array, size_t elem_size, size_t index, size_t n, bool fast);
+
+/**
+ * Removes one element from the array.
+ *
+ * Tail elements are all moved by one. If you don't need a stable order
+ * in the array, consider using cx_array_remove_fast().
+ *
+ * If the index is out of bounds, this function does nothing.
+ *
+ * @param array the name of the array
+ * @param index (@c size_t) the index of the element to remove
+ * @see cx_array_remove_fast()
+ */
+#define cx_array_remove(array, index) \
+        cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, 1, false)
+
+/**
+ * Removes one element from the array.
+ *
+ * The gap will be filled with a copy of the last element in the array.
+ * This changes the order of elements. If you want a stable order,
+ * use cx_array_remove() instead.
+ *
+ * If the index is out of bounds, this function does nothing.
+ *
+ * @param array the name of the array
+ * @param index (@c size_t) the index of the element to remove
+ * @see cx_array_remove()
+ */
+#define cx_array_remove_fast(array, index) \
+        cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, 1, true)
+
+/**
+ * Removes multiple elements from the array.
+ *
+ * Tail elements are all moved to close the gap. If you don't need a stable
+ * order in the array, consider using cx_array_remove_array_fast().
+ *
+ * If the index is out of bounds, this function does nothing.
+ * If @n overflows the array, this function removes as many elements as it can.
+ *
+ * @param array the name of the array
+ * @param index (@c size_t) the index of the first element to remove
+ * @param n (@c size_t) the number of elements to remove
+ * @see cx_array_remove_array_fast()
+ */
+#define cx_array_remove_array(array, index, n) \
+        cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, n, false)
+
+/**
+ * Removes multiple elements from the array.
+ *
+ * Tail elements are copied into the gap. If you have more tail elements
+ * than the number of elements that are removed, this will change the order
+ * of elements. If you want a stable order, use cx_array_remove_array() instead.
+ *
+ * If the index is out of bounds, this function does nothing.
+ * If @n overflows the array, this function removes as many elements as it can.
+ *
+ * @param array the name of the array
+ * @param index (@c size_t) the index of the first element to remove
+ * @param n (@c size_t) the number of elements to remove
+ * @see cx_array_remove_array()
+ */
+#define cx_array_remove_array_fast(array, index, n) \
+        cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, n, true)
+
 /**
  * Deallocates an array.
  *
@@ -601,8 +910,8 @@
  * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array
  * @param array a pointer to the array structure
  */
-cx_attr_nonnull
-CX_EXPORT void cx_array_free_(const CxAllocator *allocator, CxArray *array);
+CX_EXTERN CX_NONNULL
+void cx_array_free_(const CxAllocator *allocator, CxArray *array);
 
 /**
  * Deallocates an array.
@@ -651,8 +960,8 @@
  * @see cx_array_binary_search_sup()
  * @see cx_array_binary_search()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search_inf(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search_inf(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func cmp_func);
 
 /**
@@ -674,8 +983,8 @@
  * @see cx_array_binary_search_inf()
  * @see cx_array_binary_search_sup()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func cmp_func);
 
 /**
@@ -703,8 +1012,8 @@
  * @see cx_array_binary_search_inf()
  * @see cx_array_binary_search()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search_sup(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func cmp_func);
 
 
@@ -734,8 +1043,8 @@
  * @see cx_array_binary_search_sup()
  * @see cx_array_binary_search()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search_inf_c(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search_inf_c(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
 
 /**
@@ -758,8 +1067,8 @@
  * @see cx_array_binary_search_inf()
  * @see cx_array_binary_search_sup()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search_c(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search_c(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
 
 /**
@@ -788,8 +1097,8 @@
  * @see cx_array_binary_search_inf()
  * @see cx_array_binary_search()
  */
-cx_attr_nonnull
-CX_EXPORT size_t cx_array_binary_search_sup_c(const void *arr, size_t size,
+CX_EXTERN CX_NONNULL
+size_t cx_array_binary_search_sup_c(const void *arr, size_t size,
         size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
 
 /**
@@ -800,8 +1109,8 @@
  * @param idx1 index of the first element
  * @param idx2 index of the second element
  */
-cx_attr_nonnull
-CX_EXPORT void cx_array_swap(void *arr, size_t elem_size, size_t idx1, size_t idx2);
+CX_EXTERN CX_NONNULL
+void cx_array_swap(void *arr, size_t elem_size, size_t idx1, size_t idx2);
 
 /**
  * Allocates an array list for storing elements with @p elem_size bytes each.
@@ -816,14 +1125,8 @@
  * @param initial_capacity the initial number of elements the array can store
  * @return the created list
  */
-cx_attr_nodiscard
-cx_attr_malloc
-cx_attr_dealloc(cxListFree, 1)
-CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator,
+CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxListFree, 1)
+CxList *cxArrayListCreate(const CxAllocator *allocator,
         size_t elem_size, size_t initial_capacity);
 
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
 #endif // UCX_ARRAY_LIST_H

mercurial