src/cx/array_list.h

changeset 1608
46d8a8305948
parent 1607
0ecb13118cac
equal deleted inserted replaced
1607:0ecb13118cac 1608:46d8a8305948
63 } CxArray; 63 } CxArray;
64 64
65 cx_attr_nonnull 65 cx_attr_nonnull
66 CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); 66 CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
67 67
68 #define cx_array_init(array, capacity) cx_array_init_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
69
70 #define cx_array_init_a(allocator, array, capacity) cx_array_init_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) 68 #define cx_array_init_a(allocator, array, capacity) cx_array_init_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
71 69
70 #define cx_array_init(array, capacity) cx_array_init_a(cxDefaultAllocator, array, capacity)
71
72 cx_attr_nonnull
73 CX_EXPORT void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size);
74
75 #define cx_array_init_fixed(array, fixed_size_array, num_initialized) cx_array_init_fixed_((CxArray*)&(array), fixed_size_array, cx_nmemb(fixed_size_array), num_initialized)
76
72 cx_attr_nonnull 77 cx_attr_nonnull
73 CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); 78 CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
74 79
75 #define cx_array_reserve(array, capacity) cx_array_reserve_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
76
77 #define cx_array_reserve_a(allocator, array, capacity) cx_array_reserve_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) 80 #define cx_array_reserve_a(allocator, array, capacity) cx_array_reserve_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
78 81
82 #define cx_array_reserve(array, capacity) cx_array_reserve_a(cxDefaultAllocator, array, capacity)
83
79 cx_attr_nonnull 84 cx_attr_nonnull
80 CX_EXPORT int cx_array_move_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity); 85 CX_EXPORT int cx_array_move_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
81 86
82 #define cx_array_move_to_new(array, capacity) cx_array_move_to_new_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
83
84 #define cx_array_move_to_new_a(allocator, array, capacity) cx_array_move_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity) 87 #define cx_array_move_to_new_a(allocator, array, capacity) cx_array_move_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
85 88
86 cx_attr_nonnull 89 #define cx_array_move_to_new(array, capacity) cx_array_move_to_new_a(cxDefaultAllocator, array, capacity)
87 CX_EXPORT int cx_array_add_(const CxAllocator *allocator, CxArray *array, size_t elem_size, void *element);
88
89 #define cx_array_add(array, element) cx_array_add_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), element)
90
91 #define cx_array_add_a(allocator, array, element) cx_array_add_(allocator, (CxArray*)&(array), sizeof((array).data[0]), element)
92 90
93 cx_attr_nonnull_arg(1, 2) 91 cx_attr_nonnull_arg(1, 2)
94 CX_EXPORT int cx_array_insert_array_(const CxAllocator *allocator, CxArray *array, 92 CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
95 size_t elem_size, size_t index, const void *other, size_t n); 93 size_t elem_size, size_t index, const void *other, size_t n);
96 94
97 #define cx_array_insert_array(array, index, other, n) \ 95 #define cx_array_add_a(allocator, array, element) \
98 cx_array_insert_array_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n) 96 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, element, 1)
97
98 #define cx_array_add(array, element) cx_array_add_a(cxDefaultAllocator, array, element)
99
100 #define cx_array_insert_a(allocator, array, index, element) \
101 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, element, 1)
102
103 #define cx_array_insert(array, index, element) cx_array_insert_a(cxDefaultAllocator, array, index, element)
99 104
100 #define cx_array_insert_array_a(allocator, array, index, other, n) \ 105 #define cx_array_insert_array_a(allocator, array, index, other, n) \
101 cx_array_insert_array_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n) 106 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n)
102 107
103 #define cx_array_add_array(array, other, n) \ 108 #define cx_array_insert_array(array, index, other, n) cx_array_insert_array_a(cxDefaultAllocator, array, index, other, n)
104 cx_array_insert_array_(cxDefaultAllocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n)
105 109
106 #define cx_array_add_array_a(allocator, array, other, n) \ 110 #define cx_array_add_array_a(allocator, array, other, n) \
107 cx_array_insert_array_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n) 111 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n)
112
113 #define cx_array_add_array(array, other, n) cx_array_add_array_a(cxDefaultAllocator, array, other, n)
114
115 cx_attr_nonnull
116 CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
117 size_t elem_size, cx_compare_func cmp_func, const void *sorted_data, size_t n,
118 bool allow_duplicates);
119
120 #define cx_array_insert_sorted_a(allocator, array, cmp_func, element) \
121 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, true)
122
123 #define cx_array_insert_sorted(array, cmp_func, element) cx_array_insert_sorted_a(cxDefaultAllocator, array, cmp_func, element)
124
125 #define cx_array_insert_sorted_array_a(allocator, array, cmp_func, sorted_data, n) \
126 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, true)
127
128 #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)
129
130 #define cx_array_insert_unique_a(allocator, array, cmp_func, element) \
131 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, false)
132
133 #define cx_array_insert_unique(array, cmp_func, element) cx_array_insert_unique_a(cxDefaultAllocator, array, cmp_func, element)
134
135 #define cx_array_insert_unique_array_a(allocator, array, cmp_func, sorted_data, n) \
136 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, false)
137
138 #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)
108 139
109 cx_attr_nodiscard cx_attr_nonnull 140 cx_attr_nodiscard cx_attr_nonnull
110 CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size); 141 CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size);
111 142
112 #define cx_array_iterator(array) cx_array_iterator_((CxArray*)&(array), sizeof((array).data[0])) 143 #define cx_array_iterator(array) cx_array_iterator_((CxArray*)&(array), sizeof((array).data[0]))
121 152
122 #define cx_array_free(array) cx_array_free_(cxDefaultAllocator, (CxArray*)&(array)) 153 #define cx_array_free(array) cx_array_free_(cxDefaultAllocator, (CxArray*)&(array))
123 154
124 #define cx_array_free_a(allocator, array) cx_array_free_(allocator, (CxArray*)&(array)) 155 #define cx_array_free_a(allocator, array) cx_array_free_(allocator, (CxArray*)&(array))
125 156
126 /** 157
127 * Declares variables for an array that can be used with the convenience macros.
128 *
129 * @par Examples
130 * @code
131 * // integer array with at most 255 elements
132 * CX_ARRAY_DECLARE_SIZED(int, myarray, uint8_t)
133 *
134 * // array of MyObject* pointers where size and capacity are stored as unsigned int
135 * CX_ARRAY_DECLARE_SIZED(MyObject*, objects, unsigned int)
136 *
137 * // initializing code
138 * cx_array_initialize(myarray, 16); // reserve space for 16
139 * cx_array_initialize(objects, 100); // reserve space for 100
140 * @endcode
141 *
142 * @param type the type of the data
143 * @param name the name of the array
144 * @param size_type the type of the size (should be uint8_t, uint16_t, uint32_t, or size_t)
145 *
146 * @see cx_array_initialize()
147 * @see cx_array_simple_copy()
148 * @see cx_array_simple_add_sorted()
149 * @see cx_array_simple_insert_sorted()
150 */
151 #define CX_ARRAY_DECLARE_SIZED(type, name, size_type) \
152 type * name; \
153 /** Array size. */ size_type name##_size; \
154 /** Array capacity. */ size_type name##_capacity
155
156 /**
157 * Declares variables for an array that can be used with the convenience macros.
158 *
159 * The size and capacity variables will have type @c size_t.
160 * Use #CX_ARRAY_DECLARE_SIZED() to specify a different type.
161 *
162 * @par Examples
163 * @code
164 * // int array
165 * CX_ARRAY_DECLARE(int, myarray)
166 *
167 * // initializing code
168 * cx_array_initialize(myarray, 32); // reserve space for 32
169 * @endcode
170 *
171 * @param type the type of the data
172 * @param name the name of the array
173 *
174 * @see cx_array_initialize()
175 * @see cx_array_simple_copy()
176 * @see cx_array_simple_add_sorted()
177 * @see cx_array_simple_insert_sorted()
178 */
179 #define CX_ARRAY_DECLARE(type, name) CX_ARRAY_DECLARE_SIZED(type, name, size_t)
180
181 /**
182 * Initializes an array with the given capacity.
183 *
184 * The type of the capacity depends on the type used during declaration.
185 *
186 * @par Examples
187 * @code
188 * CX_ARRAY_DECLARE_SIZED(int, arr1, uint8_t)
189 * CX_ARRAY_DECLARE(int, arr2) // size and capacity are implicitly size_t
190 *
191 * // initializing code
192 * cx_array_initialize(arr1, 500); // error: maximum for uint8_t is 255
193 * cx_array_initialize(arr2, 500); // OK
194 * @endcode
195 *
196 *
197 * The memory for the array is allocated with the cxDefaultAllocator.
198 *
199 * @param array the name of the array
200 * @param capacity the initial capacity
201 * @see cx_array_initialize_a()
202 * @see CX_ARRAY_DECLARE_SIZED()
203 * @see CX_ARRAY_DECLARE()
204 */
205 #define cx_array_initialize(array, capacity) \
206 array##_capacity = capacity; \
207 array##_size = 0; \
208 array = cxMallocDefault(sizeof(array[0]) * capacity)
209
210 /**
211 * Initializes an array with the given capacity using the specified allocator.
212 *
213 * @par Example
214 * @code
215 * CX_ARRAY_DECLARE(int, myarray)
216 *
217 *
218 * const CxAllocator *al = // ...
219 * cx_array_initialize_a(al, myarray, 128);
220 * // ...
221 * cxFree(al, myarray); // remember to free with the same allocator
222 * @endcode
223 *
224 * @param allocator (@c CxAllocator*) the allocator
225 * @param array the name of the array
226 * @param capacity the initial capacity
227 * @see cx_array_initialize()
228 * @see CX_ARRAY_DECLARE_SIZED()
229 * @see CX_ARRAY_DECLARE()
230 */
231 #define cx_array_initialize_a(allocator, array, capacity) \
232 array##_capacity = capacity; \
233 array##_size = 0; \
234 array = cxMalloc(allocator, sizeof(array[0]) * capacity)
235
236 /**
237 * Defines a reallocation mechanism for arrays.
238 * You can create your own, use cx_array_reallocator(), or
239 * use the #cx_array_default_reallocator.
240 */
241 struct cx_array_reallocator_s {
242 /**
243 * Reallocates space for the given array.
244 *
245 * Implementations are not required to free the original array.
246 * This allows reallocation of static or stack memory by allocating heap memory
247 * and copying the array contents; namely when @c stack_ptr in this struct
248 * is not @c NULL and @p array equals @c stack_ptr.
249 *
250 * @param array the array to reallocate
251 * @param old_capacity the old number of elements
252 * @param new_capacity the new number of elements
253 * @param elem_size the size of each element
254 * @param alloc a reference to this allocator
255 * @return a pointer to the reallocated memory or @c NULL on failure
256 */
257 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity,
258 size_t elem_size, struct cx_array_reallocator_s *alloc);
259
260 /**
261 * The allocator that shall be used for the reallocations.
262 */
263 const CxAllocator *allocator;
264 /**
265 * Optional pointer to stack memory
266 * if the array is originally located on the stack.
267 */
268 const void *stack_ptr;
269 };
270
271 /**
272 * Typedef for the array reallocator struct.
273 */
274 typedef struct cx_array_reallocator_s CxArrayReallocator;
275
276 /**
277 * A default array reallocator that is based on the cxDefaultAllocator.
278 */
279 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator;
280
281 /**
282 * Creates a new array reallocator.
283 *
284 * When @p allocator is @c NULL, the cxDefaultAllocator will be used.
285 *
286 * When @p stack_ptr is not @c NULL, the reallocator is supposed to be used
287 * @em only for the specific array initially located at @p stack_ptr.
288 * When reallocation is needed, the reallocator checks if the array is
289 * still located at @p stack_ptr and copies the contents to the heap.
290 *
291 * @note Invoking this function with both arguments being @c NULL will return a
292 * reallocator that behaves like #cx_array_default_reallocator.
293 *
294 * @param allocator the allocator this reallocator shall be based on
295 * @param stack_ptr the address of the array when the array is initially located
296 * on the stack or shall not reallocate in place
297 * @return an array reallocator
298 */
299 CX_EXPORT CxArrayReallocator cx_array_reallocator(
300 const struct cx_allocator_s *allocator, const void *stack_ptr);
301 /**
302 * Copies elements from one array to another.
303 *
304 * The elements are copied to the @p target array at the specified @p index,
305 * overwriting possible elements. The @p index does not need to be in range of
306 * the current array @p size. If the new index plus the number of elements added
307 * extends the array's size, the remaining @p capacity is used.
308 *
309 * If the @p capacity is also insufficient to hold the new data, a reallocation
310 * attempt is made with the specified @p reallocator.
311 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
312 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
313 *
314 * The @p width in bytes refers to the size and capacity.
315 * Both must have the same width.
316 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit
317 * architecture. If set to zero, the native word width is used.
318 *
319 * @note When this function does reallocate the array, it may allocate more
320 * space than required to avoid further allocations in the near future.
321 *
322 * @param target a pointer to the target array
323 * @param size a pointer to the size of the target array
324 * @param capacity a pointer to the capacity of the target array
325 * @param width the width in bytes for the @p size and @p capacity or zero for default
326 * @param index the index where the copied elements shall be placed
327 * @param src the source array
328 * @param elem_size the size of one element
329 * @param elem_count the number of elements to copy
330 * @param reallocator the array reallocator to use
331 * (@c NULL defaults to #cx_array_default_reallocator)
332 * @retval zero success
333 * @retval non-zero failure
334 * @see cx_array_reallocator()
335 */
336 cx_attr_nonnull_arg(1, 2, 3, 6)
337 CX_EXPORT int cx_array_copy(void **target, void *size, void *capacity, unsigned width,
338 size_t index, const void *src, size_t elem_size, size_t elem_count,
339 CxArrayReallocator *reallocator);
340
341 /**
342 * Convenience macro that uses cx_array_copy() with a default layout and
343 * the specified reallocator.
344 *
345 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
346 * @param array the name of the array (NOT a pointer or alias to the array)
347 * @param index (@c size_t) the index where the copied elements shall be placed
348 * @param src (@c void*) the source array
349 * @param count (@c size_t) the number of elements to copy
350 * @retval zero success
351 * @retval non-zero failure
352 * @see CX_ARRAY_DECLARE()
353 * @see cx_array_simple_copy()
354 */
355 #define cx_array_simple_copy_a(reallocator, array, index, src, count) \
356 cx_array_copy((void**)&(array), &(array##_size), &(array##_capacity), \
357 sizeof(array##_size), index, src, sizeof((array)[0]), count, \
358 reallocator)
359
360 /**
361 * Convenience macro that uses cx_array_copy() with a default layout and
362 * the default reallocator.
363 *
364 * @param array the name of the array (NOT a pointer or alias to the array)
365 * @param index (@c size_t) the index where the copied elements shall be placed
366 * @param src (@c void*) the source array
367 * @param count (@c size_t) the number of elements to copy
368 * @retval zero success
369 * @retval non-zero failure
370 * @see CX_ARRAY_DECLARE()
371 * @see cx_array_simple_copy_a()
372 */
373 #define cx_array_simple_copy(array, index, src, count) \
374 cx_array_simple_copy_a(NULL, array, index, src, count)
375
376 /**
377 * Inserts a sorted array into another sorted array.
378 *
379 * If either the target or the source array is not already sorted with respect
380 * to the specified @p cmp_func, the behavior is undefined.
381 *
382 * If the capacity is insufficient to hold the new data, a reallocation
383 * attempt is made.
384 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
385 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
386 *
387 * @param target a pointer to the target array
388 * @param size a pointer to the size of the target array
389 * @param capacity a pointer to the capacity of the target array
390 * @param cmp_func the compare function for the elements
391 * @param src the source array
392 * @param elem_size the size of one element
393 * @param elem_count the number of elements to insert
394 * @param reallocator the array reallocator to use
395 * (@c NULL defaults to #cx_array_default_reallocator)
396 * @retval zero success
397 * @retval non-zero failure
398 */
399 cx_attr_nonnull_arg(1, 2, 3, 5)
400 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity,
401 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count,
402 CxArrayReallocator *reallocator);
403
404 /**
405 * Inserts an element into a sorted array.
406 *
407 * If the target array is not already sorted with respect
408 * to the specified @p cmp_func, the behavior is undefined.
409 *
410 * If the capacity is not enough to hold the new data, a reallocation
411 * attempt is made.
412 *
413 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type.
414 * It is important, however, that @p size and @p capacity are pointers to
415 * variables of the same type.
416 *
417 * @param target (@c void**) a pointer to the target array
418 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array
419 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array
420 * @param elem_size (@c size_t) the size of one element
421 * @param elem (@c void*) a pointer to the element to add
422 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
423 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
424 * @retval zero success
425 * @retval non-zero failure
426 */
427 #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \
428 cx_array_insert_sorted((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator)
429
430 /**
431 * Convenience macro for cx_array_add_sorted() with a default
432 * layout and the specified reallocator.
433 *
434 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
435 * @param array the name of the array (NOT a pointer or alias to the array)
436 * @param elem the element to add (NOT a pointer, address is automatically taken)
437 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
438 * @retval zero success
439 * @retval non-zero failure
440 * @see CX_ARRAY_DECLARE()
441 * @see cx_array_simple_add_sorted()
442 */
443 #define cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) \
444 cx_array_add_sorted(&array, &(array##_size), &(array##_capacity), \
445 sizeof((array)[0]), &(elem), cmp_func, reallocator)
446
447 /**
448 * Convenience macro for cx_array_add_sorted() with a default
449 * layout and the default reallocator.
450 *
451 * @param array the name of the array (NOT a pointer or alias to the array)
452 * @param elem the element to add (NOT a pointer, address is automatically taken)
453 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
454 * @retval zero success
455 * @retval non-zero failure
456 * @see CX_ARRAY_DECLARE()
457 * @see cx_array_simple_add_sorted_a()
458 */
459 #define cx_array_simple_add_sorted(array, elem, cmp_func) \
460 cx_array_simple_add_sorted_a(NULL, array, elem, cmp_func)
461
462 /**
463 * Convenience macro for cx_array_insert_sorted() with a default
464 * layout and the specified reallocator.
465 *
466 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
467 * @param array the name of the array (NOT a pointer or alias to the array)
468 * @param src (@c void*) pointer to the source array
469 * @param n (@c size_t) number of elements in the source array
470 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
471 * @retval zero success
472 * @retval non-zero failure
473 * @see CX_ARRAY_DECLARE()
474 * @see cx_array_simple_insert_sorted()
475 */
476 #define cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) \
477 cx_array_insert_sorted((void**)(&array), &(array##_size), &(array##_capacity), \
478 cmp_func, src, sizeof((array)[0]), n, reallocator)
479
480 /**
481 * Convenience macro for cx_array_insert_sorted() with a default
482 * layout and the default reallocator.
483 *
484 * @param array the name of the array (NOT a pointer or alias to the array)
485 * @param src (@c void*) pointer to the source array
486 * @param n (@c size_t) number of elements in the source array
487 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
488 * @retval zero success
489 * @retval non-zero failure
490 * @see CX_ARRAY_DECLARE()
491 * @see cx_array_simple_insert_sorted_a()
492 */
493 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \
494 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func)
495
496
497 /**
498 * Inserts a sorted array into another sorted array, avoiding duplicates.
499 *
500 * If either the target or the source array is not already sorted with respect
501 * to the specified @p cmp_func, the behavior is undefined.
502 *
503 * If the capacity is insufficient to hold the new data, a reallocation
504 * attempt is made.
505 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
506 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
507 *
508 * @param target a pointer to the target array
509 * @param size a pointer to the size of the target array
510 * @param capacity a pointer to the capacity of the target array
511 * @param cmp_func the compare function for the elements
512 * @param src the source array
513 * @param elem_size the size of one element
514 * @param elem_count the number of elements to insert
515 * @param reallocator the array reallocator to use
516 * (@c NULL defaults to #cx_array_default_reallocator)
517 * @retval zero success
518 * @retval non-zero failure
519 */
520 cx_attr_nonnull_arg(1, 2, 3, 5)
521 CX_EXPORT int cx_array_insert_unique(void **target, size_t *size, size_t *capacity,
522 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count,
523 CxArrayReallocator *reallocator);
524
525 /**
526 * Inserts an element into a sorted array if it does not exist.
527 *
528 * If the target array is not already sorted with respect
529 * to the specified @p cmp_func, the behavior is undefined.
530 *
531 * If the capacity is insufficient to hold the new data, a reallocation
532 * attempt is made.
533 *
534 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type.
535 * It is important, however, that @p size and @p capacity are pointers to
536 * variables of the same type.
537 *
538 * @param target (@c void**) a pointer to the target array
539 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array
540 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array
541 * @param elem_size (@c size_t) the size of one element
542 * @param elem (@c void*) a pointer to the element to add
543 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
544 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
545 * @retval zero success (also when the element was already present)
546 * @retval non-zero failure
547 */
548 #define cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) \
549 cx_array_insert_unique((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator)
550
551 /**
552 * Convenience macro for cx_array_add_unique() with a default
553 * layout and the specified reallocator.
554 *
555 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
556 * @param array the name of the array (NOT a pointer or alias to the array)
557 * @param elem the element to add (NOT a pointer, address is automatically taken)
558 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
559 * @retval zero success
560 * @retval non-zero failure
561 * @see CX_ARRAY_DECLARE()
562 * @see cx_array_simple_add_unique()
563 */
564 #define cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) \
565 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \
566 sizeof((array)[0]), &(elem), cmp_func, reallocator)
567
568 /**
569 * Convenience macro for cx_array_add_unique() with a default
570 * layout and the default reallocator.
571 *
572 * @param array the name of the array (NOT a pointer or alias to the array)
573 * @param elem the element to add (NOT a pointer, address is automatically taken)
574 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
575 * @retval zero success
576 * @retval non-zero failure
577 * @see CX_ARRAY_DECLARE()
578 * @see cx_array_simple_add_unique_a()
579 */
580 #define cx_array_simple_add_unique(array, elem, cmp_func) \
581 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func)
582
583 /**
584 * Convenience macro for cx_array_insert_unique() with a default
585 * layout and the specified reallocator.
586 *
587 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use
588 * @param array the name of the array (NOT a pointer or alias to the array)
589 * @param src (@c void*) pointer to the source array
590 * @param n (@c size_t) number of elements in the source array
591 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
592 * @retval zero success
593 * @retval non-zero failure
594 * @see CX_ARRAY_DECLARE()
595 * @see cx_array_simple_insert_unique()
596 */
597 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \
598 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \
599 cmp_func, src, sizeof((array)[0]), n, reallocator)
600
601 /**
602 * Convenience macro for cx_array_insert_unique() with a default
603 * layout and the default reallocator.
604 *
605 * @param array the name of the array (NOT a pointer or alias to the array)
606 * @param src (@c void*) pointer to the source array
607 * @param n (@c size_t) number of elements in the source array
608 * @param cmp_func (@c cx_cmp_func) the compare function for the elements
609 * @retval zero success
610 * @retval non-zero failure
611 * @see CX_ARRAY_DECLARE()
612 * @see cx_array_simple_insert_unique_a()
613 */
614 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \
615 cx_array_simple_insert_unique_a(NULL, array, src, n, cmp_func)
616 158
617 /** 159 /**
618 * Searches the largest lower bound in a sorted array. 160 * Searches the largest lower bound in a sorted array.
619 * 161 *
620 * In other words, this function returns the index of the largest element 162 * In other words, this function returns the index of the largest element

mercurial