| 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 |