| 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 capacity the new capacity (number of elements) |
179 * @param old_capacity the old number of elements |
| |
180 * @param new_capacity the new number of elements |
| 182 * @param elem_size the size of each element |
181 * @param elem_size the size of each element |
| 183 * @param alloc a reference to this allocator |
182 * @param alloc a reference to this allocator |
| 184 * @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 |
| 185 */ |
184 */ |
| 186 cx_attr_nodiscard |
185 void *(*realloc)( void *array, size_t old_capacity, size_t new_capacity, |
| 187 cx_attr_nonnull_arg(4) |
186 size_t elem_size, struct cx_array_reallocator_s *alloc); |
| 188 cx_attr_allocsize(2, 3) |
|
| 189 void *(*realloc)( |
|
| 190 void *array, |
|
| 191 size_t capacity, |
|
| 192 size_t elem_size, |
|
| 193 struct cx_array_reallocator_s *alloc |
|
| 194 ); |
|
| 195 |
187 |
| 196 /** |
188 /** |
| 197 * Custom data pointer. |
189 * The allocator that shall be used for the reallocations. |
| 198 */ |
190 */ |
| 199 void *ptr1; |
191 const CxAllocator *allocator; |
| 200 /** |
192 /** |
| 201 * Custom data pointer. |
193 * Optional pointer to stack memory |
| |
194 * if the array is originally located on the stack. |
| 202 */ |
195 */ |
| 203 void *ptr2; |
196 const void *stack_ptr; |
| 204 /** |
|
| 205 * Custom data integer. |
|
| 206 */ |
|
| 207 size_t int1; |
|
| 208 /** |
|
| 209 * Custom data integer. |
|
| 210 */ |
|
| 211 size_t int2; |
|
| 212 }; |
197 }; |
| 213 |
198 |
| 214 /** |
199 /** |
| 215 * Typedef for the array reallocator struct. |
200 * Typedef for the array reallocator struct. |
| 216 */ |
201 */ |
| 217 typedef struct cx_array_reallocator_s CxArrayReallocator; |
202 typedef struct cx_array_reallocator_s CxArrayReallocator; |
| 218 |
203 |
| 219 /** |
204 /** |
| 220 * A default stdlib-based array reallocator. |
205 * A default array reallocator that is based on the cxDefaultAllocator. |
| 221 */ |
206 */ |
| 222 cx_attr_export |
207 CX_EXPORT extern CxArrayReallocator *cx_array_default_reallocator; |
| 223 extern CxArrayReallocator *cx_array_default_reallocator; |
|
| 224 |
208 |
| 225 /** |
209 /** |
| 226 * Creates a new array reallocator. |
210 * Creates a new array reallocator. |
| 227 * |
211 * |
| 228 * When @p allocator is @c NULL, the stdlib default allocator will be used. |
212 * When @p allocator is @c NULL, the cxDefaultAllocator will be used. |
| 229 * |
213 * |
| 230 * 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 |
| 231 * @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. |
| 232 * When reallocation is needed, the reallocator checks, if the array is |
216 * When reallocation is needed, the reallocator checks if the array is |
| 233 * 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. |
| 234 * |
218 * |
| 235 * @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 |
| 236 * reallocator that behaves like #cx_array_default_reallocator. |
220 * reallocator that behaves like #cx_array_default_reallocator. |
| 237 * |
221 * |
| 238 * @param allocator the allocator this reallocator shall be based on |
222 * @param allocator the allocator this reallocator shall be based on |
| 239 * @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 |
| 240 * on the stack or shall not reallocated in place |
224 * on the stack or shall not reallocate in place |
| 241 * @return an array reallocator |
225 * @return an array reallocator |
| 242 */ |
226 */ |
| 243 cx_attr_export |
227 CX_EXPORT CxArrayReallocator cx_array_reallocator( |
| 244 CxArrayReallocator cx_array_reallocator( |
228 const struct cx_allocator_s *allocator, const void *stack_ptr); |
| 245 const struct cx_allocator_s *allocator, |
|
| 246 const void *stackmem |
|
| 247 ); |
|
| 248 |
229 |
| 249 /** |
230 /** |
| 250 * Reserves memory for additional elements. |
231 * Reserves memory for additional elements. |
| 251 * |
232 * |
| 252 * 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 |
| 275 * @retval zero success |
256 * @retval zero success |
| 276 * @retval non-zero failure |
257 * @retval non-zero failure |
| 277 * @see cx_array_reallocator() |
258 * @see cx_array_reallocator() |
| 278 */ |
259 */ |
| 279 cx_attr_nonnull_arg(1, 2, 3) |
260 cx_attr_nonnull_arg(1, 2, 3) |
| 280 cx_attr_export |
261 CX_EXPORT int cx_array_reserve(void **array, void *size, void *capacity, |
| 281 int cx_array_reserve( |
262 unsigned width, size_t elem_size, size_t elem_count, |
| 282 void **array, |
263 CxArrayReallocator *reallocator); |
| 283 void *size, |
|
| 284 void *capacity, |
|
| 285 unsigned width, |
|
| 286 size_t elem_size, |
|
| 287 size_t elem_count, |
|
| 288 CxArrayReallocator *reallocator |
|
| 289 ); |
|
| 290 |
264 |
| 291 /** |
265 /** |
| 292 * Copies elements from one array to another. |
266 * Copies elements from one array to another. |
| 293 * |
267 * |
| 294 * 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, |
| 295 * 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 |
| 296 * 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 |
| 297 * would extend the array's size, the remaining @p capacity is used. |
271 * extends the array's size, the remaining @p capacity is used. |
| 298 * |
272 * |
| 299 * 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 |
| 300 * attempt is made with the specified @p reallocator. |
274 * attempt is made with the specified @p reallocator. |
| 301 * 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, |
| 302 * 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. |
| 303 * |
277 * |
| 304 * The @p width in bytes refers to the size and capacity. |
278 * The @p width in bytes refers to the size and capacity. |
| 305 * Both must have the same width. |
279 * Both must have the same width. |
| 306 * 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 |
| 307 * architecture. If set to zero, the native word width is used. |
281 * architecture. If set to zero, the native word width is used. |
| 308 * |
282 * |
| 309 * @param target a pointer to the target array |
283 * @param target a pointer to the target array |
| 310 * @param size a pointer to the size of the target array |
284 * @param size a pointer to the size of the target array |
| 311 * @param capacity a pointer to the capacity of the target array |
285 * @param capacity a pointer to the capacity of the target array |
| 478 * (@c NULL defaults to #cx_array_default_reallocator) |
443 * (@c NULL defaults to #cx_array_default_reallocator) |
| 479 * @retval zero success |
444 * @retval zero success |
| 480 * @retval non-zero failure |
445 * @retval non-zero failure |
| 481 */ |
446 */ |
| 482 cx_attr_nonnull_arg(1, 2, 3, 5) |
447 cx_attr_nonnull_arg(1, 2, 3, 5) |
| 483 cx_attr_export |
448 CX_EXPORT int cx_array_insert_sorted(void **target, size_t *size, size_t *capacity, |
| 484 int cx_array_insert_sorted( |
449 cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, |
| 485 void **target, |
450 CxArrayReallocator *reallocator); |
| 486 size_t *size, |
|
| 487 size_t *capacity, |
|
| 488 cx_compare_func cmp_func, |
|
| 489 const void *src, |
|
| 490 size_t elem_size, |
|
| 491 size_t elem_count, |
|
| 492 CxArrayReallocator *reallocator |
|
| 493 ); |
|
| 494 |
451 |
| 495 /** |
452 /** |
| 496 * Inserts an element into a sorted array. |
453 * Inserts an element into a sorted array. |
| 497 * |
454 * |
| 498 * If the target array is not already sorted with respect |
455 * If the target array is not already sorted with respect |
| 499 * to the specified @p cmp_func, the behavior is undefined. |
456 * to the specified @p cmp_func, the behavior is undefined. |
| 500 * |
457 * |
| 501 * 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 |
| 502 * attempt is made. |
459 * attempt is made. |
| 503 * |
460 * |
| 504 * 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. |
| 505 * 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 |
| 506 * variables of the same type. |
463 * variables of the same type. |
| 581 * @see CX_ARRAY_DECLARE() |
538 * @see CX_ARRAY_DECLARE() |
| 582 * @see cx_array_simple_insert_sorted_a() |
539 * @see cx_array_simple_insert_sorted_a() |
| 583 */ |
540 */ |
| 584 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ |
541 #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \ |
| 585 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) |
| 586 |
664 |
| 587 /** |
665 /** |
| 588 * Searches the largest lower bound in a sorted array. |
666 * Searches the largest lower bound in a sorted array. |
| 589 * |
667 * |
| 590 * 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 |
| 663 * @return the index of the smallest upper bound, or @p size |
729 * @return the index of the smallest upper bound, or @p size |
| 664 * @see cx_array_binary_search_inf() |
730 * @see cx_array_binary_search_inf() |
| 665 * @see cx_array_binary_search() |
731 * @see cx_array_binary_search() |
| 666 */ |
732 */ |
| 667 cx_attr_nonnull |
733 cx_attr_nonnull |
| 668 cx_attr_export |
734 CX_EXPORT size_t cx_array_binary_search_sup(const void *arr, size_t size, |
| 669 size_t cx_array_binary_search_sup( |
735 size_t elem_size, const void *elem, cx_compare_func cmp_func); |
| 670 const void *arr, |
|
| 671 size_t size, |
|
| 672 size_t elem_size, |
|
| 673 const void *elem, |
|
| 674 cx_compare_func cmp_func |
|
| 675 ); |
|
| 676 |
736 |
| 677 /** |
737 /** |
| 678 * Swaps two array elements. |
738 * Swaps two array elements. |
| 679 * |
739 * |
| 680 * @param arr the array |
740 * @param arr the array |
| 681 * @param elem_size the element size |
741 * @param elem_size the element size |
| 682 * @param idx1 index of first element |
742 * @param idx1 index of the first element |
| 683 * @param idx2 index of second element |
743 * @param idx2 index of the second element |
| 684 */ |
744 */ |
| 685 cx_attr_nonnull |
745 cx_attr_nonnull |
| 686 cx_attr_export |
746 CX_EXPORT void cx_array_swap(void *arr, size_t elem_size, size_t idx1, size_t idx2); |
| 687 void cx_array_swap( |
|
| 688 void *arr, |
|
| 689 size_t elem_size, |
|
| 690 size_t idx1, |
|
| 691 size_t idx2 |
|
| 692 ); |
|
| 693 |
747 |
| 694 /** |
748 /** |
| 695 * 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. |
| 696 * |
750 * |
| 697 * 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 |
| 698 * 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 |
| 699 * to cx_cmp_ptr(), if none is given. |
753 * to cx_cmp_ptr(), if none is given. |
| 700 * |
754 * |
| 701 * @param allocator the allocator for allocating the list memory |
755 * @param allocator the allocator for allocating the list memory |
| 702 * (if @c NULL, a default stdlib allocator will be used) |
756 * (if @c NULL, the cxDefaultAllocator will be used) |
| 703 * @param comparator the comparator for the elements |
757 * @param comparator the comparator for the elements |
| 704 * (if @c NULL, and the list is not storing pointers, sort and find |
758 * (if @c NULL, and the list is not storing pointers, sort and find |
| 705 * functions will not work) |
759 * functions will not work) |
| 706 * @param elem_size the size of each element in bytes |
760 * @param elem_size the size of each element in bytes |
| 707 * @param initial_capacity the initial number of elements the array can store |
761 * @param initial_capacity the initial number of elements the array can store |
| 708 * @return the created list |
762 * @return the created list |
| 709 */ |
763 */ |
| 710 cx_attr_nodiscard |
764 cx_attr_nodiscard |
| 711 cx_attr_malloc |
765 cx_attr_malloc |
| 712 cx_attr_dealloc(cxListFree, 1) |
766 cx_attr_dealloc(cxListFree, 1) |
| 713 cx_attr_export |
767 CX_EXPORT CxList *cxArrayListCreate(const CxAllocator *allocator, |
| 714 CxList *cxArrayListCreate( |
768 cx_compare_func comparator, size_t elem_size, size_t initial_capacity); |
| 715 const CxAllocator *allocator, |
|
| 716 cx_compare_func comparator, |
|
| 717 size_t elem_size, |
|
| 718 size_t initial_capacity |
|
| 719 ); |
|
| 720 |
769 |
| 721 /** |
770 /** |
| 722 * Allocates an array list for storing elements with @p elem_size bytes each. |
771 * Allocates an array list for storing elements with @p elem_size bytes each. |
| 723 * |
772 * |
| 724 * The list will use the cxDefaultAllocator and @em NO compare function. |
773 * The list will use the cxDefaultAllocator and @em NO compare function. |
| 725 * If you want to call functions that need a compare function, you have to |
774 * If you want to call functions that need a compare function, you have to |
| 726 * set it immediately after creation or use cxArrayListCreate(). |
775 * set it immediately after creation or use cxArrayListCreate(). |
| 727 * |
776 * |
| 728 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
777 * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of |
| 729 * copies of the added elements and the compare function will be automatically set |
778 * copies of the added elements and the compare function will be automatically set |
| 730 * to cx_cmp_ptr(), if none is given. |
779 * to cx_cmp_ptr(). |
| 731 * |
780 * |
| 732 * @param elem_size (@c size_t) the size of each element in bytes |
781 * @param elem_size (@c size_t) the size of each element in bytes |
| 733 * @param initial_capacity (@c size_t) the initial number of elements the array can store |
782 * @param initial_capacity (@c size_t) the initial number of elements the array can store |
| 734 * @return the created list |
783 * @return the created list |
| 735 */ |
784 */ |