ucx/cx/array_list.h

branch
dav-2
changeset 891
4d58cbcc9efa
parent 889
42cdbf9bbd49
equal deleted inserted replaced
890:e77ccf1c4bb3 891:4d58cbcc9efa
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 * @param array a pointer to the target array 235 * @see cx_array_init_fixed()
249 * @param size a pointer to the size of the array 236 */
250 * @param capacity a pointer to the capacity of the array 237 #define cx_array_copy_to_new_a(allocator, array, capacity) \
251 * @param width the width in bytes for the @p size and @p capacity or zero for default 238 cx_array_copy_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
252 * @param elem_size the size of one element 239
253 * @param elem_count the number of expected additional elements 240 /**
254 * @param reallocator the array reallocator to use 241 * Copies the array to a new memory region.
255 * (@c NULL defaults to #cx_array_default_reallocator) 242 *
256 * @retval zero success 243 * This is useful when you have initialized the array with a fixed size memory
257 * @retval non-zero failure 244 * using cx_array_init_fixed(), and now you want to increase the capacity.
258 * @see cx_array_reallocator() 245 *
259 */ 246 * @attention When the original memory does not belong to stack memory, and
260 cx_attr_nonnull_arg(1, 2, 3) 247 * you do not have another reference to this memory, it will leak.
261 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, 248 *
262 unsigned width, size_t elem_size, size_t elem_count, 249 * @param array the name of the array
263 CxArrayReallocator *reallocator); 250 * @param capacity (@c size_t) the new maximum number of elements
264 251 * @retval zero allocation was successful
265 /** 252 * @retval non-zero allocation failed
266 * Copies elements from one array to another. 253 * @see cx_array_init_fixed()
267 * 254 */
268 * The elements are copied to the @p target array at the specified @p index, 255 #define cx_array_copy_to_new(array, capacity) \
269 * overwriting possible elements. The @p index does not need to be in range of 256 cx_array_copy_to_new_a(cxDefaultAllocator, array, capacity)
270 * the current array @p size. If the new index plus the number of elements added 257
271 * extends the array's size, the remaining @p capacity is used. 258 /**
272 * 259 * Inserts data into an array.
273 * If the @p capacity is also insufficient to hold the new data, a reallocation 260 *
274 * attempt is made with the specified @p reallocator. 261 * Internal function - do not use.
275 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 262 *
276 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 263 * @param allocator the allocator to use for a possible reallocation
277 * 264 * @param array a pointer to the array structure
278 * The @p width in bytes refers to the size and capacity. 265 * @param elem_size the size of one element
279 * Both must have the same width. 266 * @param index the index where to insert the @p other data
280 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit 267 * @param other a pointer to an array of data that shall be inserted
281 * architecture. If set to zero, the native word width is used. 268 * @param n the number of elements that shall be inserted
282 * 269 * @retval zero success
283 * @param target a pointer to the target array 270 * @retval non-zero a re-allocation was necessary but failed
284 * @param size a pointer to the size of the target array 271 */
285 * @param capacity a pointer to the capacity of the target array 272 cx_attr_nonnull_arg(1, 2)
286 * @param width the width in bytes for the @p size and @p capacity or zero for default 273 CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
287 * @param index the index where the copied elements shall be placed 274 size_t elem_size, size_t index, const void *other, size_t n);
288 * @param src the source array 275
289 * @param elem_size the size of one element 276 /**
290 * @param elem_count the number of elements to copy 277 * Appends an element to an array.
291 * @param reallocator the array reallocator to use 278 *
292 * (@c NULL defaults to #cx_array_default_reallocator) 279 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
293 * @retval zero success 280 *
294 * @retval non-zero failure 281 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
295 * @see cx_array_reallocator() 282 * @param array the name of the array where the element shall be added
296 */ 283 * @param element the element that shall be added
297 cx_attr_nonnull_arg(1, 2, 3, 6) 284 * @retval zero success
298 CX_EXPORT int cx_array_copy(void **target, void *size, void *capacity, unsigned width, 285 * @retval non-zero a re-allocation was necessary but failed
299 size_t index, const void *src, size_t elem_size, size_t elem_count, 286 */
300 CxArrayReallocator *reallocator); 287 #define cx_array_add_a(allocator, array, element) \
301 288 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, (void*)&(element), 1)
302 /** 289
303 * Convenience macro that uses cx_array_copy() with a default layout and 290 /**
304 * the specified reallocator. 291 * Appends an element to an array.
305 * 292 *
306 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 293 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
307 * @param array the name of the array (NOT a pointer or alias to the array) 294 *
308 * @param index (@c size_t) the index where the copied elements shall be placed 295 * @param array the name of the array where the element shall be added
309 * @param src (@c void*) the source array 296 * @param element (@c void*) a pointer to the element that shall be added
310 * @param count (@c size_t) the number of elements to copy 297 * @retval zero success
311 * @retval zero success 298 * @retval non-zero a re-allocation was necessary but failed
312 * @retval non-zero failure 299 */
313 * @see CX_ARRAY_DECLARE() 300 #define cx_array_add(array, element) \
314 * @see cx_array_simple_copy() 301 cx_array_add_a(cxDefaultAllocator, array, element)
315 */ 302
316 #define cx_array_simple_copy_a(reallocator, array, index, src, count) \ 303 /**
317 cx_array_copy((void**)&(array), &(array##_size), &(array##_capacity), \ 304 * Inserts an element into an array.
318 sizeof(array##_size), index, src, sizeof((array)[0]), count, \ 305 *
319 reallocator) 306 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
320 307 *
321 /** 308 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
322 * Convenience macro that uses cx_array_copy() with a default layout and 309 * @param array the name of the array where the element shall be inserted
323 * the default reallocator. 310 * @param index (@c size_t) the index where to insert the @p element
324 * 311 * @param element the element that shall be inserted
325 * @param array the name of the array (NOT a pointer or alias to the array) 312 * @retval zero success
326 * @param index (@c size_t) the index where the copied elements shall be placed 313 * @retval non-zero a re-allocation was necessary but failed
327 * @param src (@c void*) the source array 314 */
328 * @param count (@c size_t) the number of elements to copy 315 #define cx_array_insert_a(allocator, array, index, element) \
329 * @retval zero success 316 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, (void*)&(element), 1)
330 * @retval non-zero failure 317
331 * @see CX_ARRAY_DECLARE() 318 /**
332 * @see cx_array_simple_copy_a() 319 * Inserts an element into an array.
333 */ 320 *
334 #define cx_array_simple_copy(array, index, src, count) \ 321 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
335 cx_array_simple_copy_a(NULL, array, index, src, count) 322 *
336 323 * @param array the name of the array where the element shall be inserted
337 /** 324 * @param index (@c size_t) the index where to insert the @p element
338 * Convenience macro that uses cx_array_reserve() with a default layout and 325 * @param element (@c void*) a pointer to the element that shall be inserted
339 * the specified reallocator. 326 * @retval zero success
340 * 327 * @retval non-zero a re-allocation was necessary but failed
341 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 328 */
342 * @param array the name of the array (NOT a pointer or alias to the array) 329 #define cx_array_insert(array, index, element) \
343 * @param count (@c size_t) the number of expected @em additional elements 330 cx_array_insert_a(cxDefaultAllocator, array, index, element)
344 * @retval zero success 331
345 * @retval non-zero failure 332 /**
346 * @see CX_ARRAY_DECLARE() 333 * Inserts data into an array.
347 * @see cx_array_simple_reserve() 334 *
348 */ 335 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
349 #define cx_array_simple_reserve_a(reallocator, array, count) \ 336 *
350 cx_array_reserve((void**)&(array), &(array##_size), &(array##_capacity), \ 337 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
351 sizeof(array##_size), sizeof((array)[0]), count, \ 338 * @param array the name of the array where the elements shall be inserted
352 reallocator) 339 * @param index (@c size_t) the index where to insert the @p other data
353 340 * @param other (@c void*) a pointer to an array of data that shall be inserted
354 /** 341 * @param n (@c size_t) the number of elements that shall be inserted
355 * Convenience macro that uses cx_array_reserve() with a default layout and 342 * @retval zero success
356 * the default reallocator. 343 * @retval non-zero a re-allocation was necessary but failed
357 * 344 */
358 * @param array the name of the array (NOT a pointer or alias to the array) 345 #define cx_array_insert_array_a(allocator, array, index, other, n) \
359 * @param count (@c size_t) the number of expected additional elements 346 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n)
360 * @retval zero success 347
361 * @retval non-zero failure 348 /**
362 * @see CX_ARRAY_DECLARE() 349 * Inserts data into an array.
363 * @see cx_array_simple_reserve_a() 350 *
364 */ 351 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
365 #define cx_array_simple_reserve(array, count) \ 352 *
366 cx_array_simple_reserve_a(NULL, array, count) 353 * @param array the name of the array where the elements shall be inserted
367 354 * @param index (@c size_t) the index where to insert the @p other data
368 /** 355 * @param other (@c void*) a pointer to an array of data that shall be inserted
369 * Adds an element to an array with the possibility of allocating more space. 356 * @param n (@c size_t) the number of elements that shall be inserted
370 * 357 * @retval zero success
371 * The element @p elem is added to the end of the @p target array which contains 358 * @retval non-zero a re-allocation was necessary but failed
372 * @p size elements, already. The @p capacity must point to a variable denoting 359 */
373 * the current maximum number of elements the array can hold. 360 #define cx_array_insert_array(array, index, other, n) \
374 * 361 cx_array_insert_array_a(cxDefaultAllocator, array, index, other, n)
375 * If the capacity is insufficient to hold the new element, an attempt to 362
376 * increase the @p capacity is made and the new capacity is written back. 363 /**
377 * 364 * Appends data to an array.
378 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 365 *
379 * It is important, however, that @p size and @p capacity are pointers to 366 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
380 * variables of the same type. 367 *
381 * 368 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
382 * @param target (@c void**) a pointer to the target array 369 * @param array the name of the array where the elements shall be added
383 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 370 * @param other (@c void*) a pointer to an array of data that shall be added
384 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 371 * @param n (@c size_t) the number of elements that shall be added
385 * @param elem_size (@c size_t) the size of one element 372 * @retval zero success
386 * @param elem (@c void*) a pointer to the element to add 373 * @retval non-zero a re-allocation was necessary but failed
387 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 374 */
388 * @retval zero success 375 #define cx_array_add_array_a(allocator, array, other, n) \
389 * @retval non-zero failure 376 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n)
390 */ 377
391 #define cx_array_add(target, size, capacity, elem_size, elem, reallocator) \ 378 /**
392 cx_array_copy((void**)(target), size, capacity, sizeof(*(size)), \ 379 * Appends data to an array.
393 *(size), elem, elem_size, 1, reallocator) 380 *
394 381 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
395 /** 382 *
396 * Convenience macro that uses cx_array_add() with a default layout and 383 * @param array the name of the array where the elements shall be added
397 * the specified reallocator. 384 * @param other (@c void*) a pointer to an array of data that shall be added
398 * 385 * @param n (@c size_t) the number of elements that shall be added
399 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 386 * @retval zero success
400 * @param array the name of the array (NOT a pointer or alias to the array) 387 * @retval non-zero a re-allocation was necessary but failed
401 * @param elem the element to add (NOT a pointer, address is automatically taken) 388 */
402 * @retval zero success 389 #define cx_array_add_array(array, other, n) \
403 * @retval non-zero failure 390 cx_array_add_array_a(cxDefaultAllocator, array, other, n)
404 * @see CX_ARRAY_DECLARE() 391
405 * @see cx_array_simple_add() 392 /**
406 */ 393 * Inserts sorted data into a sorted array.
407 #define cx_array_simple_add_a(reallocator, array, elem) \ 394 *
408 cx_array_simple_copy_a(reallocator, array, array##_size, &(elem), 1) 395 * Internal function - do not use.
409 396 *
410 /** 397 * @param allocator the allocator to use for a possible reallocation
411 * Convenience macro that uses cx_array_add() with a default layout and 398 * @param array a pointer to the array structure
412 * the default reallocator. 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 * @param array the name of the array (NOT a pointer or alias to the array) 401 * @param n the number of elements that shall be inserted
415 * @param elem the element to add (NOT a pointer, address is automatically taken) 402 * @param cmp_func the compare function
416 * @retval zero success 403 * @param allow_duplicates @c false if duplicates shall be skipped during insertion
417 * @retval non-zero failure 404 * @retval zero success
418 * @see CX_ARRAY_DECLARE() 405 * @retval non-zero a re-allocation was necessary but failed
419 * @see cx_array_simple_add_a() 406 */
420 */ 407 cx_attr_nonnull
421 #define cx_array_simple_add(array, elem) \ 408 CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
422 cx_array_simple_add_a(cx_array_default_reallocator, array, elem) 409 size_t elem_size, const void *sorted_data, size_t n,
423 410 cx_compare_func cmp_func, bool allow_duplicates);
424 /**
425 * Inserts a sorted array into another sorted array.
426 *
427 * If either the target or the source array is not already sorted with respect
428 * to the specified @p cmp_func, the behavior is undefined.
429 *
430 * If the capacity is insufficient to hold the new data, a reallocation
431 * attempt is made.
432 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
433 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
434 *
435 * @param target a pointer to the target array
436 * @param size a pointer to the size of the target array
437 * @param capacity a pointer to the capacity of the target array
438 * @param cmp_func the compare function for the elements
439 * @param src the source array
440 * @param elem_size the size of one element
441 * @param elem_count the number of elements to insert
442 * @param reallocator the array reallocator to use
443 * (@c NULL defaults to #cx_array_default_reallocator)
444 * @retval zero success
445 * @retval non-zero failure
446 */
447 cx_attr_nonnull_arg(1, 2, 3, 5)
448 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity,
449 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count,
450 CxArrayReallocator *reallocator);
451 411
452 /** 412 /**
453 * Inserts an element into a sorted array. 413 * Inserts an element into a sorted array.
454 * 414 *
455 * 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.
456 * to the specified @p cmp_func, the behavior is undefined. 416 *
457 * 417 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
458 * If the capacity is not enough to hold the new data, a reallocation 418 *
459 * attempt is made. 419 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
460 * 420 * @param array the name of the array where the elements shall be inserted
461 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 421 * @param element the element that shall be inserted
462 * 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
463 * variables of the same type. 423 * @retval zero success
464 * 424 * @retval non-zero a re-allocation was necessary but failed
465 * @param target (@c void**) a pointer to the target array 425 */
466 * @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) \
467 * @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)
468 * @param elem_size (@c size_t) the size of one element 428
469 * @param elem (@c void*) a pointer to the element to add 429 /**
470 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 430 * Inserts an element into a sorted array.
471 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 431 *
472 * @retval zero success 432 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
473 * @retval non-zero failure 433 *
474 */ 434 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
475 #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ 435 *
476 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
477 437 * @param element the element that shall be inserted
478 /** 438 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
479 * Convenience macro for cx_array_add_sorted() with a default 439 * @retval zero success
480 * layout and the specified reallocator. 440 * @retval non-zero a re-allocation was necessary but failed
481 * 441 */
482 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 442 #define cx_array_insert_sorted(array, element, cmp_func) \
483 * @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)
484 * @param elem the element to add (NOT a pointer, address is automatically taken) 444
485 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 445 /**
486 * @retval zero success 446 * Inserts sorted data into a sorted array.
487 * @retval non-zero failure 447 *
488 * @see CX_ARRAY_DECLARE() 448 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
489 * @see cx_array_simple_add_sorted() 449 *
490 */ 450 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
491 #define cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) \ 451 *
492 cx_array_add_sorted(&array, &(array##_size), &(array##_capacity), \ 452 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
493 sizeof((array)[0]), &(elem), cmp_func, reallocator) 453 * @param array the name of the array where the elements shall be inserted
494 454 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
495 /** 455 * @param n (@c size_t) the number of elements that shall be inserted
496 * 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
497 * layout and the default reallocator. 457 * @retval zero success
498 * 458 * @retval non-zero a re-allocation was necessary but failed
499 * @param array the name of the array (NOT a pointer or alias to the array) 459 */
500 * @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) \
501 * @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)
502 * @retval zero success 462
503 * @retval non-zero failure 463 /**
504 * @see CX_ARRAY_DECLARE() 464 * Inserts sorted data into a sorted array.
505 * @see cx_array_simple_add_sorted_a() 465 *
506 */ 466 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
507 #define cx_array_simple_add_sorted(array, elem, cmp_func) \ 467 *
508 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.
509 469 *
510 /** 470 * @param array the name of the array where the elements shall be inserted
511 * 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
512 * layout and the specified reallocator. 472 * @param n (@c size_t) the number of elements that shall be inserted
513 * 473 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
514 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 474 * @retval zero success
515 * @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
516 * @param src (@c void*) pointer to the source array 476 */
517 * @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) \
518 * @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)
519 * @retval zero success 479
520 * @retval non-zero failure 480 /**
521 * @see CX_ARRAY_DECLARE() 481 * Inserts an element into a sorted array if it is not already contained.
522 * @see cx_array_simple_insert_sorted() 482 *
523 */ 483 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
524 #define cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) \ 484 *
525 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.
526 cmp_func, src, sizeof((array)[0]), n, reallocator) 486 *
527 487 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
528 /** 488 * @param array the name of the array where the elements shall be inserted
529 * Convenience macro for cx_array_insert_sorted() with a default 489 * @param element the element that shall be inserted
530 * layout and the default reallocator. 490 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
531 * 491 * @retval zero success
532 * @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
533 * @param src (@c void*) pointer to the source array 493 */
534 * @param n (@c size_t) number of elements in the source array 494 #define cx_array_insert_unique_a(allocator, array, element, cmp_func) \
535 * @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)
536 * @retval zero success 496
537 * @retval non-zero failure 497 /**
538 * @see CX_ARRAY_DECLARE() 498 * Inserts an element into a sorted array if it is not already contained.
539 * @see cx_array_simple_insert_sorted_a() 499 *
540 */ 500 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
541 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ 501 *
542 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.
543 503 *
544 504 * @param array the name of the array where the elements shall be inserted
545 /** 505 * @param element the element that shall be inserted
546 * 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
547 * 507 * @retval zero success
548 * 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
549 * to the specified @p cmp_func, the behavior is undefined. 509 */
550 * 510 #define cx_array_insert_unique(array, element, cmp_func) \
551 * If the capacity is insufficient to hold the new data, a reallocation 511 cx_array_insert_unique_a(cxDefaultAllocator, array, element, cmp_func)
552 * attempt is made. 512
553 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 513 /**
554 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 514 * Inserts sorted data into a sorted array, skipping duplicates.
555 * 515 *
556 * @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.
557 * @param size a pointer to the size of the target array 517 *
558 * @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.
559 * @param cmp_func the compare function for the elements 519 *
560 * @param src the source array 520 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
561 * @param elem_size the size of one element 521 * @param array the name of the array where the elements shall be inserted
562 * @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
563 * @param reallocator the array reallocator to use 523 * @param n (@c size_t) the number of elements that shall be inserted
564 * (@c NULL defaults to #cx_array_default_reallocator) 524 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
565 * @retval zero success 525 * @retval zero success
566 * @retval non-zero failure 526 * @retval non-zero a re-allocation was necessary but failed
567 */ 527 */
568 cx_attr_nonnull_arg(1, 2, 3, 5) 528 #define cx_array_insert_unique_array_a(allocator, array, sorted_data, n, cmp_func) \
569 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)
570 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, 530
571 CxArrayReallocator *reallocator); 531 /**
572 532 * Inserts sorted data into a sorted array, skipping duplicates.
573 /** 533 *
574 * 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.
575 * 535 *
576 * 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.
577 * to the specified @p cmp_func, the behavior is undefined. 537 *
578 * 538 * @param array the name of the array where the elements shall be inserted
579 * 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
580 * attempt is made. 540 * @param n (@c size_t) the number of elements that shall be inserted
581 * 541 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
582 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 542 * @retval zero success
583 * It is important, however, that @p size and @p capacity are pointers to 543 * @retval non-zero a re-allocation was necessary but failed
584 * variables of the same type. 544 */
585 * 545 #define cx_array_insert_unique_array(array, sorted_data, n, cmp_func) \
586 * @param target (@c void**) a pointer to the target array 546 cx_array_insert_unique_array_a(cxDefaultAllocator, array, sorted_data, n, cmp_func)
587 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 547
588 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 548 /**
589 * @param elem_size (@c size_t) the size of one element 549 * Inserts sorted data into a sorted array.
590 * @param elem (@c void*) a pointer to the element to add 550 *
591 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 551 * Internal function - do not use.
592 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 552 *
593 * @retval zero success (also when the element was already present) 553 * @param allocator the allocator to use for a possible reallocation
594 * @retval non-zero failure 554 * @param array a pointer to the array structure
595 */ 555 * @param elem_size the size of one element
596 #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
597 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
598 558 * @param cmp_func the compare function
599 /** 559 * @param context additional context for the compare function
600 * Convenience macro for cx_array_add_unique() with a default 560 * @param allow_duplicates @c false if duplicates shall be skipped during insertion
601 * layout and the specified reallocator. 561 * @retval zero success
602 * 562 * @retval non-zero a re-allocation was necessary but failed
603 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 563 */
604 * @param array the name of the array (NOT a pointer or alias to the array) 564 cx_attr_nonnull_arg(1, 2, 4, 6)
605 * @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,
606 * @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,
607 * @retval zero success 567 cx_compare_func2 cmp_func, void *context, bool allow_duplicates);
608 * @retval non-zero failure 568
609 * @see CX_ARRAY_DECLARE() 569 /**
610 * @see cx_array_simple_add_unique() 570 * Inserts an element into a sorted array.
611 */ 571 *
612 #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.
613 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \ 573 *
614 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.
615 575 *
616 /** 576 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
617 * Convenience macro for cx_array_add_unique() with a default 577 * @param array the name of the array where the elements shall be inserted
618 * layout and the default reallocator. 578 * @param element the element that shall be inserted
619 * 579 * @param cmp_func (@c cx_compare_func2) the compare function that establishes the order
620 * @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
621 * @param elem the element to add (NOT a pointer, address is automatically taken) 581 * @retval zero success
622 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 582 * @retval non-zero a re-allocation was necessary but failed
623 * @retval zero success 583 */
624 * @retval non-zero failure 584 #define cx_array_insert_sorted_ca(allocator, array, element, cmp_func) \
625 * @see CX_ARRAY_DECLARE() 585 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (void*)&(element), 1, cmp_func, context, true)
626 * @see cx_array_simple_add_unique_a() 586
627 */ 587 /**
628 #define cx_array_simple_add_unique(array, elem, cmp_func) \ 588 * Inserts an element into a sorted array.
629 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func) 589 *
630 590 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
631 /** 591 *
632 * 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.
633 * layout and the specified reallocator. 593 *
634 * 594 * @param array the name of the array where the elements shall be inserted
635 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 595 * @param element the element that shall be inserted
636 * @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
637 * @param src (@c void*) pointer to the source array 597 * @param context (@c void*) additional context for the compare function
638 * @param n (@c size_t) number of elements in the source array 598 * @retval zero success
639 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 599 * @retval non-zero a re-allocation was necessary but failed
640 * @retval zero success 600 */
641 * @retval non-zero failure 601 #define cx_array_insert_sorted_c(array, element, cmp_func, context) \
642 * @see CX_ARRAY_DECLARE() 602 cx_array_insert_sorted_ca(cxDefaultAllocator, array, element, cmp_func, context)
643 * @see cx_array_simple_insert_unique() 603
644 */ 604 /**
645 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \ 605 * Inserts sorted data into a sorted array.
646 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \ 606 *
647 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.
648 608 *
649 /** 609 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
650 * Convenience macro for cx_array_insert_unique() with a default 610 *
651 * layout and the default reallocator. 611 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
652 * 612 * @param array the name of the array where the elements shall be inserted
653 * @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
654 * @param src (@c void*) pointer to the source array 614 * @param n (@c size_t) the number of elements that shall be inserted
655 * @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
656 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 616 * @param context (@c void*) additional context for the compare function
657 * @retval zero success 617 * @retval zero success
658 * @retval non-zero failure 618 * @retval non-zero a re-allocation was necessary but failed
659 * @see CX_ARRAY_DECLARE() 619 */
660 * @see cx_array_simple_insert_unique_a() 620 #define cx_array_insert_sorted_array_ca(allocator, array, sorted_data, n, cmp_func, context) \
661 */ 621 cx_array_insert_sorted_c_(allocator, (CxArray*)&(array), sizeof((array).data[0]), sorted_data, n, cmp_func, context, true)
662 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \ 622
663 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
664 939
665 /** 940 /**
666 * Searches the largest lower bound in a sorted array. 941 * Searches the largest lower bound in a sorted array.
667 * 942 *
668 * 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
669 * in @p arr that is less or equal to @p elem with respect to @p cmp_func. 944 * in @p arr that is less or equal to @p elem with respect to @p cmp_func.
670 * When no such element exists, @p size is returned. 945 * When no such element exists, @p size is returned.
946 *
947 * When such an element exists more than once, the largest index of all those
948 * elements is returned.
671 * 949 *
672 * If @p elem is contained in the array, this is identical to 950 * If @p elem is contained in the array, this is identical to
673 * #cx_array_binary_search(). 951 * #cx_array_binary_search().
674 * 952 *
675 * If the array is not sorted with respect to the @p cmp_func, the behavior 953 * If the array is not sorted with respect to the @p cmp_func, the behavior
688 CX_EXPORT size_t cx_array_binary_search_inf(const void *arr, size_t size, 966 CX_EXPORT size_t cx_array_binary_search_inf(const void *arr, size_t size,
689 size_t elem_size, const void *elem, cx_compare_func cmp_func); 967 size_t elem_size, const void *elem, cx_compare_func cmp_func);
690 968
691 /** 969 /**
692 * Searches an item in a sorted array. 970 * Searches an item in a sorted array.
971 *
972 * When such an element exists more than once, the largest index of all those
973 * elements is returned.
693 * 974 *
694 * If the array is not sorted with respect to the @p cmp_func, the behavior 975 * If the array is not sorted with respect to the @p cmp_func, the behavior
695 * is undefined. 976 * is undefined.
696 * 977 *
697 * @param arr the array to search 978 * @param arr the array to search
713 * 994 *
714 * In other words, this function returns the index of the smallest element 995 * In other words, this function returns the index of the smallest element
715 * in @p arr that is greater or equal to @p elem with respect to @p cmp_func. 996 * in @p arr that is greater or equal to @p elem with respect to @p cmp_func.
716 * When no such element exists, @p size is returned. 997 * When no such element exists, @p size is returned.
717 * 998 *
999 * When such an element exists more than once, the smallest index of all those
1000 * elements is returned.
1001 *
718 * If @p elem is contained in the array, this is identical to 1002 * If @p elem is contained in the array, this is identical to
719 * #cx_array_binary_search(). 1003 * #cx_array_binary_search().
720 * 1004 *
721 * If the array is not sorted with respect to the @p cmp_func, the behavior 1005 * If the array is not sorted with respect to the @p cmp_func, the behavior
722 * is undefined. 1006 * is undefined.
732 */ 1016 */
733 cx_attr_nonnull 1017 cx_attr_nonnull
734 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,
735 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);
736 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
737 /** 1106 /**
738 * Swaps two array elements. 1107 * Swaps two array elements.
739 * 1108 *
740 * @param arr the array 1109 * @param arr the array
741 * @param elem_size the element size 1110 * @param elem_size the element size
748 /** 1117 /**
749 * 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.
750 * 1119 *
751 * 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
752 * 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
753 * to cx_cmp_ptr(), if none is given. 1122 * to cx_cmp_ptr().
754 * 1123 *
755 * @param allocator the allocator for allocating the list memory 1124 * @param allocator the allocator for allocating the list memory
756 * (if @c NULL, the cxDefaultAllocator will be used) 1125 * (if @c NULL, the cxDefaultAllocator will be used)
757 * @param comparator the comparator for the elements
758 * (if @c NULL, and the list is not storing pointers, sort and find
759 * functions will not work)
760 * @param elem_size the size of each element in bytes 1126 * @param elem_size the size of each element in bytes
761 * @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
762 * @return the created list 1128 * @return the created list
763 */ 1129 */
764 cx_attr_nodiscard 1130 cx_attr_nodiscard
765 cx_attr_malloc 1131 cx_attr_malloc
766 cx_attr_dealloc(cxListFree, 1) 1132 cx_attr_dealloc(cxListFree, 1)
767 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator, 1133 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator,
768 cx_compare_func comparator, size_t elem_size, size_t initial_capacity); 1134 size_t elem_size, size_t initial_capacity);
769
770 /**
771 * Allocates an array list for storing elements with @p elem_size bytes each.
772 *
773 * The list will use the cxDefaultAllocator and @em NO compare function.
774 * If you want to call functions that need a compare function, you have to
775 * set it immediately after creation or use cxArrayListCreate().
776 *
777 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
778 * copies of the added elements and the compare function will be automatically set
779 * to cx_cmp_ptr().
780 *
781 * @param elem_size (@c size_t) the size of each element in bytes
782 * @param initial_capacity (@c size_t) the initial number of elements the array can store
783 * @return the created list
784 */
785 #define cxArrayListCreateSimple(elem_size, initial_capacity) \
786 cxArrayListCreate(NULL, NULL, elem_size, initial_capacity)
787 1135
788 #ifdef __cplusplus 1136 #ifdef __cplusplus
789 } // extern "C" 1137 } // extern "C"
790 #endif 1138 #endif
791 1139

mercurial