ucx/cx/array_list.h

changeset 31
287484519844
parent 23
b26390e77237
equal deleted inserted replaced
30:d33eaaec15da 31:287484519844
48 * a stack buffer when swapped. 48 * a stack buffer when swapped.
49 */ 49 */
50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size; 50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size;
51 51
52 /** 52 /**
53 * Declares variables for an array that can be used with the convenience macros. 53 * Declares a typed array with size and capacity.
54 * 54 *
55 * @par Examples 55 * @param type the type of the elements
56 * @code
57 * // integer array with at most 255 elements
58 * CX_ARRAY_DECLARE_SIZED(int, myarray, uint8_t)
59 *
60 * // array of MyObject* pointers where size and capacity are stored as unsigned int
61 * CX_ARRAY_DECLARE_SIZED(MyObject*, objects, unsigned int)
62 *
63 * // initializing code
64 * cx_array_initialize(myarray, 16); // reserve space for 16
65 * cx_array_initialize(objects, 100); // reserve space for 100
66 * @endcode
67 *
68 * @param type the type of the data
69 * @param name the name of the array 56 * @param name the name of the array
70 * @param size_type the type of the size (should be uint8_t, uint16_t, uint32_t, or size_t) 57 */
71 * 58 #define CX_ARRAY(type, name) \
72 * @see cx_array_initialize() 59 struct { \
73 * @see cx_array_simple_add() 60 type *data; \
74 * @see cx_array_simple_copy() 61 size_t size; \
75 * @see cx_array_simple_add_sorted() 62 size_t capacity; \
76 * @see cx_array_simple_insert_sorted() 63 } name
77 */ 64
78 #define CX_ARRAY_DECLARE_SIZED(type, name, size_type) \ 65 /**
79 type * name; \ 66 * Internal structure for arrays.
80 /** Array size. */ size_type name##_size; \ 67 *
81 /** Array capacity. */ size_type name##_capacity 68 * A generalization of array structures declared with CX_ARRAY().
82 69 */
83 /** 70 typedef struct cx_array_s {
84 * Declares variables for an array that can be used with the convenience macros. 71 /** The array data. */
85 * 72 void *data;
86 * The size and capacity variables will have type @c size_t. 73 /** The number of elements. */
87 * Use #CX_ARRAY_DECLARE_SIZED() to specify a different type. 74 size_t size;
88 * 75 /** The maximum number of elements. */
89 * @par Examples 76 size_t capacity;
90 * @code 77 } CxArray;
91 * // int array 78
92 * CX_ARRAY_DECLARE(int, myarray) 79 /**
93 * 80 * Initializes an array by allocating memory.
94 * // initializing code 81 *
95 * cx_array_initialize(myarray, 32); // reserve space for 32 82 * Internal function - do not use manually.
96 * @endcode 83 *
97 * 84 * @param allocator the allocator for the array
98 * @param type the type of the data 85 * @param array a pointer to the array structure
99 * @param name the name of the array 86 * @param elem_size size of one element
100 * 87 * @param capacity the initial maximum number of elements
101 * @see cx_array_initialize() 88 * @retval zero allocation was successful
102 * @see cx_array_simple_add() 89 * @retval non-zero allocation failed
103 * @see cx_array_simple_copy() 90 */
104 * @see cx_array_simple_add_sorted() 91 cx_attr_nonnull
105 * @see cx_array_simple_insert_sorted() 92 CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
106 */ 93
107 #define CX_ARRAY_DECLARE(type, name) CX_ARRAY_DECLARE_SIZED(type, name, size_t) 94 /**
108 95 * Initializes an array by allocating memory.
109 /** 96 *
110 * Initializes an array with the given capacity. 97 * The size is set to zero.
111 * 98 *
112 * The type of the capacity depends on the type used during declaration. 99 * @attention If the array was already initialized, this will leak memory.
113 * 100 * Use cx_array_reserve() to change the capacity of an initialized array.
114 * @par Examples 101 *
115 * @code 102 * @param allocator (@c CxAllocator*) the allocator for the array
116 * CX_ARRAY_DECLARE_SIZED(int, arr1, uint8_t) 103 * @param array the name of the array
117 * CX_ARRAY_DECLARE(int, arr2) // size and capacity are implicitly size_t 104 * @param capacity (@c size_t) the initial maximum number of elements
118 * 105 * @retval zero allocation was successful
119 * // initializing code 106 * @retval non-zero allocation failed
120 * cx_array_initialize(arr1, 500); // error: maximum for uint8_t is 255 107 */
121 * cx_array_initialize(arr2, 500); // OK 108 #define cx_array_init_a(allocator, array, capacity) cx_array_init_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
122 * @endcode 109
123 * 110 /**
124 * 111 * Initializes an array by allocating memory.
125 * The memory for the array is allocated with the cxDefaultAllocator. 112 *
126 * 113 * The size is set to zero.
127 * @param array the name of the array 114 *
128 * @param capacity the initial capacity 115 * @attention If the array was already initialized, this will leak memory.
129 * @see cx_array_initialize_a() 116 *
130 * @see CX_ARRAY_DECLARE_SIZED() 117 * @param array the name of the array
131 * @see CX_ARRAY_DECLARE() 118 * @param capacity (@c size_t) the initial maximum number of elements
132 */ 119 * @retval zero allocation was successful
133 #define cx_array_initialize(array, capacity) \ 120 * @retval non-zero allocation failed
134 array##_capacity = capacity; \ 121 */
135 array##_size = 0; \ 122 #define cx_array_init(array, capacity) cx_array_init_a(cxDefaultAllocator, array, capacity)
136 array = cxMallocDefault(sizeof(array[0]) * capacity) 123
137 124 /**
138 /** 125 * Initializes an array with fixed size memory.
139 * Initializes an array with the given capacity using the specified allocator. 126 *
140 * 127 * Internal function - do not use manually.
141 * @par Example 128 *
142 * @code 129 * @param array a pointer to the array structure
143 * CX_ARRAY_DECLARE(int, myarray) 130 * @param data the fixed size array
144 * 131 * @param capacity the capacity of the fixed size array
145 * 132 * @param size the number of initialized elements in the fixed size array
146 * const CxAllocator *al = // ... 133 */
147 * cx_array_initialize_a(al, myarray, 128); 134 cx_attr_nonnull
148 * // ... 135 CX_EXPORT void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size);
149 * cxFree(al, myarray); // remember to free with the same allocator 136
150 * @endcode 137 /**
151 * 138 * Initializes an array with fixed size memory.
152 * @param allocator (@c CxAllocator*) the allocator 139 *
153 * @param array the name of the array 140 * This is useful, for example, when you want to work with memory on the stack
154 * @param capacity the initial capacity 141 * and only want to move to the heap when the stack memory is not enough.
155 * @see cx_array_initialize() 142 *
156 * @see CX_ARRAY_DECLARE_SIZED() 143 * With the @p num_initialized argument you can specify how many elements in the
157 * @see CX_ARRAY_DECLARE() 144 * fixed size array are already correctly initialized, which determines the
158 */ 145 * initial size of the array.
159 #define cx_array_initialize_a(allocator, array, capacity) \ 146 *
160 array##_capacity = capacity; \ 147 * The capacity is determined automatically by the compiler.
161 array##_size = 0; \ 148 *
162 array = cxMalloc(allocator, sizeof(array[0]) * capacity) 149 * @attention When you add elements to an array that was initialized with fixed
163 150 * size memory, you MUST check the capacity before adding the element and invoke
164 /** 151 * cx_array_copy_to_new() when you intend to exceed the capacity.
165 * Defines a reallocation mechanism for arrays. 152 *
166 * You can create your own, use cx_array_reallocator(), or 153 * @attention When you pass a pointer to an array that does not have a fixed
167 * use the #cx_array_default_reallocator. 154 * size, the behavior is unspecified.
168 */ 155 *
169 struct cx_array_reallocator_s { 156 * @param array the name of the array to initialize
170 /** 157 * @param fixed_size_array (@c void*) the fixed size array
171 * Reallocates space for the given array. 158 * @param num_initialized (@c size_t) the number of already initialized elements in the fixed size array
172 * 159 * @see cx_array_copy_to_new()
173 * Implementations are not required to free the original array. 160 */
174 * This allows reallocation of static or stack memory by allocating heap memory 161 #define cx_array_init_fixed(array, fixed_size_array, num_initialized) \
175 * and copying the array contents; namely when @c stack_ptr in this struct 162 cx_array_init_fixed_((CxArray*)&(array), fixed_size_array, cx_nmemb(fixed_size_array), num_initialized)
176 * is not @c NULL and @p array equals @c stack_ptr. 163
177 * 164 /**
178 * @param array the array to reallocate 165 * Changes the capacity of an array.
179 * @param old_capacity the old number of elements 166 *
180 * @param new_capacity the new number of elements 167 * Internal function - do not use.
181 * @param elem_size the size of each element 168 *
182 * @param alloc a reference to this allocator 169 * @param allocator the allocator
183 * @return a pointer to the reallocated memory or @c NULL on failure 170 * @param array a pointer to the array structure
184 */ 171 * @param elem_size the size of one element
185 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity, 172 * @param capacity the new capacity
186 size_t elem_size, struct cx_array_reallocator_s *alloc); 173 * @retval zero allocation was successful
187 174 * @retval non-zero allocation failed
188 /** 175 */
189 * The allocator that shall be used for the reallocations. 176 cx_attr_nonnull
190 */ 177 CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
191 const CxAllocator *allocator; 178
192 /** 179 /**
193 * Optional pointer to stack memory 180 * Changes the capacity of an array.
194 * if the array is originally located on the stack. 181 *
195 */ 182 * If required, the size is reduced to fit into the new capacity.
196 const void *stack_ptr; 183 *
197 }; 184 * @param allocator (@c CxAllocator*) the allocator for the array
198 185 * @param array the name of the array
199 /** 186 * @param capacity (@c size_t) the new maximum number of elements
200 * Typedef for the array reallocator struct. 187 * @retval zero allocation was successful
201 */ 188 * @retval non-zero allocation failed
202 typedef struct cx_array_reallocator_s CxArrayReallocator; 189 */
203 190 #define cx_array_reserve_a(allocator, array, capacity) \
204 /** 191 cx_array_reserve_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
205 * A default array reallocator that is based on the cxDefaultAllocator. 192
206 */ 193 /**
207 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator; 194 * Changes the capacity of an array.
208 195 *
209 /** 196 * If required, the size is reduced to fit into the new capacity.
210 * Creates a new array reallocator. 197 *
211 * 198 * @param array the name of the array
212 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. 199 * @param capacity (@c size_t) the new maximum number of elements
213 * 200 * @retval zero allocation was successful
214 * When @p stack_ptr is not @c NULL, the reallocator is supposed to be used 201 * @retval non-zero allocation failed
215 * @em only for the specific array initially located at @p stack_ptr. 202 */
216 * When reallocation is needed, the reallocator checks if the array is 203 #define cx_array_reserve(array, capacity) \
217 * still located at @p stack_ptr and copies the contents to the heap. 204 cx_array_reserve_a(cxDefaultAllocator, array, capacity)
218 * 205
219 * @note Invoking this function with both arguments being @c NULL will return a 206 /**
220 * reallocator that behaves like #cx_array_default_reallocator. 207 * Copies the array to a new memory region.
221 * 208 *
222 * @param allocator the allocator this reallocator shall be based on 209 * Internal function - do not use.
223 * @param stack_ptr the address of the array when the array is initially located 210 *
224 * on the stack or shall not reallocate in place 211 * @param allocator the allocator for new new memory
225 * @return an array reallocator 212 * @param array a pointer to the array structure
226 */ 213 * @param elem_size the size of one element
227 CX_EXPORT CxArrayReallocator cx_array_reallocator( 214 * @param capacity the new capacity
228 const struct cx_allocator_s *allocator, const void *stack_ptr); 215 * @retval zero allocation was successful
229 216 * @retval non-zero allocation failed
230 /** 217 */
231 * Reserves memory for additional elements. 218 cx_attr_nonnull
232 * 219 CX_EXPORT int cx_array_copy_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
233 * This function checks if the @p capacity of the array is sufficient to hold 220
234 * at least @p size plus @p elem_count elements. If not, a reallocation is 221 /**
235 * performed with the specified @p reallocator. 222 * Copies the array to a new memory region.
236 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 223 *
237 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 224 * This is useful when you have initialized the array with a fixed size memory
238 * 225 * using cx_array_init_fixed(), and now you want to increase the capacity.
239 * This function can be useful to replace subsequent calls to cx_array_copy() 226 *
240 * with one single cx_array_reserve() and then - after guaranteeing a 227 * @attention When the original memory does not belong to stack memory, and
241 * sufficient capacity - use simple memmove() or memcpy(). 228 * you do not have another reference to this memory, it will leak.
242 * 229 *
243 * The @p width in bytes refers to the size and capacity. 230 * @param allocator (@c CxAllocator*) the allocator for the new memory
244 * Both must have the same width. 231 * @param array the name of the array
245 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit 232 * @param capacity (@c size_t) the new maximum number of elements
246 * architecture. If set to zero, the native word width is used. 233 * @retval zero allocation was successful
247 * 234 * @retval non-zero allocation failed
248 * @note This function will reserve the minimum required capacity to hold 235 * @see cx_array_init_fixed()
249 * the additional elements and does not perform an overallocation. 236 */
250 * 237 #define cx_array_copy_to_new_a(allocator, array, capacity) \
251 * @param array a pointer to the target array 238 cx_array_copy_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
252 * @param size a pointer to the size of the array 239
253 * @param capacity a pointer to the capacity of the array 240 /**
254 * @param width the width in bytes for the @p size and @p capacity or zero for default 241 * Copies the array to a new memory region.
255 * @param elem_size the size of one element 242 *
256 * @param elem_count the number of expected additional elements 243 * This is useful when you have initialized the array with a fixed size memory
257 * @param reallocator the array reallocator to use 244 * using cx_array_init_fixed(), and now you want to increase the capacity.
258 * (@c NULL defaults to #cx_array_default_reallocator) 245 *
259 * @retval zero success 246 * @attention When the original memory does not belong to stack memory, and
260 * @retval non-zero failure 247 * you do not have another reference to this memory, it will leak.
261 * @see cx_array_reallocator() 248 *
262 */ 249 * @param array the name of the array
263 cx_attr_nonnull_arg(1, 2, 3) 250 * @param capacity (@c size_t) the new maximum number of elements
264 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, 251 * @retval zero allocation was successful
265 unsigned width, size_t elem_size, size_t elem_count, 252 * @retval non-zero allocation failed
266 CxArrayReallocator *reallocator); 253 * @see cx_array_init_fixed()
267 254 */
268 /** 255 #define cx_array_copy_to_new(array, capacity) \
269 * Copies elements from one array to another. 256 cx_array_copy_to_new_a(cxDefaultAllocator, array, capacity)
270 * 257
271 * The elements are copied to the @p target array at the specified @p index, 258 /**
272 * overwriting possible elements. The @p index does not need to be in range of 259 * Inserts data into an array.
273 * the current array @p size. If the new index plus the number of elements added 260 *
274 * extends the array's size, the remaining @p capacity is used. 261 * Internal function - do not use.
275 * 262 *
276 * If the @p capacity is also insufficient to hold the new data, a reallocation 263 * @param allocator the allocator to use for a possible reallocation
277 * attempt is made with the specified @p reallocator. 264 * @param array a pointer to the array structure
278 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 265 * @param elem_size the size of one element
279 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 266 * @param index the index where to insert the @p other data
280 * 267 * @param other a pointer to an array of data that shall be inserted
281 * The @p width in bytes refers to the size and capacity. 268 * @param n the number of elements that shall be inserted
282 * Both must have the same width. 269 * @retval zero success
283 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit 270 * @retval non-zero a re-allocation was necessary but failed
284 * architecture. If set to zero, the native word width is used. 271 */
285 * 272 cx_attr_nonnull_arg(1, 2)
286 * @note When this function does reallocate the array, it may allocate more 273 CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
287 * space than required to avoid further allocations in the near future. 274 size_t elem_size, size_t index, const void *other, size_t n);
288 * 275
289 * @param target a pointer to the target array 276 /**
290 * @param size a pointer to the size of the target array 277 * Appends an element to an array.
291 * @param capacity a pointer to the capacity of the target array 278 *
292 * @param width the width in bytes for the @p size and @p capacity or zero for default 279 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
293 * @param index the index where the copied elements shall be placed 280 *
294 * @param src the source array 281 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
295 * @param elem_size the size of one element 282 * @param array the name of the array where the element shall be added
296 * @param elem_count the number of elements to copy 283 * @param element the element that shall be added
297 * @param reallocator the array reallocator to use 284 * @retval zero success
298 * (@c NULL defaults to #cx_array_default_reallocator) 285 * @retval non-zero a re-allocation was necessary but failed
299 * @retval zero success 286 */
300 * @retval non-zero failure 287 #define cx_array_add_a(allocator, array, element) \
301 * @see cx_array_reallocator() 288 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, (void*)&(element), 1)
302 * @see cx_array_reserve() 289
303 */ 290 /**
304 cx_attr_nonnull_arg(1, 2, 3, 6) 291 * Appends an element to an array.
305 CX_EXPORT int cx_array_copy(void **target, void *size, void *capacity, unsigned width, 292 *
306 size_t index, const void *src, size_t elem_size, size_t elem_count, 293 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
307 CxArrayReallocator *reallocator); 294 *
308 295 * @param array the name of the array where the element shall be added
309 /** 296 * @param element (@c void*) a pointer to the element that shall be added
310 * Convenience macro that uses cx_array_copy() with a default layout and 297 * @retval zero success
311 * the specified reallocator. 298 * @retval non-zero a re-allocation was necessary but failed
312 * 299 */
313 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 300 #define cx_array_add(array, element) \
314 * @param array the name of the array (NOT a pointer or alias to the array) 301 cx_array_add_a(cxDefaultAllocator, array, element)
315 * @param index (@c size_t) the index where the copied elements shall be placed 302
316 * @param src (@c void*) the source array 303 /**
317 * @param count (@c size_t) the number of elements to copy 304 * Inserts an element into an array.
318 * @retval zero success 305 *
319 * @retval non-zero failure 306 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
320 * @see CX_ARRAY_DECLARE() 307 *
321 * @see cx_array_simple_copy() 308 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
322 */ 309 * @param array the name of the array where the element shall be inserted
323 #define cx_array_simple_copy_a(reallocator, array, index, src, count) \ 310 * @param index (@c size_t) the index where to insert the @p element
324 cx_array_copy((void**)&(array), &(array##_size), &(array##_capacity), \ 311 * @param element the element that shall be inserted
325 sizeof(array##_size), index, src, sizeof((array)[0]), count, \ 312 * @retval zero success
326 reallocator) 313 * @retval non-zero a re-allocation was necessary but failed
327 314 */
328 /** 315 #define cx_array_insert_a(allocator, array, index, element) \
329 * Convenience macro that uses cx_array_copy() with a default layout and 316 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, (void*)&(element), 1)
330 * the default reallocator. 317
331 * 318 /**
332 * @param array the name of the array (NOT a pointer or alias to the array) 319 * Inserts an element into an array.
333 * @param index (@c size_t) the index where the copied elements shall be placed 320 *
334 * @param src (@c void*) the source array 321 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
335 * @param count (@c size_t) the number of elements to copy 322 *
336 * @retval zero success 323 * @param array the name of the array where the element shall be inserted
337 * @retval non-zero failure 324 * @param index (@c size_t) the index where to insert the @p element
338 * @see CX_ARRAY_DECLARE() 325 * @param element (@c void*) a pointer to the element that shall be inserted
339 * @see cx_array_simple_copy_a() 326 * @retval zero success
340 */ 327 * @retval non-zero a re-allocation was necessary but failed
341 #define cx_array_simple_copy(array, index, src, count) \ 328 */
342 cx_array_simple_copy_a(NULL, array, index, src, count) 329 #define cx_array_insert(array, index, element) \
343 330 cx_array_insert_a(cxDefaultAllocator, array, index, element)
344 /** 331
345 * Convenience macro that uses cx_array_reserve() with a default layout and 332 /**
346 * the specified reallocator. 333 * Inserts data into an array.
347 * 334 *
348 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 335 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
349 * @param array the name of the array (NOT a pointer or alias to the array) 336 *
350 * @param count (@c size_t) the number of expected @em additional elements 337 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
351 * @retval zero success 338 * @param array the name of the array where the elements shall be inserted
352 * @retval non-zero failure 339 * @param index (@c size_t) the index where to insert the @p other data
353 * @see CX_ARRAY_DECLARE() 340 * @param other (@c void*) a pointer to an array of data that shall be inserted
354 * @see cx_array_simple_reserve() 341 * @param n (@c size_t) the number of elements that shall be inserted
355 */ 342 * @retval zero success
356 #define cx_array_simple_reserve_a(reallocator, array, count) \ 343 * @retval non-zero a re-allocation was necessary but failed
357 cx_array_reserve((void**)&(array), &(array##_size), &(array##_capacity), \ 344 */
358 sizeof(array##_size), sizeof((array)[0]), count, \ 345 #define cx_array_insert_array_a(allocator, array, index, other, n) \
359 reallocator) 346 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n)
360 347
361 /** 348 /**
362 * Convenience macro that uses cx_array_reserve() with a default layout and 349 * Inserts data into an array.
363 * the default reallocator. 350 *
364 * 351 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
365 * @param array the name of the array (NOT a pointer or alias to the array) 352 *
366 * @param count (@c size_t) the number of expected additional elements 353 * @param array the name of the array where the elements shall be inserted
367 * @retval zero success 354 * @param index (@c size_t) the index where to insert the @p other data
368 * @retval non-zero failure 355 * @param other (@c void*) a pointer to an array of data that shall be inserted
369 * @see CX_ARRAY_DECLARE() 356 * @param n (@c size_t) the number of elements that shall be inserted
370 * @see cx_array_simple_reserve_a() 357 * @retval zero success
371 */ 358 * @retval non-zero a re-allocation was necessary but failed
372 #define cx_array_simple_reserve(array, count) \ 359 */
373 cx_array_simple_reserve_a(NULL, array, count) 360 #define cx_array_insert_array(array, index, other, n) \
374 361 cx_array_insert_array_a(cxDefaultAllocator, array, index, other, n)
375 /** 362
376 * Adds an element to an array with the possibility of allocating more space. 363 /**
377 * 364 * Appends data to an array.
378 * The element @p elem is added to the end of the @p target array which contains 365 *
379 * @p size elements, already. The @p capacity must point to a variable denoting 366 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
380 * the current maximum number of elements the array can hold. 367 *
381 * 368 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
382 * If the capacity is insufficient to hold the new element, an attempt to 369 * @param array the name of the array where the elements shall be added
383 * increase the @p capacity is made and the new capacity is written back. 370 * @param other (@c void*) a pointer to an array of data that shall be added
384 * 371 * @param n (@c size_t) the number of elements that shall be added
385 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 372 * @retval zero success
386 * It is important, however, that @p size and @p capacity are pointers to 373 * @retval non-zero a re-allocation was necessary but failed
387 * variables of the same type. 374 */
388 * 375 #define cx_array_add_array_a(allocator, array, other, n) \
389 * @param target (@c void**) a pointer to the target array 376 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n)
390 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 377
391 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 378 /**
392 * @param elem_size (@c size_t) the size of one element 379 * Appends data to an array.
393 * @param elem (@c void*) a pointer to the element to add 380 *
394 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 381 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
395 * @retval zero success 382 *
396 * @retval non-zero failure 383 * @param array the name of the array where the elements shall be added
397 */ 384 * @param other (@c void*) a pointer to an array of data that shall be added
398 #define cx_array_add(target, size, capacity, elem_size, elem, reallocator) \ 385 * @param n (@c size_t) the number of elements that shall be added
399 cx_array_copy((void**)(target), size, capacity, sizeof(*(size)), \ 386 * @retval zero success
400 *(size), elem, elem_size, 1, reallocator) 387 * @retval non-zero a re-allocation was necessary but failed
401 388 */
402 /** 389 #define cx_array_add_array(array, other, n) \
403 * Convenience macro that uses cx_array_add() with a default layout and 390 cx_array_add_array_a(cxDefaultAllocator, array, other, n)
404 * the specified reallocator. 391
405 * 392 /**
406 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 393 * Inserts sorted data into a sorted array.
407 * @param array the name of the array (NOT a pointer or alias to the array) 394 *
408 * @param elem the element to add (NOT a pointer, address is automatically taken) 395 * Internal function - do not use.
409 * @retval zero success 396 *
410 * @retval non-zero failure 397 * @param allocator the allocator to use for a possible reallocation
411 * @see CX_ARRAY_DECLARE() 398 * @param array a pointer to the array structure
412 * @see cx_array_simple_add() 399 * @param elem_size the size of one element
413 */ 400 * @param sorted_data a pointer to an array of data that shall be inserted
414 #define cx_array_simple_add_a(reallocator, array, elem) \ 401 * @param n the number of elements that shall be inserted
415 cx_array_simple_copy_a(reallocator, array, array##_size, &(elem), 1) 402 * @param cmp_func the compare function
416 403 * @param allow_duplicates @c false if duplicates shall be skipped during insertion
417 /** 404 * @retval zero success
418 * Convenience macro that uses cx_array_add() with a default layout and 405 * @retval non-zero a re-allocation was necessary but failed
419 * the default reallocator. 406 */
420 * 407 cx_attr_nonnull
421 * @param array the name of the array (NOT a pointer or alias to the array) 408 CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
422 * @param elem the element to add (NOT a pointer, address is automatically taken) 409 size_t elem_size, const void *sorted_data, size_t n,
423 * @retval zero success 410 cx_compare_func cmp_func, bool allow_duplicates);
424 * @retval non-zero failure
425 * @see CX_ARRAY_DECLARE()
426 * @see cx_array_simple_add_a()
427 */
428 #define cx_array_simple_add(array, elem) \
429 cx_array_simple_add_a(cx_array_default_reallocator, array, elem)
430
431 /**
432 * Inserts a sorted array into another sorted array.
433 *
434 * If either the target or the source array is not already sorted with respect
435 * to the specified @p cmp_func, the behavior is undefined.
436 *
437 * If the capacity is insufficient to hold the new data, a reallocation
438 * attempt is made.
439 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
440 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
441 *
442 * @param target a pointer to the target array
443 * @param size a pointer to the size of the target array
444 * @param capacity a pointer to the capacity of the target array
445 * @param cmp_func the compare function for the elements
446 * @param src the source array
447 * @param elem_size the size of one element
448 * @param elem_count the number of elements to insert
449 * @param reallocator the array reallocator to use
450 * (@c NULL defaults to #cx_array_default_reallocator)
451 * @retval zero success
452 * @retval non-zero failure
453 */
454 cx_attr_nonnull_arg(1, 2, 3, 5)
455 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity,
456 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count,
457 CxArrayReallocator *reallocator);
458 411
459 /** 412 /**
460 * Inserts an element into a sorted array. 413 * Inserts an element into a sorted array.
461 * 414 *
462 * If the target array is not already sorted with respect 415 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
463 * to the specified @p cmp_func, the behavior is undefined. 416 *
464 * 417 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
465 * If the capacity is not enough to hold the new data, a reallocation 418 *
466 * attempt is made. 419 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
467 * 420 * @param array the name of the array where the elements shall be inserted
468 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 421 * @param element the element that shall be inserted
469 * It is important, however, that @p size and @p capacity are pointers to 422 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
470 * variables of the same type. 423 * @retval zero success
471 * 424 * @retval non-zero a re-allocation was necessary but failed
472 * @param target (@c void**) a pointer to the target array 425 */
473 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 426 #define cx_array_insert_sorted_a(allocator, array, element, cmp_func) \
474 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 427 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, true)
475 * @param elem_size (@c size_t) the size of one element 428
476 * @param elem (@c void*) a pointer to the element to add 429 /**
477 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 430 * Inserts an element into a sorted array.
478 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 431 *
479 * @retval zero success 432 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
480 * @retval non-zero failure 433 *
481 */ 434 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
482 #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ 435 *
483 cx_array_insert_sorted((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) 436 * @param array the name of the array where the elements shall be inserted
484 437 * @param element the element that shall be inserted
485 /** 438 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
486 * Convenience macro for cx_array_add_sorted() with a default 439 * @retval zero success
487 * layout and the specified reallocator. 440 * @retval non-zero a re-allocation was necessary but failed
488 * 441 */
489 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 442 #define cx_array_insert_sorted(array, element, cmp_func) \
490 * @param array the name of the array (NOT a pointer or alias to the array) 443 cx_array_insert_sorted_a(cxDefaultAllocator, array, element, cmp_func)
491 * @param elem the element to add (NOT a pointer, address is automatically taken) 444
492 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 445 /**
493 * @retval zero success 446 * Inserts sorted data into a sorted array.
494 * @retval non-zero failure 447 *
495 * @see CX_ARRAY_DECLARE() 448 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
496 * @see cx_array_simple_add_sorted() 449 *
497 */ 450 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
498 #define cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) \ 451 *
499 cx_array_add_sorted(&array, &(array##_size), &(array##_capacity), \ 452 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
500 sizeof((array)[0]), &(elem), cmp_func, reallocator) 453 * @param array the name of the array where the elements shall be inserted
501 454 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
502 /** 455 * @param n (@c size_t) the number of elements that shall be inserted
503 * Convenience macro for cx_array_add_sorted() with a default 456 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
504 * layout and the default reallocator. 457 * @retval zero success
505 * 458 * @retval non-zero a re-allocation was necessary but failed
506 * @param array the name of the array (NOT a pointer or alias to the array) 459 */
507 * @param elem the element to add (NOT a pointer, address is automatically taken) 460 #define cx_array_insert_sorted_array_a(allocator, array, sorted_data, n, cmp_func) \
508 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 461 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, true)
509 * @retval zero success 462
510 * @retval non-zero failure 463 /**
511 * @see CX_ARRAY_DECLARE() 464 * Inserts sorted data into a sorted array.
512 * @see cx_array_simple_add_sorted_a() 465 *
513 */ 466 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
514 #define cx_array_simple_add_sorted(array, elem, cmp_func) \ 467 *
515 cx_array_simple_add_sorted_a(NULL, array, elem, cmp_func) 468 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
516 469 *
517 /** 470 * @param array the name of the array where the elements shall be inserted
518 * Convenience macro for cx_array_insert_sorted() with a default 471 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
519 * layout and the specified reallocator. 472 * @param n (@c size_t) the number of elements that shall be inserted
520 * 473 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
521 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 474 * @retval zero success
522 * @param array the name of the array (NOT a pointer or alias to the array) 475 * @retval non-zero a re-allocation was necessary but failed
523 * @param src (@c void*) pointer to the source array 476 */
524 * @param n (@c size_t) number of elements in the source array 477 #define cx_array_insert_sorted_array(array, sorted_data, n, cmp_func) \
525 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 478 cx_array_insert_sorted_array_a(cxDefaultAllocator, array, sorted_data, n, cmp_func)
526 * @retval zero success 479
527 * @retval non-zero failure 480 /**
528 * @see CX_ARRAY_DECLARE() 481 * Inserts an element into a sorted array if it is not already contained.
529 * @see cx_array_simple_insert_sorted() 482 *
530 */ 483 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
531 #define cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) \ 484 *
532 cx_array_insert_sorted((void**)(&array), &(array##_size), &(array##_capacity), \ 485 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
533 cmp_func, src, sizeof((array)[0]), n, reallocator) 486 *
534 487 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
535 /** 488 * @param array the name of the array where the elements shall be inserted
536 * Convenience macro for cx_array_insert_sorted() with a default 489 * @param element the element that shall be inserted
537 * layout and the default reallocator. 490 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
538 * 491 * @retval zero success
539 * @param array the name of the array (NOT a pointer or alias to the array) 492 * @retval non-zero a re-allocation was necessary but failed
540 * @param src (@c void*) pointer to the source array 493 */
541 * @param n (@c size_t) number of elements in the source array 494 #define cx_array_insert_unique_a(allocator, array, element, cmp_func) \
542 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 495 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, false)
543 * @retval zero success 496
544 * @retval non-zero failure 497 /**
545 * @see CX_ARRAY_DECLARE() 498 * Inserts an element into a sorted array if it is not already contained.
546 * @see cx_array_simple_insert_sorted_a() 499 *
547 */ 500 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
548 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ 501 *
549 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func) 502 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
550 503 *
551 504 * @param array the name of the array where the elements shall be inserted
552 /** 505 * @param element the element that shall be inserted
553 * Inserts a sorted array into another sorted array, avoiding duplicates. 506 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
554 * 507 * @retval zero success
555 * If either the target or the source array is not already sorted with respect 508 * @retval non-zero a re-allocation was necessary but failed
556 * to the specified @p cmp_func, the behavior is undefined. 509 */
557 * 510 #define cx_array_insert_unique(array, element, cmp_func) \
558 * If the capacity is insufficient to hold the new data, a reallocation 511 cx_array_insert_unique_a(cxDefaultAllocator, array, element, cmp_func)
559 * attempt is made. 512
560 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 513 /**
561 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 514 * Inserts sorted data into a sorted array, skipping duplicates.
562 * 515 *
563 * @param target a pointer to the target array 516 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
564 * @param size a pointer to the size of the target array 517 *
565 * @param capacity a pointer to the capacity of the target array 518 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
566 * @param cmp_func the compare function for the elements 519 *
567 * @param src the source array 520 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
568 * @param elem_size the size of one element 521 * @param array the name of the array where the elements shall be inserted
569 * @param elem_count the number of elements to insert 522 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
570 * @param reallocator the array reallocator to use 523 * @param n (@c size_t) the number of elements that shall be inserted
571 * (@c NULL defaults to #cx_array_default_reallocator) 524 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
572 * @retval zero success 525 * @retval zero success
573 * @retval non-zero failure 526 * @retval non-zero a re-allocation was necessary but failed
574 */ 527 */
575 cx_attr_nonnull_arg(1, 2, 3, 5) 528 #define cx_array_insert_unique_array_a(allocator, array, sorted_data, n, cmp_func) \
576 CX_EXPORT int cx_array_insert_unique(void **target, size_t *size, size_t *capacity, 529 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, false)
577 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, 530
578 CxArrayReallocator *reallocator); 531 /**
579 532 * Inserts sorted data into a sorted array, skipping duplicates.
580 /** 533 *
581 * Inserts an element into a sorted array if it does not exist. 534 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
582 * 535 *
583 * If the target array is not already sorted with respect 536 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
584 * to the specified @p cmp_func, the behavior is undefined. 537 *
585 * 538 * @param array the name of the array where the elements shall be inserted
586 * If the capacity is insufficient to hold the new data, a reallocation 539 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
587 * attempt is made. 540 * @param n (@c size_t) the number of elements that shall be inserted
588 * 541 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
589 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 542 * @retval zero success
590 * It is important, however, that @p size and @p capacity are pointers to 543 * @retval non-zero a re-allocation was necessary but failed
591 * variables of the same type. 544 */
592 * 545 #define cx_array_insert_unique_array(array, sorted_data, n, cmp_func) \
593 * @param target (@c void**) a pointer to the target array 546 cx_array_insert_unique_array_a(cxDefaultAllocator, array, sorted_data, n, cmp_func)
594 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 547
595 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 548 /**
596 * @param elem_size (@c size_t) the size of one element 549 * Inserts sorted data into a sorted array.
597 * @param elem (@c void*) a pointer to the element to add 550 *
598 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 551 * Internal function - do not use.
599 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 552 *
600 * @retval zero success (also when the element was already present) 553 * @param allocator the allocator to use for a possible reallocation
601 * @retval non-zero failure 554 * @param array a pointer to the array structure
602 */ 555 * @param elem_size the size of one element
603 #define cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ 556 * @param sorted_data a pointer to an array of data that shall be inserted
604 cx_array_insert_unique((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) 557 * @param n the number of elements that shall be inserted
605 558 * @param cmp_func the compare function
606 /** 559 * @param context additional context for the compare function
607 * Convenience macro for cx_array_add_unique() with a default 560 * @param allow_duplicates @c false if duplicates shall be skipped during insertion
608 * layout and the specified reallocator. 561 * @retval zero success
609 * 562 * @retval non-zero a re-allocation was necessary but failed
610 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 563 */
611 * @param array the name of the array (NOT a pointer or alias to the array) 564 cx_attr_nonnull_arg(1, 2, 4, 6)
612 * @param elem the element to add (NOT a pointer, address is automatically taken) 565 CX_EXPORT int cx_array_insert_sorted_c_(const CxAllocator *allocator, CxArray *array,
613 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 566 size_t elem_size, const void *sorted_data, size_t n,
614 * @retval zero success 567 cx_compare_func2 cmp_func, void *context, bool allow_duplicates);
615 * @retval non-zero failure 568
616 * @see CX_ARRAY_DECLARE() 569 /**
617 * @see cx_array_simple_add_unique() 570 * Inserts an element into a sorted array.
618 */ 571 *
619 #define cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) \ 572 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
620 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \ 573 *
621 sizeof((array)[0]), &(elem), cmp_func, reallocator) 574 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
622 575 *
623 /** 576 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
624 * Convenience macro for cx_array_add_unique() with a default 577 * @param array the name of the array where the elements shall be inserted
625 * layout and the default reallocator. 578 * @param element the element that shall be inserted
626 * 579 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
627 * @param array the name of the array (NOT a pointer or alias to the array) 580 * @param context (@c void*) additional context for the compare function
628 * @param elem the element to add (NOT a pointer, address is automatically taken) 581 * @retval zero success
629 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 582 * @retval non-zero a re-allocation was necessary but failed
630 * @retval zero success 583 */
631 * @retval non-zero failure 584 #define cx_array_insert_sorted_ca(allocator, array, element, cmp_func) \
632 * @see CX_ARRAY_DECLARE() 585 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, context, true)
633 * @see cx_array_simple_add_unique_a() 586
634 */ 587 /**
635 #define cx_array_simple_add_unique(array, elem, cmp_func) \ 588 * Inserts an element into a sorted array.
636 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func) 589 *
637 590 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
638 /** 591 *
639 * Convenience macro for cx_array_insert_unique() with a default 592 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
640 * layout and the specified reallocator. 593 *
641 * 594 * @param array the name of the array where the elements shall be inserted
642 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 595 * @param element the element that shall be inserted
643 * @param array the name of the array (NOT a pointer or alias to the array) 596 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
644 * @param src (@c void*) pointer to the source array 597 * @param context (@c void*) additional context for the compare function
645 * @param n (@c size_t) number of elements in the source array 598 * @retval zero success
646 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 599 * @retval non-zero a re-allocation was necessary but failed
647 * @retval zero success 600 */
648 * @retval non-zero failure 601 #define cx_array_insert_sorted_c(array, element, cmp_func, context) \
649 * @see CX_ARRAY_DECLARE() 602 cx_array_insert_sorted_ca(cxDefaultAllocator, array, element, cmp_func, context)
650 * @see cx_array_simple_insert_unique() 603
651 */ 604 /**
652 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \ 605 * Inserts sorted data into a sorted array.
653 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \ 606 *
654 cmp_func, src, sizeof((array)[0]), n, reallocator) 607 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
655 608 *
656 /** 609 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
657 * Convenience macro for cx_array_insert_unique() with a default 610 *
658 * layout and the default reallocator. 611 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
659 * 612 * @param array the name of the array where the elements shall be inserted
660 * @param array the name of the array (NOT a pointer or alias to the array) 613 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
661 * @param src (@c void*) pointer to the source array 614 * @param n (@c size_t) the number of elements that shall be inserted
662 * @param n (@c size_t) number of elements in the source array 615 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
663 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 616 * @param context (@c void*) additional context for the compare function
664 * @retval zero success 617 * @retval zero success
665 * @retval non-zero failure 618 * @retval non-zero a re-allocation was necessary but failed
666 * @see CX_ARRAY_DECLARE() 619 */
667 * @see cx_array_simple_insert_unique_a() 620 #define cx_array_insert_sorted_array_ca(allocator, array, sorted_data, n, cmp_func, context) \
668 */ 621 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, context, true)
669 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \ 622
670 cx_array_simple_insert_unique_a(NULL, array, src, n, cmp_func) 623 /**
624 * Inserts sorted data into a sorted array.
625 *
626 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
627 *
628 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
629 *
630 * @param array the name of the array where the elements shall be inserted
631 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
632 * @param n (@c size_t) the number of elements that shall be inserted
633 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
634 * @param context (@c void*) additional context for the compare function
635 * @retval zero success
636 * @retval non-zero a re-allocation was necessary but failed
637 */
638 #define cx_array_insert_sorted_array_c(array, sorted_data, n, cmp_func, context) \
639 cx_array_insert_sorted_array_ca(cxDefaultAllocator, array, sorted_data, n, cmp_func, context)
640
641 /**
642 * Inserts an element into a sorted array if it is not already contained.
643 *
644 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
645 *
646 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
647 *
648 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
649 * @param array the name of the array where the elements shall be inserted
650 * @param element the element that shall be inserted
651 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
652 * @param context (@c void*) additional context for the compare function
653 * @retval zero success
654 * @retval non-zero a re-allocation was necessary but failed
655 */
656 #define cx_array_insert_unique_ca(allocator, array, element, cmp_func, context) \
657 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, context, false)
658
659 /**
660 * Inserts an element into a sorted array if it is not already contained.
661 *
662 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
663 *
664 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
665 *
666 * @param array the name of the array where the elements shall be inserted
667 * @param element the element that shall be inserted
668 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
669 * @param context (@c void*) additional context for the compare function
670 * @retval zero success
671 * @retval non-zero a re-allocation was necessary but failed
672 */
673 #define cx_array_insert_unique_c(array, element, cmp_func, context) \
674 cx_array_insert_unique_ca(cxDefaultAllocator, array, element, cmp_func, context)
675
676 /**
677 * Inserts sorted data into a sorted array, skipping duplicates.
678 *
679 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
680 *
681 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
682 *
683 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
684 * @param array the name of the array where the elements shall be inserted
685 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
686 * @param n (@c size_t) the number of elements that shall be inserted
687 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
688 * @param context (@c void*) additional context for the compare function
689 * @retval zero success
690 * @retval non-zero a re-allocation was necessary but failed
691 */
692 #define cx_array_insert_unique_array_ca(allocator, array, sorted_data, n, cmp_func, context) \
693 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, context, false)
694
695 /**
696 * Inserts sorted data into a sorted array, skipping duplicates.
697 *
698 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
699 *
700 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
701 *
702 * @param array the name of the array where the elements shall be inserted
703 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
704 * @param n (@c size_t) the number of elements that shall be inserted
705 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
706 * @param context (@c void*) additional context for the compare function
707 * @retval zero success
708 * @retval non-zero a re-allocation was necessary but failed
709 */
710 #define cx_array_insert_unique_array_c(array, sorted_data, n, cmp_func, context) \
711 cx_array_insert_unique_array_ca(cxDefaultAllocator, array, sorted_data, n, cmp_func, context)
712
713 /**
714 * An alternative to qsort_r() when that is not available on your platform.
715 *
716 * If it is available, qsort_r() is used directly.
717 *
718 * @param array the array that shall be sorted
719 * @param nmemb the number of elements in the array
720 * @param size the size of one element
721 * @param fn the compare function
722 * @param context the context for the compare function
723 */
724 CX_EXPORT void cx_array_qsort_c(void *array, size_t nmemb, size_t size,
725 cx_compare_func2 fn, void *context);
726
727 /**
728 * Sorts an array.
729 *
730 * Internal function - do not use.
731 *
732 * @param array a pointer to the array structure
733 * @param elem_size the size of one element
734 * @param fn the compare function
735 */
736 CX_EXPORT void cx_array_sort_(CxArray *array, size_t elem_size,
737 cx_compare_func fn);
738
739 /**
740 * Sorts an array.
741 *
742 * Internal function - do not use.
743 *
744 * @param array a pointer to the array structure
745 * @param elem_size the size of one element
746 * @param fn the compare function
747 * @param context the context for the compare function
748 */
749 CX_EXPORT void cx_array_sort_c_(CxArray *array, size_t elem_size,
750 cx_compare_func2 fn, void *context);
751
752 /**
753 * Sorts an array.
754 *
755 * @param array the name of the array
756 * @param fn (@c cx_compare_func) the compare function
757 * @param context (@c void*) the context for the compare function
758 */
759 #define cx_array_sort(array, fn) \
760 cx_array_sort_((CxArray*)&(array), sizeof((array).data[0]), fn)
761
762 /**
763 * Sorts an array.
764 *
765 * @param array the name of the array
766 * @param fn (@c cx_compare_func2) the compare function
767 * @param context (@c void*) the context for the compare function
768 */
769 #define cx_array_sort_c(array, fn, context) \
770 cx_array_sort_c_((CxArray*)&(array), sizeof((array).data[0]), fn, context)
771
772 /**
773 * Creates an iterator over the elements of an array.
774 *
775 * Internal function - do not use.
776 *
777 * @param array a pointer to the array structure
778 * @param elem_size the size of one element
779 * @return an iterator over the elements
780 */
781 cx_attr_nodiscard cx_attr_nonnull
782 CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size);
783
784 /**
785 * Creates an iterator over the elements of an array.
786 *
787 * The iterator will yield pointers to the elements.
788 *
789 * This iterator cannot be used to remove elements
790 * because it does not get a modifiable reference to the array's size.
791 *
792 * @param array the name of the array
793 * @return an iterator over the elements
794 * @see cx_array_iterator_ptr()
795 */
796 #define cx_array_iterator(array) \
797 cx_array_iterator_((CxArray*)&(array), sizeof((array).data[0]))
798
799 /**
800 * Creates an iterator over the elements of an array containing pointers.
801 *
802 * Internal function - do not use.
803 *
804 * @param array the name of the array
805 * @return an iterator over the elements
806 */
807 cx_attr_nodiscard cx_attr_nonnull
808 CX_EXPORT CxIterator cx_array_iterator_ptr_(CxArray *array);
809
810 /**
811 * Creates an iterator over the elements of an array containing pointers.
812 *
813 * The iterator will yield the elements themselves, which are supposed to
814 * be pointers.
815 *
816 * This iterator cannot be used to remove elements
817 * because it does not get a modifiable reference to the array's size.
818 *
819 * @param array the name of the array
820 * @return an iterator over the elements
821 * @see cx_array_iterator()
822 */
823 #define cx_array_iterator_ptr(array) \
824 cx_array_iterator_ptr_((CxArray*)&(array))
825
826
827 /**
828 * Removes elements from the array.
829 *
830 * Internal function - do not use.
831 *
832 * @param array a pointer to the array structure
833 * @param elem_size the size of one element
834 * @param index the index of the first element to remove
835 * @param n the number of elements to remove
836 * @param fast indicates whether tail elements should be copied into the gap
837 */
838 cx_attr_nonnull
839 CX_EXPORT void cx_array_remove_(CxArray *array, size_t elem_size, size_t index, size_t n, bool fast);
840
841 /**
842 * Removes one element from the array.
843 *
844 * Tail elements are all moved by one. If you don't need a stable order
845 * in the array, consider using cx_array_remove_fast().
846 *
847 * If the index is out of bounds, this function does nothing.
848 *
849 * @param array the name of the array
850 * @param index (@c size_t) the index of the element to remove
851 * @see cx_array_remove_fast()
852 */
853 #define cx_array_remove(array, index) \
854 cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, 1, false)
855
856 /**
857 * Removes one element from the array.
858 *
859 * The gap will be filled with a copy of the last element in the array.
860 * This changes the order of elements. If you want a stable order,
861 * use cx_array_remove() instead.
862 *
863 * If the index is out of bounds, this function does nothing.
864 *
865 * @param array the name of the array
866 * @param index (@c size_t) the index of the element to remove
867 * @see cx_array_remove()
868 */
869 #define cx_array_remove_fast(array, index) \
870 cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, 1, true)
871
872 /**
873 * Removes multiple elements from the array.
874 *
875 * Tail elements are all moved to close the gap. If you don't need a stable
876 * order in the array, consider using cx_array_remove_array_fast().
877 *
878 * If the index is out of bounds, this function does nothing.
879 * If @n overflows the array, this function removes as many elements as it can.
880 *
881 * @param array the name of the array
882 * @param index (@c size_t) the index of the first element to remove
883 * @param n (@c size_t) the number of elements to remove
884 * @see cx_array_remove_array_fast()
885 */
886 #define cx_array_remove_array(array, index, n) \
887 cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, n, false)
888
889 /**
890 * Removes multiple elements from the array.
891 *
892 * Tail elements are copied into the gap. If you have more tail elements
893 * than the number of elements that are removed, this will change the order
894 * of elements. If you want a stable order, use cx_array_remove_array() instead.
895 *
896 * If the index is out of bounds, this function does nothing.
897 * If @n overflows the array, this function removes as many elements as it can.
898 *
899 * @param array the name of the array
900 * @param index (@c size_t) the index of the first element to remove
901 * @param n (@c size_t) the number of elements to remove
902 * @see cx_array_remove_array()
903 */
904 #define cx_array_remove_array_fast(array, index, n) \
905 cx_array_remove_((CxArray*)&(array), sizeof((array).data[0]), index, n, true)
906
907 /**
908 * Deallocates an array.
909 *
910 * Internal function - do not use.
911 *
912 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array
913 * @param array a pointer to the array structure
914 */
915 cx_attr_nonnull
916 CX_EXPORT void cx_array_free_(const CxAllocator *allocator, CxArray *array);
917
918 /**
919 * Deallocates an array.
920 *
921 * The structure is reset to zero and can be re-initialized with
922 * cx_array_inita().
923 *
924 * @param array the name of the array
925 */
926 #define cx_array_free(array) cx_array_free_(cxDefaultAllocator, (CxArray*)&(array))
927
928 /**
929 * Deallocates an array.
930 *
931 * The structure is reset to zero and can be re-initialized with
932 * cx_array_init_a().
933 *
934 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array
935 * @param array the name of the array
936 */
937 #define cx_array_free_a(allocator, array) cx_array_free_(allocator, (CxArray*)&(array))
938
671 939
672 /** 940 /**
673 * Searches the largest lower bound in a sorted array. 941 * Searches the largest lower bound in a sorted array.
674 * 942 *
675 * In other words, this function returns the index of the largest element 943 * In other words, this function returns the index of the largest element
748 */ 1016 */
749 cx_attr_nonnull 1017 cx_attr_nonnull
750 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size, 1018 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size,
751 size_t elem_size, const void *elem, cx_compare_func cmp_func); 1019 size_t elem_size, const void *elem, cx_compare_func cmp_func);
752 1020
1021
1022 /**
1023 * Searches the largest lower bound in a sorted array.
1024 *
1025 * In other words, this function returns the index of the largest element
1026 * in @p arr that is less or equal to @p elem with respect to @p cmp_func.
1027 * When no such element exists, @p size is returned.
1028 *
1029 * When such an element exists more than once, the largest index of all those
1030 * elements is returned.
1031 *
1032 * If @p elem is contained in the array, this is identical to
1033 * #cx_array_binary_search().
1034 *
1035 * If the array is not sorted with respect to the @p cmp_func, the behavior
1036 * is undefined.
1037 *
1038 * @param arr the array to search
1039 * @param size the size of the array
1040 * @param elem_size the size of one element
1041 * @param elem the element to find
1042 * @param cmp_func the compare function
1043 * @param context the context for the compare function
1044 * @return the index of the largest lower bound, or @p size
1045 * @see cx_array_binary_search_sup()
1046 * @see cx_array_binary_search()
1047 */
1048 cx_attr_nonnull
1049 CX_EXPORT size_t cx_array_binary_search_inf_c(const void *arr, size_t size,
1050 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
1051
1052 /**
1053 * Searches an item in a sorted array.
1054 *
1055 * When such an element exists more than once, the largest index of all those
1056 * elements is returned.
1057 *
1058 * If the array is not sorted with respect to the @p cmp_func, the behavior
1059 * is undefined.
1060 *
1061 * @param arr the array to search
1062 * @param size the size of the array
1063 * @param elem_size the size of one element
1064 * @param elem the element to find
1065 * @param cmp_func the compare function
1066 * @param context the context for the compare function
1067 * @return the index of the element in the array, or @p size if the element
1068 * cannot be found
1069 * @see cx_array_binary_search_inf()
1070 * @see cx_array_binary_search_sup()
1071 */
1072 cx_attr_nonnull
1073 CX_EXPORT size_t cx_array_binary_search_c(const void *arr, size_t size,
1074 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
1075
1076 /**
1077 * Searches the smallest upper bound in a sorted array.
1078 *
1079 * In other words, this function returns the index of the smallest element
1080 * in @p arr that is greater or equal to @p elem with respect to @p cmp_func.
1081 * When no such element exists, @p size is returned.
1082 *
1083 * When such an element exists more than once, the smallest index of all those
1084 * elements is returned.
1085 *
1086 * If @p elem is contained in the array, this is identical to
1087 * #cx_array_binary_search().
1088 *
1089 * If the array is not sorted with respect to the @p cmp_func, the behavior
1090 * is undefined.
1091 *
1092 * @param arr the array to search
1093 * @param size the size of the array
1094 * @param elem_size the size of one element
1095 * @param elem the element to find
1096 * @param cmp_func the compare function
1097 * @param context the context for the compare function
1098 * @return the index of the smallest upper bound, or @p size
1099 * @see cx_array_binary_search_inf()
1100 * @see cx_array_binary_search()
1101 */
1102 cx_attr_nonnull
1103 CX_EXPORT size_t cx_array_binary_search_sup_c(const void *arr, size_t size,
1104 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
1105
753 /** 1106 /**
754 * Swaps two array elements. 1107 * Swaps two array elements.
755 * 1108 *
756 * @param arr the array 1109 * @param arr the array
757 * @param elem_size the element size 1110 * @param elem_size the element size
764 /** 1117 /**
765 * Allocates an array list for storing elements with @p elem_size bytes each. 1118 * Allocates an array list for storing elements with @p elem_size bytes each.
766 * 1119 *
767 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of 1120 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
768 * copies of the added elements, and the compare function will be automatically set 1121 * copies of the added elements, and the compare function will be automatically set
769 * to cx_cmp_ptr(), if none is given. 1122 * to cx_cmp_ptr().
770 * 1123 *
771 * @param allocator the allocator for allocating the list memory 1124 * @param allocator the allocator for allocating the list memory
772 * (if @c NULL, the cxDefaultAllocator will be used) 1125 * (if @c NULL, the cxDefaultAllocator will be used)
773 * @param comparator the comparator for the elements
774 * (if @c NULL, and the list is not storing pointers, sort and find
775 * functions will not work)
776 * @param elem_size the size of each element in bytes 1126 * @param elem_size the size of each element in bytes
777 * @param initial_capacity the initial number of elements the array can store 1127 * @param initial_capacity the initial number of elements the array can store
778 * @return the created list 1128 * @return the created list
779 */ 1129 */
780 cx_attr_nodiscard 1130 cx_attr_nodiscard
781 cx_attr_malloc 1131 cx_attr_malloc
782 cx_attr_dealloc(cxListFree, 1) 1132 cx_attr_dealloc(cxListFree, 1)
783 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator, 1133 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator,
784 cx_compare_func comparator, size_t elem_size, size_t initial_capacity); 1134 size_t elem_size, size_t initial_capacity);
785
786 /**
787 * Allocates an array list for storing elements with @p elem_size bytes each.
788 *
789 * The list will use the cxDefaultAllocator and @em NO compare function.
790 * If you want to call functions that need a compare function, you have to
791 * set it immediately after creation or use cxArrayListCreate().
792 *
793 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
794 * copies of the added elements and the compare function will be automatically set
795 * to cx_cmp_ptr().
796 *
797 * @param elem_size (@c size_t) the size of each element in bytes
798 * @param initial_capacity (@c size_t) the initial number of elements the array can store
799 * @return the created list
800 */
801 #define cxArrayListCreateSimple(elem_size, initial_capacity) \
802 cxArrayListCreate(NULL, NULL, elem_size, initial_capacity)
803 1135
804 #ifdef __cplusplus 1136 #ifdef __cplusplus
805 } // extern "C" 1137 } // extern "C"
806 #endif 1138 #endif
807 1139

mercurial