ucx/cx/array_list.h

changeset 1016
ccde46662db7
parent 943
9b5948aa5b90
equal deleted inserted replaced
1015:b459361d98ad 1016:ccde46662db7
48 * a stack buffer when swapped. 48 * a stack buffer when swapped.
49 */ 49 */
50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size; 50 CX_EXPORT extern const unsigned cx_array_swap_sbo_size;
51 51
52 /** 52 /**
53 * Declares variables for an array that can be used with the convenience macros. 53 * Declares a typed array with size and capacity.
54 * 54 *
55 * @par Examples 55 * @param type the type of the elements
56 * @code
57 * // integer array with at most 255 elements
58 * CX_ARRAY_DECLARE_SIZED(int, myarray, uint8_t)
59 *
60 * // array of MyObject* pointers where size and capacity are stored as unsigned int
61 * CX_ARRAY_DECLARE_SIZED(MyObject*, objects, unsigned int)
62 *
63 * // initializing code
64 * cx_array_initialize(myarray, 16); // reserve space for 16
65 * cx_array_initialize(objects, 100); // reserve space for 100
66 * @endcode
67 *
68 * @param type the type of the data
69 * @param name the name of the array 56 * @param name the name of the array
70 * @param size_type the type of the size (should be uint8_t, uint16_t, uint32_t, or size_t) 57 */
71 * 58 #define CX_ARRAY(type, name) \
72 * @see cx_array_initialize() 59 struct { \
73 * @see cx_array_simple_add() 60 type *data; \
74 * @see cx_array_simple_copy() 61 size_t size; \
75 * @see cx_array_simple_add_sorted() 62 size_t capacity; \
76 * @see cx_array_simple_insert_sorted() 63 } name
77 */ 64
78 #define CX_ARRAY_DECLARE_SIZED(type, name, size_type) \ 65 /**
79 type * name; \ 66 * Internal structure for arrays.
80 /** Array size. */ size_type name##_size; \ 67 *
81 /** Array capacity. */ size_type name##_capacity 68 * A generalization of array structures declared with CX_ARRAY().
82 69 */
83 /** 70 typedef struct cx_array_s {
84 * Declares variables for an array that can be used with the convenience macros. 71 /** The array data. */
85 * 72 void *data;
86 * The size and capacity variables will have type @c size_t. 73 /** The number of elements. */
87 * Use #CX_ARRAY_DECLARE_SIZED() to specify a different type. 74 size_t size;
88 * 75 /** The maximum number of elements. */
89 * @par Examples 76 size_t capacity;
90 * @code 77 } CxArray;
91 * // int array 78
92 * CX_ARRAY_DECLARE(int, myarray) 79 /**
93 * 80 * Initializes an array by allocating memory.
94 * // initializing code 81 *
95 * cx_array_initialize(myarray, 32); // reserve space for 32 82 * Internal function - do not use manually.
96 * @endcode 83 *
97 * 84 * @param allocator the allocator for the array
98 * @param type the type of the data 85 * @param array a pointer to the array structure
99 * @param name the name of the array 86 * @param elem_size size of one element
100 * 87 * @param capacity the initial maximum number of elements
101 * @see cx_array_initialize() 88 * @retval zero allocation was successful
102 * @see cx_array_simple_add() 89 * @retval non-zero allocation failed
103 * @see cx_array_simple_copy() 90 */
104 * @see cx_array_simple_add_sorted() 91 cx_attr_nonnull
105 * @see cx_array_simple_insert_sorted() 92 CX_EXPORT int cx_array_init_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
106 */ 93
107 #define CX_ARRAY_DECLARE(type, name) CX_ARRAY_DECLARE_SIZED(type, name, size_t) 94 /**
108 95 * Initializes an array by allocating memory.
109 /** 96 *
110 * Initializes an array with the given capacity. 97 * The size is set to zero.
111 * 98 *
112 * The type of the capacity depends on the type used during declaration. 99 * @attention If the array was already initialized, this will leak memory.
113 * 100 * Use cx_array_reserve() to change the capacity of an initialized array.
114 * @par Examples 101 *
115 * @code 102 * @param allocator (@c CxAllocator*) the allocator for the array
116 * CX_ARRAY_DECLARE_SIZED(int, arr1, uint8_t) 103 * @param array the name of the array
117 * CX_ARRAY_DECLARE(int, arr2) // size and capacity are implicitly size_t 104 * @param capacity (@c size_t) the initial maximum number of elements
118 * 105 * @retval zero allocation was successful
119 * // initializing code 106 * @retval non-zero allocation failed
120 * cx_array_initialize(arr1, 500); // error: maximum for uint8_t is 255 107 */
121 * cx_array_initialize(arr2, 500); // OK 108 #define cx_array_init_a(allocator, array, capacity) cx_array_init_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
122 * @endcode 109
123 * 110 /**
124 * 111 * Initializes an array by allocating memory.
125 * The memory for the array is allocated with the cxDefaultAllocator. 112 *
126 * 113 * The size is set to zero.
127 * @param array the name of the array 114 *
128 * @param capacity the initial capacity 115 * @attention If the array was already initialized, this will leak memory.
129 * @see cx_array_initialize_a() 116 *
130 * @see CX_ARRAY_DECLARE_SIZED() 117 * @param array the name of the array
131 * @see CX_ARRAY_DECLARE() 118 * @param capacity (@c size_t) the initial maximum number of elements
132 */ 119 * @retval zero allocation was successful
133 #define cx_array_initialize(array, capacity) \ 120 * @retval non-zero allocation failed
134 array##_capacity = capacity; \ 121 */
135 array##_size = 0; \ 122 #define cx_array_init(array, capacity) cx_array_init_a(cxDefaultAllocator, array, capacity)
136 array = cxMallocDefault(sizeof(array[0]) * capacity) 123
137 124 /**
138 /** 125 * Initializes an array with fixed size memory.
139 * Initializes an array with the given capacity using the specified allocator. 126 *
140 * 127 * Internal function - do not use manually.
141 * @par Example 128 *
142 * @code 129 * @param array a pointer to the array structure
143 * CX_ARRAY_DECLARE(int, myarray) 130 * @param data the fixed size array
144 * 131 * @param capacity the capacity of the fixed size array
145 * 132 * @param size the number of initialized elements in the fixed size array
146 * const CxAllocator *al = // ... 133 */
147 * cx_array_initialize_a(al, myarray, 128); 134 cx_attr_nonnull
148 * // ... 135 CX_EXPORT void cx_array_init_fixed_(CxArray *array, const void *data, size_t capacity, size_t size);
149 * cxFree(al, myarray); // remember to free with the same allocator 136
150 * @endcode 137 /**
151 * 138 * Initializes an array with fixed size memory.
152 * @param allocator (@c CxAllocator*) the allocator 139 *
153 * @param array the name of the array 140 * This is useful, for example, when you want to work with memory on the stack
154 * @param capacity the initial capacity 141 * and only want to move to the heap when the stack memory is not enough.
155 * @see cx_array_initialize() 142 *
156 * @see CX_ARRAY_DECLARE_SIZED() 143 * With the @p num_initialized argument you can specify how many elements in the
157 * @see CX_ARRAY_DECLARE() 144 * fixed size array are already correctly initialized, which determines the
158 */ 145 * initial size of the array.
159 #define cx_array_initialize_a(allocator, array, capacity) \ 146 *
160 array##_capacity = capacity; \ 147 * The capacity is determined automatically by the compiler.
161 array##_size = 0; \ 148 *
162 array = cxMalloc(allocator, sizeof(array[0]) * capacity) 149 * @attention When you add elements to an array that was initialized with fixed
163 150 * size memory, you MUST check the capacity before adding the element and invoke
164 /** 151 * cx_array_copy_to_new() when you intend to exceed the capacity.
165 * Defines a reallocation mechanism for arrays. 152 *
166 * You can create your own, use cx_array_reallocator(), or 153 * @attention When you pass a pointer to an array that does not have a fixed
167 * use the #cx_array_default_reallocator. 154 * size, the behavior is unspecified.
168 */ 155 *
169 struct cx_array_reallocator_s { 156 * @param array the name of the array to initialize
170 /** 157 * @param fixed_size_array (@c void*) the fixed size array
171 * Reallocates space for the given array. 158 * @param num_initialized (@c size_t) the number of already initialized elements in the fixed size array
172 * 159 * @see cx_array_copy_to_new()
173 * Implementations are not required to free the original array. 160 */
174 * This allows reallocation of static or stack memory by allocating heap memory 161 #define cx_array_init_fixed(array, fixed_size_array, num_initialized) \
175 * and copying the array contents; namely when @c stack_ptr in this struct 162 cx_array_init_fixed_((CxArray*)&(array), fixed_size_array, cx_nmemb(fixed_size_array), num_initialized)
176 * is not @c NULL and @p array equals @c stack_ptr. 163
177 * 164 /**
178 * @param array the array to reallocate 165 * Changes the capacity of an array.
179 * @param old_capacity the old number of elements 166 *
180 * @param new_capacity the new number of elements 167 * Internal function - do not use.
181 * @param elem_size the size of each element 168 *
182 * @param alloc a reference to this allocator 169 * @param allocator the allocator
183 * @return a pointer to the reallocated memory or @c NULL on failure 170 * @param array a pointer to the array structure
184 */ 171 * @param elem_size the size of one element
185 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity, 172 * @param capacity the new capacity
186 size_t elem_size, struct cx_array_reallocator_s *alloc); 173 * @retval zero allocation was successful
187 174 * @retval non-zero allocation failed
188 /** 175 */
189 * The allocator that shall be used for the reallocations. 176 cx_attr_nonnull
190 */ 177 CX_EXPORT int cx_array_reserve_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
191 const CxAllocator *allocator; 178
192 /** 179 /**
193 * Optional pointer to stack memory 180 * Changes the capacity of an array.
194 * if the array is originally located on the stack. 181 *
195 */ 182 * If required, the size is reduced to fit into the new capacity.
196 const void *stack_ptr; 183 *
197 }; 184 * @param allocator (@c CxAllocator*) the allocator for the array
198 185 * @param array the name of the array
199 /** 186 * @param capacity (@c size_t) the new maximum number of elements
200 * Typedef for the array reallocator struct. 187 * @retval zero allocation was successful
201 */ 188 * @retval non-zero allocation failed
202 typedef struct cx_array_reallocator_s CxArrayReallocator; 189 */
203 190 #define cx_array_reserve_a(allocator, array, capacity) \
204 /** 191 cx_array_reserve_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
205 * A default array reallocator that is based on the cxDefaultAllocator. 192
206 */ 193 /**
207 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator; 194 * Changes the capacity of an array.
208 195 *
209 /** 196 * If required, the size is reduced to fit into the new capacity.
210 * Creates a new array reallocator. 197 *
211 * 198 * @param array the name of the array
212 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. 199 * @param capacity (@c size_t) the new maximum number of elements
213 * 200 * @retval zero allocation was successful
214 * When @p stack_ptr is not @c NULL, the reallocator is supposed to be used 201 * @retval non-zero allocation failed
215 * @em only for the specific array initially located at @p stack_ptr. 202 */
216 * When reallocation is needed, the reallocator checks if the array is 203 #define cx_array_reserve(array, capacity) \
217 * still located at @p stack_ptr and copies the contents to the heap. 204 cx_array_reserve_a(cxDefaultAllocator, array, capacity)
218 * 205
219 * @note Invoking this function with both arguments being @c NULL will return a 206 /**
220 * reallocator that behaves like #cx_array_default_reallocator. 207 * Copies the array to a new memory region.
221 * 208 *
222 * @param allocator the allocator this reallocator shall be based on 209 * Internal function - do not use.
223 * @param stack_ptr the address of the array when the array is initially located 210 *
224 * on the stack or shall not reallocate in place 211 * @param allocator the allocator for new new memory
225 * @return an array reallocator 212 * @param array a pointer to the array structure
226 */ 213 * @param elem_size the size of one element
227 CX_EXPORT CxArrayReallocator cx_array_reallocator( 214 * @param capacity the new capacity
228 const struct cx_allocator_s *allocator, const void *stack_ptr); 215 * @retval zero allocation was successful
229 216 * @retval non-zero allocation failed
230 /** 217 */
231 * Reserves memory for additional elements. 218 cx_attr_nonnull
232 * 219 CX_EXPORT int cx_array_copy_to_new_(const CxAllocator *allocator, CxArray *array, size_t elem_size, size_t capacity);
233 * This function checks if the @p capacity of the array is sufficient to hold 220
234 * at least @p size plus @p elem_count elements. If not, a reallocation is 221 /**
235 * performed with the specified @p reallocator. 222 * Copies the array to a new memory region.
236 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 223 *
237 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 224 * This is useful when you have initialized the array with a fixed size memory
238 * 225 * using cx_array_init_fixed(), and now you want to increase the capacity.
239 * This function can be useful to replace subsequent calls to cx_array_copy() 226 *
240 * with one single cx_array_reserve() and then - after guaranteeing a 227 * @attention When the original memory does not belong to stack memory, and
241 * sufficient capacity - use simple memmove() or memcpy(). 228 * you do not have another reference to this memory, it will leak.
242 * 229 *
243 * The @p width in bytes refers to the size and capacity. 230 * @param allocator (@c CxAllocator*) the allocator for the new memory
244 * Both must have the same width. 231 * @param array the name of the array
245 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit 232 * @param capacity (@c size_t) the new maximum number of elements
246 * architecture. If set to zero, the native word width is used. 233 * @retval zero allocation was successful
247 * 234 * @retval non-zero allocation failed
248 * @note This function will reserve the minimum required capacity to hold 235 * @see cx_array_init_fixed()
249 * the additional elements and does not perform an overallocation. 236 */
250 * 237 #define cx_array_copy_to_new_a(allocator, array, capacity) \
251 * @param array a pointer to the target array 238 cx_array_copy_to_new_(allocator, (CxArray*)&(array), sizeof((array).data[0]), capacity)
252 * @param size a pointer to the size of the array 239
253 * @param capacity a pointer to the capacity of the array 240 /**
254 * @param width the width in bytes for the @p size and @p capacity or zero for default 241 * Copies the array to a new memory region.
255 * @param elem_size the size of one element 242 *
256 * @param elem_count the number of expected additional elements 243 * This is useful when you have initialized the array with a fixed size memory
257 * @param reallocator the array reallocator to use 244 * using cx_array_init_fixed(), and now you want to increase the capacity.
258 * (@c NULL defaults to #cx_array_default_reallocator) 245 *
259 * @retval zero success 246 * @attention When the original memory does not belong to stack memory, and
260 * @retval non-zero failure 247 * you do not have another reference to this memory, it will leak.
261 * @see cx_array_reallocator() 248 *
262 */ 249 * @param array the name of the array
263 cx_attr_nonnull_arg(1, 2, 3) 250 * @param capacity (@c size_t) the new maximum number of elements
264 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, 251 * @retval zero allocation was successful
265 unsigned width, size_t elem_size, size_t elem_count, 252 * @retval non-zero allocation failed
266 CxArrayReallocator *reallocator); 253 * @see cx_array_init_fixed()
267 254 */
268 /** 255 #define cx_array_copy_to_new(array, capacity) \
269 * Copies elements from one array to another. 256 cx_array_copy_to_new_a(cxDefaultAllocator, array, capacity)
270 * 257
271 * The elements are copied to the @p target array at the specified @p index, 258 /**
272 * overwriting possible elements. The @p index does not need to be in range of 259 * Inserts data into an array.
273 * the current array @p size. If the new index plus the number of elements added 260 *
274 * extends the array's size, the remaining @p capacity is used. 261 * Internal function - do not use.
275 * 262 *
276 * If the @p capacity is also insufficient to hold the new data, a reallocation 263 * @param allocator the allocator to use for a possible reallocation
277 * attempt is made with the specified @p reallocator. 264 * @param array a pointer to the array structure
278 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 265 * @param elem_size the size of one element
279 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 266 * @param index the index where to insert the @p other data
280 * 267 * @param other a pointer to an array of data that shall be inserted
281 * The @p width in bytes refers to the size and capacity. 268 * @param n the number of elements that shall be inserted
282 * Both must have the same width. 269 * @retval zero success
283 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit 270 * @retval non-zero a re-allocation was necessary but failed
284 * architecture. If set to zero, the native word width is used. 271 */
285 * 272 cx_attr_nonnull_arg(1, 2)
286 * @note When this function does reallocate the array, it may allocate more 273 CX_EXPORT int cx_array_insert_(const CxAllocator *allocator, CxArray *array,
287 * space than required to avoid further allocations in the near future. 274 size_t elem_size, size_t index, const void *other, size_t n);
288 * 275
289 * @param target a pointer to the target array 276 /**
290 * @param size a pointer to the size of the target array 277 * Appends an element to an array.
291 * @param capacity a pointer to the capacity of the target array 278 *
292 * @param width the width in bytes for the @p size and @p capacity or zero for default 279 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
293 * @param index the index where the copied elements shall be placed 280 *
294 * @param src the source array 281 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
295 * @param elem_size the size of one element 282 * @param array the name of the array where the element shall be added
296 * @param elem_count the number of elements to copy 283 * @param element (@c void*) a pointer to the element that shall be added
297 * @param reallocator the array reallocator to use 284 * @retval zero success
298 * (@c NULL defaults to #cx_array_default_reallocator) 285 * @retval non-zero a re-allocation was necessary but failed
299 * @retval zero success 286 */
300 * @retval non-zero failure 287 #define cx_array_add_a(allocator, array, element) \
301 * @see cx_array_reallocator() 288 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, element, 1)
302 * @see cx_array_reserve() 289
303 */ 290 /**
304 cx_attr_nonnull_arg(1, 2, 3, 6) 291 * Appends an element to an array.
305 CX_EXPORT int cx_array_copy(void **target, void *size, void *capacity, unsigned width, 292 *
306 size_t index, const void *src, size_t elem_size, size_t elem_count, 293 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
307 CxArrayReallocator *reallocator); 294 *
308 295 * @param array the name of the array where the element shall be added
309 /** 296 * @param element (@c void*) a pointer to the element that shall be added
310 * Convenience macro that uses cx_array_copy() with a default layout and 297 * @retval zero success
311 * the specified reallocator. 298 * @retval non-zero a re-allocation was necessary but failed
312 * 299 */
313 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 300 #define cx_array_add(array, element) \
314 * @param array the name of the array (NOT a pointer or alias to the array) 301 cx_array_add_a(cxDefaultAllocator, array, element)
315 * @param index (@c size_t) the index where the copied elements shall be placed 302
316 * @param src (@c void*) the source array 303 /**
317 * @param count (@c size_t) the number of elements to copy 304 * Inserts an element into an array.
318 * @retval zero success 305 *
319 * @retval non-zero failure 306 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
320 * @see CX_ARRAY_DECLARE() 307 *
321 * @see cx_array_simple_copy() 308 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
322 */ 309 * @param array the name of the array where the element shall be inserted
323 #define cx_array_simple_copy_a(reallocator, array, index, src, count) \ 310 * @param index (@c size_t) the index where to insert the @p element
324 cx_array_copy((void**)&(array), &(array##_size), &(array##_capacity), \ 311 * @param element (@c void*) a pointer to the element that shall be inserted
325 sizeof(array##_size), index, src, sizeof((array)[0]), count, \ 312 * @retval zero success
326 reallocator) 313 * @retval non-zero a re-allocation was necessary but failed
327 314 */
328 /** 315 #define cx_array_insert_a(allocator, array, index, element) \
329 * Convenience macro that uses cx_array_copy() with a default layout and 316 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, element, 1)
330 * the default reallocator. 317
331 * 318 /**
332 * @param array the name of the array (NOT a pointer or alias to the array) 319 * Inserts an element into an array.
333 * @param index (@c size_t) the index where the copied elements shall be placed 320 *
334 * @param src (@c void*) the source array 321 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
335 * @param count (@c size_t) the number of elements to copy 322 *
336 * @retval zero success 323 * @param array the name of the array where the element shall be inserted
337 * @retval non-zero failure 324 * @param index (@c size_t) the index where to insert the @p element
338 * @see CX_ARRAY_DECLARE() 325 * @param element (@c void*) a pointer to the element that shall be inserted
339 * @see cx_array_simple_copy_a() 326 * @retval zero success
340 */ 327 * @retval non-zero a re-allocation was necessary but failed
341 #define cx_array_simple_copy(array, index, src, count) \ 328 */
342 cx_array_simple_copy_a(NULL, array, index, src, count) 329 #define cx_array_insert(array, index, element) \
343 330 cx_array_insert_a(cxDefaultAllocator, array, index, element)
344 /** 331
345 * Convenience macro that uses cx_array_reserve() with a default layout and 332 /**
346 * the specified reallocator. 333 * Inserts data into an array.
347 * 334 *
348 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 335 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
349 * @param array the name of the array (NOT a pointer or alias to the array) 336 *
350 * @param count (@c size_t) the number of expected @em additional elements 337 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
351 * @retval zero success 338 * @param array the name of the array where the elements shall be inserted
352 * @retval non-zero failure 339 * @param index (@c size_t) the index where to insert the @p other data
353 * @see CX_ARRAY_DECLARE() 340 * @param other (@c void*) a pointer to an array of data that shall be inserted
354 * @see cx_array_simple_reserve() 341 * @param n (@c size_t) the number of elements that shall be inserted
355 */ 342 * @retval zero success
356 #define cx_array_simple_reserve_a(reallocator, array, count) \ 343 * @retval non-zero a re-allocation was necessary but failed
357 cx_array_reserve((void**)&(array), &(array##_size), &(array##_capacity), \ 344 */
358 sizeof(array##_size), sizeof((array)[0]), count, \ 345 #define cx_array_insert_array_a(allocator, array, index, other, n) \
359 reallocator) 346 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), index, other, n)
360 347
361 /** 348 /**
362 * Convenience macro that uses cx_array_reserve() with a default layout and 349 * Inserts data into an array.
363 * the default reallocator. 350 *
364 * 351 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
365 * @param array the name of the array (NOT a pointer or alias to the array) 352 *
366 * @param count (@c size_t) the number of expected additional elements 353 * @param array the name of the array where the elements shall be inserted
367 * @retval zero success 354 * @param index (@c size_t) the index where to insert the @p other data
368 * @retval non-zero failure 355 * @param other (@c void*) a pointer to an array of data that shall be inserted
369 * @see CX_ARRAY_DECLARE() 356 * @param n (@c size_t) the number of elements that shall be inserted
370 * @see cx_array_simple_reserve_a() 357 * @retval zero success
371 */ 358 * @retval non-zero a re-allocation was necessary but failed
372 #define cx_array_simple_reserve(array, count) \ 359 */
373 cx_array_simple_reserve_a(NULL, array, count) 360 #define cx_array_insert_array(array, index, other, n) \
374 361 cx_array_insert_array_a(cxDefaultAllocator, array, index, other, n)
375 /** 362
376 * Adds an element to an array with the possibility of allocating more space. 363 /**
377 * 364 * Appends data to an array.
378 * The element @p elem is added to the end of the @p target array which contains 365 *
379 * @p size elements, already. The @p capacity must point to a variable denoting 366 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
380 * the current maximum number of elements the array can hold. 367 *
381 * 368 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
382 * If the capacity is insufficient to hold the new element, an attempt to 369 * @param array the name of the array where the elements shall be added
383 * increase the @p capacity is made and the new capacity is written back. 370 * @param other (@c void*) a pointer to an array of data that shall be added
384 * 371 * @param n (@c size_t) the number of elements that shall be added
385 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 372 * @retval zero success
386 * It is important, however, that @p size and @p capacity are pointers to 373 * @retval non-zero a re-allocation was necessary but failed
387 * variables of the same type. 374 */
388 * 375 #define cx_array_add_array_a(allocator, array, other, n) \
389 * @param target (@c void**) a pointer to the target array 376 cx_array_insert_(allocator, (CxArray*)&(array), sizeof((array).data[0]), (array).size, other, n)
390 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 377
391 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 378 /**
392 * @param elem_size (@c size_t) the size of one element 379 * Appends data to an array.
393 * @param elem (@c void*) a pointer to the element to add 380 *
394 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 381 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
395 * @retval zero success 382 *
396 * @retval non-zero failure 383 * @param array the name of the array where the elements shall be added
397 */ 384 * @param other (@c void*) a pointer to an array of data that shall be added
398 #define cx_array_add(target, size, capacity, elem_size, elem, reallocator) \ 385 * @param n (@c size_t) the number of elements that shall be added
399 cx_array_copy((void**)(target), size, capacity, sizeof(*(size)), \ 386 * @retval zero success
400 *(size), elem, elem_size, 1, reallocator) 387 * @retval non-zero a re-allocation was necessary but failed
401 388 */
402 /** 389 #define cx_array_add_array(array, other, n) \
403 * Convenience macro that uses cx_array_add() with a default layout and 390 cx_array_add_array_a(cxDefaultAllocator, array, other, n)
404 * the specified reallocator. 391
405 * 392 /**
406 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 393 * Inserts sorted data into a sorted array.
407 * @param array the name of the array (NOT a pointer or alias to the array) 394 *
408 * @param elem the element to add (NOT a pointer, address is automatically taken) 395 * Internal function - do not use.
409 * @retval zero success 396 *
410 * @retval non-zero failure 397 * @param allocator the allocator to use for a possible reallocation
411 * @see CX_ARRAY_DECLARE() 398 * @param array a pointer to the array structure
412 * @see cx_array_simple_add() 399 * @param elem_size the size of one element
413 */ 400 * @param cmp_func
414 #define cx_array_simple_add_a(reallocator, array, elem) \ 401 * @param sorted_data a pointer to an array of data that shall be inserted
415 cx_array_simple_copy_a(reallocator, array, array##_size, &(elem), 1) 402 * @param n the number of elements that shall be inserted
416 403 * @param allow_duplicates @c false if duplicates shall be skipped during insertion
417 /** 404 * @retval zero success
418 * Convenience macro that uses cx_array_add() with a default layout and 405 * @retval non-zero a re-allocation was necessary but failed
419 * the default reallocator. 406 */
420 * 407 cx_attr_nonnull
421 * @param array the name of the array (NOT a pointer or alias to the array) 408 CX_EXPORT int cx_array_insert_sorted_(const CxAllocator *allocator, CxArray *array,
422 * @param elem the element to add (NOT a pointer, address is automatically taken) 409 size_t elem_size, cx_compare_func cmp_func, const void *sorted_data, size_t n,
423 * @retval zero success 410 bool allow_duplicates);
424 * @retval non-zero failure
425 * @see CX_ARRAY_DECLARE()
426 * @see cx_array_simple_add_a()
427 */
428 #define cx_array_simple_add(array, elem) \
429 cx_array_simple_add_a(cx_array_default_reallocator, array, elem)
430
431 /**
432 * Inserts a sorted array into another sorted array.
433 *
434 * If either the target or the source array is not already sorted with respect
435 * to the specified @p cmp_func, the behavior is undefined.
436 *
437 * If the capacity is insufficient to hold the new data, a reallocation
438 * attempt is made.
439 * You can create your own reallocator by hand, use #cx_array_default_reallocator,
440 * or use the convenience function cx_array_reallocator() to create a custom reallocator.
441 *
442 * @param target a pointer to the target array
443 * @param size a pointer to the size of the target array
444 * @param capacity a pointer to the capacity of the target array
445 * @param cmp_func the compare function for the elements
446 * @param src the source array
447 * @param elem_size the size of one element
448 * @param elem_count the number of elements to insert
449 * @param reallocator the array reallocator to use
450 * (@c NULL defaults to #cx_array_default_reallocator)
451 * @retval zero success
452 * @retval non-zero failure
453 */
454 cx_attr_nonnull_arg(1, 2, 3, 5)
455 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity,
456 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count,
457 CxArrayReallocator *reallocator);
458 411
459 /** 412 /**
460 * Inserts an element into a sorted array. 413 * Inserts an element into a sorted array.
461 * 414 *
462 * If the target array is not already sorted with respect 415 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
463 * to the specified @p cmp_func, the behavior is undefined. 416 *
464 * 417 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
465 * If the capacity is not enough to hold the new data, a reallocation 418 *
466 * attempt is made. 419 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
467 * 420 * @param array the name of the array where the elements shall be inserted
468 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 421 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
469 * It is important, however, that @p size and @p capacity are pointers to 422 * @param element (@c void*) a pointer to element that shall be inserted
470 * variables of the same type. 423 * @retval zero success
471 * 424 * @retval non-zero a re-allocation was necessary but failed
472 * @param target (@c void**) a pointer to the target array 425 */
473 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 426 #define cx_array_insert_sorted_a(allocator, array, cmp_func, element) \
474 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 427 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, true)
475 * @param elem_size (@c size_t) the size of one element 428
476 * @param elem (@c void*) a pointer to the element to add 429 /**
477 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 430 * Inserts an element into a sorted array.
478 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 431 *
479 * @retval zero success 432 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
480 * @retval non-zero failure 433 *
481 */ 434 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
482 #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ 435 *
483 cx_array_insert_sorted((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) 436 * @param array the name of the array where the elements shall be inserted
484 437 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
485 /** 438 * @param element (@c void*) a pointer to element that shall be inserted
486 * Convenience macro for cx_array_add_sorted() with a default 439 * @retval zero success
487 * layout and the specified reallocator. 440 * @retval non-zero a re-allocation was necessary but failed
488 * 441 */
489 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 442 #define cx_array_insert_sorted(array, cmp_func, element) \
490 * @param array the name of the array (NOT a pointer or alias to the array) 443 cx_array_insert_sorted_a(cxDefaultAllocator, array, cmp_func, element)
491 * @param elem the element to add (NOT a pointer, address is automatically taken) 444
492 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 445 /**
493 * @retval zero success 446 * Inserts sorted data into a sorted array.
494 * @retval non-zero failure 447 *
495 * @see CX_ARRAY_DECLARE() 448 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
496 * @see cx_array_simple_add_sorted() 449 *
497 */ 450 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
498 #define cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) \ 451 *
499 cx_array_add_sorted(&array, &(array##_size), &(array##_capacity), \ 452 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
500 sizeof((array)[0]), &(elem), cmp_func, reallocator) 453 * @param array the name of the array where the elements shall be inserted
501 454 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
502 /** 455 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
503 * Convenience macro for cx_array_add_sorted() with a default 456 * @param n (@c size_t) the number of elements that shall be inserted
504 * layout and the default reallocator. 457 * @retval zero success
505 * 458 * @retval non-zero a re-allocation was necessary but failed
506 * @param array the name of the array (NOT a pointer or alias to the array) 459 */
507 * @param elem the element to add (NOT a pointer, address is automatically taken) 460 #define cx_array_insert_sorted_array_a(allocator, array, cmp_func, sorted_data, n) \
508 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 461 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, true)
509 * @retval zero success 462
510 * @retval non-zero failure 463 /**
511 * @see CX_ARRAY_DECLARE() 464 * Inserts sorted data into a sorted array.
512 * @see cx_array_simple_add_sorted_a() 465 *
513 */ 466 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
514 #define cx_array_simple_add_sorted(array, elem, cmp_func) \ 467 *
515 cx_array_simple_add_sorted_a(NULL, array, elem, cmp_func) 468 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
516 469 *
517 /** 470 * @param array the name of the array where the elements shall be inserted
518 * Convenience macro for cx_array_insert_sorted() with a default 471 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
519 * layout and the specified reallocator. 472 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
520 * 473 * @param n (@c size_t) the number of elements that shall be inserted
521 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 474 * @retval zero success
522 * @param array the name of the array (NOT a pointer or alias to the array) 475 * @retval non-zero a re-allocation was necessary but failed
523 * @param src (@c void*) pointer to the source array 476 */
524 * @param n (@c size_t) number of elements in the source array 477 #define cx_array_insert_sorted_array(array, cmp_func, sorted_data, n) \
525 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 478 cx_array_insert_sorted_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n)
526 * @retval zero success 479
527 * @retval non-zero failure 480 /**
528 * @see CX_ARRAY_DECLARE() 481 * Inserts an element into a sorted array if it is not already contained.
529 * @see cx_array_simple_insert_sorted() 482 *
530 */ 483 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
531 #define cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) \ 484 *
532 cx_array_insert_sorted((void**)(&array), &(array##_size), &(array##_capacity), \ 485 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
533 cmp_func, src, sizeof((array)[0]), n, reallocator) 486 *
534 487 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
535 /** 488 * @param array the name of the array where the elements shall be inserted
536 * Convenience macro for cx_array_insert_sorted() with a default 489 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
537 * layout and the default reallocator. 490 * @param element (@c void*) a pointer to element that shall be inserted
538 * 491 * @retval zero success
539 * @param array the name of the array (NOT a pointer or alias to the array) 492 * @retval non-zero a re-allocation was necessary but failed
540 * @param src (@c void*) pointer to the source array 493 */
541 * @param n (@c size_t) number of elements in the source array 494 #define cx_array_insert_unique_a(allocator, array, cmp_func, element) \
542 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 495 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, element, 1, false)
543 * @retval zero success 496
544 * @retval non-zero failure 497 /**
545 * @see CX_ARRAY_DECLARE() 498 * Inserts an element into a sorted array if it is not already contained.
546 * @see cx_array_simple_insert_sorted_a() 499 *
547 */ 500 * When the capacity is not enough to hold the new element, a re-allocation is attempted.
548 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ 501 *
549 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func) 502 * @attention if the array is not sorted according to the specified @p cmp_func, the behavior is undefined.
550 503 *
551 504 * @param array the name of the array where the elements shall be inserted
552 /** 505 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
553 * Inserts a sorted array into another sorted array, avoiding duplicates. 506 * @param element (@c void*) a pointer to element that shall be inserted
554 * 507 * @retval zero success
555 * If either the target or the source array is not already sorted with respect 508 * @retval non-zero a re-allocation was necessary but failed
556 * to the specified @p cmp_func, the behavior is undefined. 509 */
557 * 510 #define cx_array_insert_unique(array, cmp_func, element) \
558 * If the capacity is insufficient to hold the new data, a reallocation 511 cx_array_insert_unique_a(cxDefaultAllocator, array, cmp_func, element)
559 * attempt is made. 512
560 * You can create your own reallocator by hand, use #cx_array_default_reallocator, 513 /**
561 * or use the convenience function cx_array_reallocator() to create a custom reallocator. 514 * Inserts sorted data into a sorted array, skipping duplicates.
562 * 515 *
563 * @param target a pointer to the target array 516 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
564 * @param size a pointer to the size of the target array 517 *
565 * @param capacity a pointer to the capacity of the target array 518 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
566 * @param cmp_func the compare function for the elements 519 *
567 * @param src the source array 520 * @param allocator (@c CxAllocator*) the allocator to use for a possible reallocation
568 * @param elem_size the size of one element 521 * @param array the name of the array where the elements shall be inserted
569 * @param elem_count the number of elements to insert 522 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
570 * @param reallocator the array reallocator to use 523 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
571 * (@c NULL defaults to #cx_array_default_reallocator) 524 * @param n (@c size_t) the number of elements that shall be inserted
572 * @retval zero success 525 * @retval zero success
573 * @retval non-zero failure 526 * @retval non-zero a re-allocation was necessary but failed
574 */ 527 */
575 cx_attr_nonnull_arg(1, 2, 3, 5) 528 #define cx_array_insert_unique_array_a(allocator, array, cmp_func, sorted_data, n) \
576 CX_EXPORT int cx_array_insert_unique(void **target, size_t *size, size_t *capacity, 529 cx_array_insert_sorted_(allocator, (CxArray*)&(array), sizeof((array).data[0]), cmp_func, sorted_data, n, false)
577 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, 530
578 CxArrayReallocator *reallocator); 531 /**
579 532 * Inserts sorted data into a sorted array, skipping duplicates.
580 /** 533 *
581 * Inserts an element into a sorted array if it does not exist. 534 * When the capacity is not enough to hold the new elements, a re-allocation is attempted.
582 * 535 *
583 * If the target array is not already sorted with respect 536 * @attention if either array is not sorted according to the specified @p cmp_func, the behavior is undefined.
584 * to the specified @p cmp_func, the behavior is undefined. 537 *
585 * 538 * @param array the name of the array where the elements shall be inserted
586 * If the capacity is insufficient to hold the new data, a reallocation 539 * @param cmp_func (@c cx_compare_func) the compare function that establishes the order
587 * attempt is made. 540 * @param sorted_data (@c void*) a pointer to an array of sorted data that shall be inserted
588 * 541 * @param n (@c size_t) the number of elements that shall be inserted
589 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. 542 * @retval zero success
590 * It is important, however, that @p size and @p capacity are pointers to 543 * @retval non-zero a re-allocation was necessary but failed
591 * variables of the same type. 544 */
592 * 545 #define cx_array_insert_unique_array(array, cmp_func, sorted_data, n) \
593 * @param target (@c void**) a pointer to the target array 546 cx_array_insert_unique_array_a(cxDefaultAllocator, array, cmp_func, sorted_data, n)
594 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array 547
595 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array 548 /**
596 * @param elem_size (@c size_t) the size of one element 549 * Creates an iterator over the elements of an array.
597 * @param elem (@c void*) a pointer to the element to add 550 *
598 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 551 * Internal function - do not use.
599 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 552 *
600 * @retval zero success (also when the element was already present) 553 * @param array a pointer to the array structure
601 * @retval non-zero failure 554 * @param elem_size the size of one element
602 */ 555 * @return an iterator over the elements
603 #define cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ 556 */
604 cx_array_insert_unique((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) 557 cx_attr_nodiscard cx_attr_nonnull
605 558 CX_EXPORT CxIterator cx_array_iterator_(CxArray *array, size_t elem_size);
606 /** 559
607 * Convenience macro for cx_array_add_unique() with a default 560 /**
608 * layout and the specified reallocator. 561 * Creates an iterator over the elements of an array.
609 * 562 *
610 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 563 * The iterator will yield pointers to the elements.
611 * @param array the name of the array (NOT a pointer or alias to the array) 564 *
612 * @param elem the element to add (NOT a pointer, address is automatically taken) 565 * @param array the name of the array
613 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 566 * @return an iterator over the elements
614 * @retval zero success 567 * @see cx_array_iterator_ptr()
615 * @retval non-zero failure 568 */
616 * @see CX_ARRAY_DECLARE() 569 #define cx_array_iterator(array) \
617 * @see cx_array_simple_add_unique() 570 cx_array_iterator_((CxArray*)&(array), sizeof((array).data[0]))
618 */ 571
619 #define cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) \ 572 /**
620 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \ 573 * Creates an iterator over the elements of an array containing pointers.
621 sizeof((array)[0]), &(elem), cmp_func, reallocator) 574 *
622 575 * Internal function - do not use.
623 /** 576 *
624 * Convenience macro for cx_array_add_unique() with a default 577 * @param array the name of the array
625 * layout and the default reallocator. 578 * @return an iterator over the elements
626 * 579 */
627 * @param array the name of the array (NOT a pointer or alias to the array) 580 cx_attr_nodiscard cx_attr_nonnull
628 * @param elem the element to add (NOT a pointer, address is automatically taken) 581 CX_EXPORT CxIterator cx_array_iterator_ptr_(CxArray *array);
629 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 582
630 * @retval zero success 583 /**
631 * @retval non-zero failure 584 * Creates an iterator over the elements of an array containing pointers.
632 * @see CX_ARRAY_DECLARE() 585 *
633 * @see cx_array_simple_add_unique_a() 586 * The iterator will yield the elements themselves, which are supposed to
634 */ 587 * be pointers.
635 #define cx_array_simple_add_unique(array, elem, cmp_func) \ 588 *
636 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func) 589 * @param array the name of the array
637 590 * @return an iterator over the elements
638 /** 591 * @see cx_array_iterator()
639 * Convenience macro for cx_array_insert_unique() with a default 592 */
640 * layout and the specified reallocator. 593 #define cx_array_iterator_ptr(array) \
641 * 594 cx_array_iterator_ptr_((CxArray*)&(array))
642 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use 595
643 * @param array the name of the array (NOT a pointer or alias to the array) 596 /**
644 * @param src (@c void*) pointer to the source array 597 * Deallocates an array.
645 * @param n (@c size_t) number of elements in the source array 598 *
646 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 599 * Internal function - do not use.
647 * @retval zero success 600 *
648 * @retval non-zero failure 601 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array
649 * @see CX_ARRAY_DECLARE() 602 * @param array a pointer to the array structure
650 * @see cx_array_simple_insert_unique() 603 */
651 */ 604 cx_attr_nonnull
652 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \ 605 CX_EXPORT void cx_array_free_(const CxAllocator *allocator, CxArray *array);
653 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \ 606
654 cmp_func, src, sizeof((array)[0]), n, reallocator) 607 /**
655 608 * Deallocates an array.
656 /** 609 *
657 * Convenience macro for cx_array_insert_unique() with a default 610 * The structure is reset to zero and can be re-initialized with
658 * layout and the default reallocator. 611 * cx_array_inita().
659 * 612 *
660 * @param array the name of the array (NOT a pointer or alias to the array) 613 * @param array the name of the array
661 * @param src (@c void*) pointer to the source array 614 */
662 * @param n (@c size_t) number of elements in the source array 615 #define cx_array_free(array) cx_array_free_(cxDefaultAllocator, (CxArray*)&(array))
663 * @param cmp_func (@c cx_cmp_func) the compare function for the elements 616
664 * @retval zero success 617 /**
665 * @retval non-zero failure 618 * Deallocates an array.
666 * @see CX_ARRAY_DECLARE() 619 *
667 * @see cx_array_simple_insert_unique_a() 620 * The structure is reset to zero and can be re-initialized with
668 */ 621 * cx_array_init_a().
669 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \ 622 *
670 cx_array_simple_insert_unique_a(NULL, array, src, n, cmp_func) 623 * @param allocator (@c CxAllocator*) the allocator which was used to allocate the array
624 * @param array the name of the array
625 */
626 #define cx_array_free_a(allocator, array) cx_array_free_(allocator, (CxArray*)&(array))
627
671 628
672 /** 629 /**
673 * Searches the largest lower bound in a sorted array. 630 * Searches the largest lower bound in a sorted array.
674 * 631 *
675 * In other words, this function returns the index of the largest element 632 * In other words, this function returns the index of the largest element
748 */ 705 */
749 cx_attr_nonnull 706 cx_attr_nonnull
750 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size, 707 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size,
751 size_t elem_size, const void *elem, cx_compare_func cmp_func); 708 size_t elem_size, const void *elem, cx_compare_func cmp_func);
752 709
710
711 /**
712 * Searches the largest lower bound in a sorted array.
713 *
714 * In other words, this function returns the index of the largest element
715 * in @p arr that is less or equal to @p elem with respect to @p cmp_func.
716 * When no such element exists, @p size is returned.
717 *
718 * When such an element exists more than once, the largest index of all those
719 * elements is returned.
720 *
721 * If @p elem is contained in the array, this is identical to
722 * #cx_array_binary_search().
723 *
724 * If the array is not sorted with respect to the @p cmp_func, the behavior
725 * is undefined.
726 *
727 * @param arr the array to search
728 * @param size the size of the array
729 * @param elem_size the size of one element
730 * @param elem the element to find
731 * @param cmp_func the compare function
732 * @param context the context for the compare function
733 * @return the index of the largest lower bound, or @p size
734 * @see cx_array_binary_search_sup()
735 * @see cx_array_binary_search()
736 */
737 cx_attr_nonnull
738 CX_EXPORT size_t cx_array_binary_search_inf_c(const void *arr, size_t size,
739 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
740
741 /**
742 * Searches an item in a sorted array.
743 *
744 * When such an element exists more than once, the largest index of all those
745 * elements is returned.
746 *
747 * If the array is not sorted with respect to the @p cmp_func, the behavior
748 * is undefined.
749 *
750 * @param arr the array to search
751 * @param size the size of the array
752 * @param elem_size the size of one element
753 * @param elem the element to find
754 * @param cmp_func the compare function
755 * @param context the context for the compare function
756 * @return the index of the element in the array, or @p size if the element
757 * cannot be found
758 * @see cx_array_binary_search_inf()
759 * @see cx_array_binary_search_sup()
760 */
761 cx_attr_nonnull
762 CX_EXPORT size_t cx_array_binary_search_c(const void *arr, size_t size,
763 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
764
765 /**
766 * Searches the smallest upper bound in a sorted array.
767 *
768 * In other words, this function returns the index of the smallest element
769 * in @p arr that is greater or equal to @p elem with respect to @p cmp_func.
770 * When no such element exists, @p size is returned.
771 *
772 * When such an element exists more than once, the smallest index of all those
773 * elements is returned.
774 *
775 * If @p elem is contained in the array, this is identical to
776 * #cx_array_binary_search().
777 *
778 * If the array is not sorted with respect to the @p cmp_func, the behavior
779 * is undefined.
780 *
781 * @param arr the array to search
782 * @param size the size of the array
783 * @param elem_size the size of one element
784 * @param elem the element to find
785 * @param cmp_func the compare function
786 * @param context the context for the compare function
787 * @return the index of the smallest upper bound, or @p size
788 * @see cx_array_binary_search_inf()
789 * @see cx_array_binary_search()
790 */
791 cx_attr_nonnull
792 CX_EXPORT size_t cx_array_binary_search_sup_c(const void *arr, size_t size,
793 size_t elem_size, const void *elem, cx_compare_func2 cmp_func, void *context);
794
753 /** 795 /**
754 * Swaps two array elements. 796 * Swaps two array elements.
755 * 797 *
756 * @param arr the array 798 * @param arr the array
757 * @param elem_size the element size 799 * @param elem_size the element size
764 /** 806 /**
765 * Allocates an array list for storing elements with @p elem_size bytes each. 807 * Allocates an array list for storing elements with @p elem_size bytes each.
766 * 808 *
767 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of 809 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
768 * copies of the added elements, and the compare function will be automatically set 810 * copies of the added elements, and the compare function will be automatically set
769 * to cx_cmp_ptr(), if none is given. 811 * to cx_cmp_ptr().
770 * 812 *
771 * @param allocator the allocator for allocating the list memory 813 * @param allocator the allocator for allocating the list memory
772 * (if @c NULL, the cxDefaultAllocator will be used) 814 * (if @c NULL, the cxDefaultAllocator will be used)
773 * @param comparator the comparator for the elements
774 * (if @c NULL, and the list is not storing pointers, sort and find
775 * functions will not work)
776 * @param elem_size the size of each element in bytes 815 * @param elem_size the size of each element in bytes
777 * @param initial_capacity the initial number of elements the array can store 816 * @param initial_capacity the initial number of elements the array can store
778 * @return the created list 817 * @return the created list
779 */ 818 */
780 cx_attr_nodiscard 819 cx_attr_nodiscard
781 cx_attr_malloc 820 cx_attr_malloc
782 cx_attr_dealloc(cxListFree, 1) 821 cx_attr_dealloc(cxListFree, 1)
783 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator, 822 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator,
784 cx_compare_func comparator, size_t elem_size, size_t initial_capacity); 823 size_t elem_size, size_t initial_capacity);
785
786 /**
787 * Allocates an array list for storing elements with @p elem_size bytes each.
788 *
789 * The list will use the cxDefaultAllocator and @em NO compare function.
790 * If you want to call functions that need a compare function, you have to
791 * set it immediately after creation or use cxArrayListCreate().
792 *
793 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
794 * copies of the added elements and the compare function will be automatically set
795 * to cx_cmp_ptr().
796 *
797 * @param elem_size (@c size_t) the size of each element in bytes
798 * @param initial_capacity (@c size_t) the initial number of elements the array can store
799 * @return the created list
800 */
801 #define cxArrayListCreateSimple(elem_size, initial_capacity) \
802 cxArrayListCreate(NULL, NULL, elem_size, initial_capacity)
803 824
804 #ifdef __cplusplus 825 #ifdef __cplusplus
805 } // extern "C" 826 } // extern "C"
806 #endif 827 #endif
807 828

mercurial