| 170 struct cx_array_reallocator_s { |
169 struct cx_array_reallocator_s { |
| 171 /** |
170 /** |
| 172 * Reallocates space for the given array. |
171 * Reallocates space for the given array. |
| 173 * |
172 * |
| 174 * Implementations are not required to free the original array. |
173 * Implementations are not required to free the original array. |
| 175 * This allows reallocation of static memory by allocating heap memory |
174 * This allows reallocation of static or stack memory by allocating heap memory |
| 176 * and copying the array contents. The information in the custom fields of |
175 * and copying the array contents; namely when @c stack_ptr in this struct |
| 177 * the referenced allocator can be used to track the state of the memory |
176 * is not @c NULL and @p array equals @c stack_ptr. |
| 178 * or to transport other additional data. |
|
| 179 * |
177 * |
| 180 * @param array the array to reallocate |
178 * @param array the array to reallocate |
| 181 * @param old_capacity the old number of elements |
179 * @param old_capacity the old number of elements |
| 182 * @param new_capacity the new number of elements |
180 * @param new_capacity the new number of elements |
| 183 * @param elem_size the size of each element |
181 * @param elem_size the size of each element |
| 184 * @param alloc a reference to this allocator |
182 * @param alloc a reference to this allocator |
| 185 * @return a pointer to the reallocated memory or @c NULL on failure |
183 * @return a pointer to the reallocated memory or @c NULL on failure |
| 186 */ |
184 */ |
| 187 cx_attr_nodiscard |
185 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity, |
| 188 cx_attr_nonnull_arg(5) |
186 size_t elem_size, struct cx_array_reallocator_s *alloc); |
| 189 cx_attr_allocsize(3, 4) |
|
| 190 void *(*realloc)( |
|
| 191 void *array, |
|
| 192 size_t old_capacity, |
|
| 193 size_t new_capacity, |
|
| 194 size_t elem_size, |
|
| 195 struct cx_array_reallocator_s *alloc |
|
| 196 ); |
|
| 197 |
187 |
| 198 /** |
188 /** |
| 199 * Custom data pointer. |
189 * The allocator that shall be used for the reallocations. |
| 200 */ |
190 */ |
| 201 void *ptr1; |
191 const CxAllocator *allocator; |
| 202 /** |
192 /** |
| 203 * Custom data pointer. |
193 * Optional pointer to stack memory |
| |
194 * if the array is originally located on the stack. |
| 204 */ |
195 */ |
| 205 void *ptr2; |
196 const void *stack_ptr; |
| 206 /** |
|
| 207 * Custom data integer. |
|
| 208 */ |
|
| 209 size_t int1; |
|
| 210 /** |
|
| 211 * Custom data integer. |
|
| 212 */ |
|
| 213 size_t int2; |
|
| 214 }; |
197 }; |
| 215 |
198 |
| 216 /** |
199 /** |
| 217 * Typedef for the array reallocator struct. |
200 * Typedef for the array reallocator struct. |
| 218 */ |
201 */ |
| 219 typedef struct cx_array_reallocator_s CxArrayReallocator; |
202 typedef struct cx_array_reallocator_s CxArrayReallocator; |
| 220 |
203 |
| 221 /** |
204 /** |
| 222 * A default array reallocator that is based on the cxDefaultAllocator. |
205 * A default array reallocator that is based on the cxDefaultAllocator. |
| 223 */ |
206 */ |
| 224 cx_attr_export |
207 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator; |
| 225 extern CxArrayReallocator *cx_array_default_reallocator; |
|
| 226 |
208 |
| 227 /** |
209 /** |
| 228 * Creates a new array reallocator. |
210 * Creates a new array reallocator. |
| 229 * |
211 * |
| 230 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. |
212 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. |
| 231 * |
213 * |
| 232 * When @p stackmem is not @c NULL, the reallocator is supposed to be used |
214 * When @p stack_ptr is not @c NULL, the reallocator is supposed to be used |
| 233 * @em only for the specific array that is initially located at @p stackmem. |
215 * @em only for the specific array initially located at @p stack_ptr. |
| 234 * When reallocation is needed, the reallocator checks, if the array is |
216 * When reallocation is needed, the reallocator checks if the array is |
| 235 * still located at @p stackmem and copies the contents to the heap. |
217 * still located at @p stack_ptr and copies the contents to the heap. |
| 236 * |
218 * |
| 237 * @note Invoking this function with both arguments @c NULL will return a |
219 * @note Invoking this function with both arguments being @c NULL will return a |
| 238 * reallocator that behaves like #cx_array_default_reallocator. |
220 * reallocator that behaves like #cx_array_default_reallocator. |
| 239 * |
221 * |
| 240 * @param allocator the allocator this reallocator shall be based on |
222 * @param allocator the allocator this reallocator shall be based on |
| 241 * @param stackmem the address of the array when the array is initially located |
223 * @param stack_ptr the address of the array when the array is initially located |
| 242 * on the stack or shall not reallocated in place |
224 * on the stack or shall not reallocate in place |
| 243 * @return an array reallocator |
225 * @return an array reallocator |
| 244 */ |
226 */ |
| 245 cx_attr_export |
227 CX_EXPORT CxArrayReallocator cx_array_reallocator( |
| 246 CxArrayReallocator cx_array_reallocator( |
228 const struct cx_allocator_s *allocator, const void *stack_ptr); |
| 247 const struct cx_allocator_s *allocator, |
|
| 248 const void *stackmem |
|
| 249 ); |
|
| 250 |
229 |
| 251 /** |
230 /** |
| 252 * Reserves memory for additional elements. |
231 * Reserves memory for additional elements. |
| 253 * |
232 * |
| 254 * This function checks if the @p capacity of the array is sufficient to hold |
233 * This function checks if the @p capacity of the array is sufficient to hold |
| 277 * @retval zero success |
256 * @retval zero success |
| 278 * @retval non-zero failure |
257 * @retval non-zero failure |
| 279 * @see cx_array_reallocator() |
258 * @see cx_array_reallocator() |
| 280 */ |
259 */ |
| 281 cx_attr_nonnull_arg(1, 2, 3) |
260 cx_attr_nonnull_arg(1, 2, 3) |
| 282 cx_attr_export |
261 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, |
| 283 int cx_array_reserve( |
262 unsigned width, size_t elem_size, size_t elem_count, |
| 284 void **array, |
263 CxArrayReallocator *reallocator); |
| 285 void *size, |
|
| 286 void *capacity, |
|
| 287 unsigned width, |
|
| 288 size_t elem_size, |
|
| 289 size_t elem_count, |
|
| 290 CxArrayReallocator *reallocator |
|
| 291 ); |
|
| 292 |
264 |
| 293 /** |
265 /** |
| 294 * Copies elements from one array to another. |
266 * Copies elements from one array to another. |
| 295 * |
267 * |
| 296 * The elements are copied to the @p target array at the specified @p index, |
268 * The elements are copied to the @p target array at the specified @p index, |
| 297 * overwriting possible elements. The @p index does not need to be in range of |
269 * overwriting possible elements. The @p index does not need to be in range of |
| 298 * the current array @p size. If the new index plus the number of elements added |
270 * the current array @p size. If the new index plus the number of elements added |
| 299 * would extend the array's size, the remaining @p capacity is used. |
271 * extends the array's size, the remaining @p capacity is used. |
| 300 * |
272 * |
| 301 * If the @p capacity is also insufficient to hold the new data, a reallocation |
273 * If the @p capacity is also insufficient to hold the new data, a reallocation |
| 302 * attempt is made with the specified @p reallocator. |
274 * attempt is made with the specified @p reallocator. |
| 303 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
275 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
| 304 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
276 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
| 305 * |
277 * |
| 306 * The @p width in bytes refers to the size and capacity. |
278 * The @p width in bytes refers to the size and capacity. |
| 307 * Both must have the same width. |
279 * Both must have the same width. |
| 308 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64 bit |
280 * Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit |
| 309 * architecture. If set to zero, the native word width is used. |
281 * architecture. If set to zero, the native word width is used. |
| 310 * |
282 * |
| 311 * @param target a pointer to the target array |
283 * @param target a pointer to the target array |
| 312 * @param size a pointer to the size of the target array |
284 * @param size a pointer to the size of the target array |
| 313 * @param capacity a pointer to the capacity of the target array |
285 * @param capacity a pointer to the capacity of the target array |
| 480 * (@c NULL defaults to #cx_array_default_reallocator) |
443 * (@c NULL defaults to #cx_array_default_reallocator) |
| 481 * @retval zero success |
444 * @retval zero success |
| 482 * @retval non-zero failure |
445 * @retval non-zero failure |
| 483 */ |
446 */ |
| 484 cx_attr_nonnull_arg(1, 2, 3, 5) |
447 cx_attr_nonnull_arg(1, 2, 3, 5) |
| 485 cx_attr_export |
448 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity, |
| 486 int cx_array_insert_sorted( |
449 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, |
| 487 void **target, |
450 CxArrayReallocator *reallocator); |
| 488 size_t *size, |
|
| 489 size_t *capacity, |
|
| 490 cx_compare_func cmp_func, |
|
| 491 const void *src, |
|
| 492 size_t elem_size, |
|
| 493 size_t elem_count, |
|
| 494 CxArrayReallocator *reallocator |
|
| 495 ); |
|
| 496 |
451 |
| 497 /** |
452 /** |
| 498 * Inserts an element into a sorted array. |
453 * Inserts an element into a sorted array. |
| 499 * |
454 * |
| 500 * If the target array is not already sorted with respect |
455 * If the target array is not already sorted with respect |
| 501 * to the specified @p cmp_func, the behavior is undefined. |
456 * to the specified @p cmp_func, the behavior is undefined. |
| 502 * |
457 * |
| 503 * If the capacity is insufficient to hold the new data, a reallocation |
458 * If the capacity is not enough to hold the new data, a reallocation |
| 504 * attempt is made. |
459 * attempt is made. |
| 505 * |
460 * |
| 506 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
461 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
| 507 * It is important, however, that @p size and @p capacity are pointers to |
462 * It is important, however, that @p size and @p capacity are pointers to |
| 508 * variables of the same type. |
463 * variables of the same type. |
| 583 * @see CX_ARRAY_DECLARE() |
538 * @see CX_ARRAY_DECLARE() |
| 584 * @see cx_array_simple_insert_sorted_a() |
539 * @see cx_array_simple_insert_sorted_a() |
| 585 */ |
540 */ |
| 586 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ |
541 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ |
| 587 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func) |
542 cx_array_simple_insert_sorted_a(NULL, array, src, n, cmp_func) |
| |
543 |
| |
544 |
| |
545 /** |
| |
546 * Inserts a sorted array into another sorted array, avoiding duplicates. |
| |
547 * |
| |
548 * If either the target or the source array is not already sorted with respect |
| |
549 * to the specified @p cmp_func, the behavior is undefined. |
| |
550 * |
| |
551 * If the capacity is insufficient to hold the new data, a reallocation |
| |
552 * attempt is made. |
| |
553 * You can create your own reallocator by hand, use #cx_array_default_reallocator, |
| |
554 * or use the convenience function cx_array_reallocator() to create a custom reallocator. |
| |
555 * |
| |
556 * @param target a pointer to the target array |
| |
557 * @param size a pointer to the size of the target array |
| |
558 * @param capacity a pointer to the capacity of the target array |
| |
559 * @param cmp_func the compare function for the elements |
| |
560 * @param src the source array |
| |
561 * @param elem_size the size of one element |
| |
562 * @param elem_count the number of elements to insert |
| |
563 * @param reallocator the array reallocator to use |
| |
564 * (@c NULL defaults to #cx_array_default_reallocator) |
| |
565 * @retval zero success |
| |
566 * @retval non-zero failure |
| |
567 */ |
| |
568 cx_attr_nonnull_arg(1, 2, 3, 5) |
| |
569 CX_EXPORT int cx_array_insert_unique(void **target, size_t *size, size_t *capacity, |
| |
570 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, |
| |
571 CxArrayReallocator *reallocator); |
| |
572 |
| |
573 /** |
| |
574 * Inserts an element into a sorted array if it does not exist. |
| |
575 * |
| |
576 * If the target array is not already sorted with respect |
| |
577 * to the specified @p cmp_func, the behavior is undefined. |
| |
578 * |
| |
579 * If the capacity is insufficient to hold the new data, a reallocation |
| |
580 * attempt is made. |
| |
581 * |
| |
582 * The \@ SIZE_TYPE is flexible and can be any unsigned integer type. |
| |
583 * It is important, however, that @p size and @p capacity are pointers to |
| |
584 * variables of the same type. |
| |
585 * |
| |
586 * @param target (@c void**) a pointer to the target array |
| |
587 * @param size (@c SIZE_TYPE*) a pointer to the size of the target array |
| |
588 * @param capacity (@c SIZE_TYPE*) a pointer to the capacity of the target array |
| |
589 * @param elem_size (@c size_t) the size of one element |
| |
590 * @param elem (@c void*) a pointer to the element to add |
| |
591 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
| |
592 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
| |
593 * @retval zero success (also when the element was already present) |
| |
594 * @retval non-zero failure |
| |
595 */ |
| |
596 #define cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ |
| |
597 cx_array_insert_unique((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) |
| |
598 |
| |
599 /** |
| |
600 * Convenience macro for cx_array_add_unique() with a default |
| |
601 * layout and the specified reallocator. |
| |
602 * |
| |
603 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
| |
604 * @param array the name of the array (NOT a pointer or alias to the array) |
| |
605 * @param elem the element to add (NOT a pointer, address is automatically taken) |
| |
606 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
| |
607 * @retval zero success |
| |
608 * @retval non-zero failure |
| |
609 * @see CX_ARRAY_DECLARE() |
| |
610 * @see cx_array_simple_add_unique() |
| |
611 */ |
| |
612 #define cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) \ |
| |
613 cx_array_add_unique(&array, &(array##_size), &(array##_capacity), \ |
| |
614 sizeof((array)[0]), &(elem), cmp_func, reallocator) |
| |
615 |
| |
616 /** |
| |
617 * Convenience macro for cx_array_add_unique() with a default |
| |
618 * layout and the default reallocator. |
| |
619 * |
| |
620 * @param array the name of the array (NOT a pointer or alias to the array) |
| |
621 * @param elem the element to add (NOT a pointer, address is automatically taken) |
| |
622 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
| |
623 * @retval zero success |
| |
624 * @retval non-zero failure |
| |
625 * @see CX_ARRAY_DECLARE() |
| |
626 * @see cx_array_simple_add_unique_a() |
| |
627 */ |
| |
628 #define cx_array_simple_add_unique(array, elem, cmp_func) \ |
| |
629 cx_array_simple_add_unique_a(NULL, array, elem, cmp_func) |
| |
630 |
| |
631 /** |
| |
632 * Convenience macro for cx_array_insert_unique() with a default |
| |
633 * layout and the specified reallocator. |
| |
634 * |
| |
635 * @param reallocator (@c CxArrayReallocator*) the array reallocator to use |
| |
636 * @param array the name of the array (NOT a pointer or alias to the array) |
| |
637 * @param src (@c void*) pointer to the source array |
| |
638 * @param n (@c size_t) number of elements in the source array |
| |
639 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
| |
640 * @retval zero success |
| |
641 * @retval non-zero failure |
| |
642 * @see CX_ARRAY_DECLARE() |
| |
643 * @see cx_array_simple_insert_unique() |
| |
644 */ |
| |
645 #define cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) \ |
| |
646 cx_array_insert_unique((void**)(&array), &(array##_size), &(array##_capacity), \ |
| |
647 cmp_func, src, sizeof((array)[0]), n, reallocator) |
| |
648 |
| |
649 /** |
| |
650 * Convenience macro for cx_array_insert_unique() with a default |
| |
651 * layout and the default reallocator. |
| |
652 * |
| |
653 * @param array the name of the array (NOT a pointer or alias to the array) |
| |
654 * @param src (@c void*) pointer to the source array |
| |
655 * @param n (@c size_t) number of elements in the source array |
| |
656 * @param cmp_func (@c cx_cmp_func) the compare function for the elements |
| |
657 * @retval zero success |
| |
658 * @retval non-zero failure |
| |
659 * @see CX_ARRAY_DECLARE() |
| |
660 * @see cx_array_simple_insert_unique_a() |
| |
661 */ |
| |
662 #define cx_array_simple_insert_unique(array, src, n, cmp_func) \ |
| |
663 cx_array_simple_insert_unique_a(NULL, array, src, n, cmp_func) |
| 588 |
664 |
| 589 /** |
665 /** |
| 590 * Searches the largest lower bound in a sorted array. |
666 * Searches the largest lower bound in a sorted array. |
| 591 * |
667 * |
| 592 * In other words, this function returns the index of the largest element |
668 * In other words, this function returns the index of the largest element |
| 665 * @return the index of the smallest upper bound, or @p size |
729 * @return the index of the smallest upper bound, or @p size |
| 666 * @see cx_array_binary_search_inf() |
730 * @see cx_array_binary_search_inf() |
| 667 * @see cx_array_binary_search() |
731 * @see cx_array_binary_search() |
| 668 */ |
732 */ |
| 669 cx_attr_nonnull |
733 cx_attr_nonnull |
| 670 cx_attr_export |
734 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size, |
| 671 size_t cx_array_binary_search_sup( |
735 size_t elem_size, const void *elem, cx_compare_func cmp_func); |
| 672 const void *arr, |
|
| 673 size_t size, |
|
| 674 size_t elem_size, |
|
| 675 const void *elem, |
|
| 676 cx_compare_func cmp_func |
|
| 677 ); |
|
| 678 |
736 |
| 679 /** |
737 /** |
| 680 * Swaps two array elements. |
738 * Swaps two array elements. |
| 681 * |
739 * |
| 682 * @param arr the array |
740 * @param arr the array |
| 683 * @param elem_size the element size |
741 * @param elem_size the element size |
| 684 * @param idx1 index of first element |
742 * @param idx1 index of the first element |
| 685 * @param idx2 index of second element |
743 * @param idx2 index of the second element |
| 686 */ |
744 */ |
| 687 cx_attr_nonnull |
745 cx_attr_nonnull |
| 688 cx_attr_export |
746 CX_EXPORT void cx_array_swap(void *arr, size_t elem_size, size_t idx1, size_t idx2); |
| 689 void cx_array_swap( |
|
| 690 void *arr, |
|
| 691 size_t elem_size, |
|
| 692 size_t idx1, |
|
| 693 size_t idx2 |
|
| 694 ); |
|
| 695 |
747 |
| 696 /** |
748 /** |
| 697 * Allocates an array list for storing elements with @p elem_size bytes each. |
749 * Allocates an array list for storing elements with @p elem_size bytes each. |
| 698 * |
750 * |
| 699 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
751 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
| 700 * copies of the added elements and the compare function will be automatically set |
752 * copies of the added elements, and the compare function will be automatically set |
| 701 * to cx_cmp_ptr(), if none is given. |
753 * to cx_cmp_ptr(), if none is given. |
| 702 * |
754 * |
| 703 * @param allocator the allocator for allocating the list memory |
755 * @param allocator the allocator for allocating the list memory |
| 704 * (if @c NULL, the cxDefaultAllocator will be used) |
756 * (if @c NULL, the cxDefaultAllocator will be used) |
| 705 * @param comparator the comparator for the elements |
757 * @param comparator the comparator for the elements |