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