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