Mon, 11 Nov 2024 21:42:14 +0100
simplify cx_array_copy() - fixes #474
src/array_list.c | file | annotate | diff | comparison | revisions | |
src/cx/array_list.h | file | annotate | diff | comparison | revisions | |
tests/test_list.c | file | annotate | diff | comparison | revisions |
--- a/src/array_list.c Thu Nov 07 22:46:58 2024 +0100 +++ b/src/array_list.c Mon Nov 11 21:42:14 2024 +0100 @@ -88,7 +88,7 @@ // LOW LEVEL ARRAY LIST FUNCTIONS -enum cx_array_result cx_array_copy( +int cx_array_copy( void **target, size_t *size, size_t *capacity, @@ -101,24 +101,20 @@ // assert pointers assert(target != NULL); assert(size != NULL); + assert(capacity != NULL); assert(src != NULL); + assert(reallocator != NULL); // determine capacity - size_t cap = capacity == NULL ? *size : *capacity; + size_t cap = *capacity; assert(*target != NULL || cap == 0); // check if resize is required size_t minsize = index + elem_count; size_t newsize = *size < minsize ? minsize : *size; - bool needrealloc = newsize > cap; // reallocate if possible - if (needrealloc) { - // a reallocator and a capacity variable must be available - if (reallocator == NULL || capacity == NULL) { - return CX_ARRAY_REALLOC_NOT_SUPPORTED; - } - + if (newsize > cap) { // check, if we need to repair the src pointer uintptr_t targetaddr = (uintptr_t) *target; uintptr_t srcaddr = (uintptr_t) src; @@ -134,7 +130,7 @@ *target, cap, elem_size, reallocator ); if (newmem == NULL) { - return CX_ARRAY_REALLOC_FAILED; + return 1; } // repair src pointer, if necessary @@ -156,10 +152,10 @@ *size = newsize; // return successfully - return CX_ARRAY_SUCCESS; + return 0; } -enum cx_array_result cx_array_insert_sorted( +int cx_array_insert_sorted( void **target, size_t *size, size_t *capacity, @@ -193,7 +189,7 @@ if (new_mem == NULL) { // give it up right away, there is no contract // that requires us to insert as much as we can - return CX_ARRAY_REALLOC_FAILED; + return 1; } *target = new_mem; *capacity = new_capacity; @@ -267,7 +263,7 @@ // still buffer elements left? // don't worry, we already moved them to the correct place - return CX_ARRAY_SUCCESS; + return 0; } size_t cx_array_binary_search_inf( @@ -458,7 +454,7 @@ size_t elems_to_move = list->collection.size - index; size_t start_of_moved = index + n; - if (CX_ARRAY_SUCCESS != cx_array_copy( + if (cx_array_copy( &arl->data, &list->collection.size, &arl->capacity, @@ -478,7 +474,7 @@ // therefore, it is impossible to leave this function with an invalid array // place the new elements - if (CX_ARRAY_SUCCESS == cx_array_copy( + if (cx_array_copy( &arl->data, &list->collection.size, &arl->capacity, @@ -488,10 +484,10 @@ n, &arl->reallocator )) { - return n; - } else { // array list implementation is "all or nothing" return 0; + } else { + return n; } } @@ -503,7 +499,7 @@ // get a correctly typed pointer to the list cx_array_list *arl = (cx_array_list *) list; - if (CX_ARRAY_SUCCESS == cx_array_insert_sorted( + if (cx_array_insert_sorted( &arl->data, &list->collection.size, &arl->capacity, @@ -513,10 +509,10 @@ n, &arl->reallocator )) { - return n; - } else { // array list implementation is "all or nothing" return 0; + } else { + return n; } }
--- a/src/cx/array_list.h Thu Nov 07 22:46:58 2024 +0100 +++ b/src/cx/array_list.h Mon Nov 11 21:42:14 2024 +0100 @@ -153,42 +153,28 @@ ); /** - * Return codes for array functions. - */ -enum cx_array_result { - CX_ARRAY_SUCCESS, - CX_ARRAY_REALLOC_NOT_SUPPORTED, - CX_ARRAY_REALLOC_FAILED, -}; - -/** * Copies elements from one array to another. * * The elements are copied to the \p target array at the specified \p index, * overwriting possible elements. The \p index does not need to be in range of * the current array \p size. If the new index plus the number of elements added - * would extend the array's size, and \p capacity is not \c NULL, the remaining - * capacity is used. + * would extend the array's size, the remaining \p capacity is used. * - * If the capacity is insufficient to hold the new data, a reallocation - * attempt is made, unless the \p reallocator is set to \c NULL, in which case - * this function ultimately returns a failure. + * If the \p capacity is also insufficient to hold the new data, a reallocation + * attempt is made with the specified \p reallocator. * * @param target a pointer to the target array * @param size a pointer to the size of the target array - * @param capacity a pointer to the target array's capacity - - * \c NULL if only the size shall be used to bound the array (reallocations - * will NOT be supported in that case) + * @param capacity a pointer to the capacity of the target array * @param index the index where the copied elements shall be placed * @param src the source array * @param elem_size the size of one element * @param elem_count the number of elements to copy - * @param reallocator the array reallocator to use, or \c NULL - * if reallocation shall not happen - * @return zero on success, non-zero error code on failure + * @param reallocator the array reallocator to use + * @return zero on success, non-zero on failure */ -cx_attr_nonnull_arg(1, 2, 5) -enum cx_array_result cx_array_copy( +cx_attr_nonnull +int cx_array_copy( void **target, size_t *size, size_t *capacity, @@ -200,12 +186,14 @@ ); /** - * Convenience macro that uses cx_array_copy() with a default layout and the default reallocator. + * Convenience macro that uses cx_array_copy() with a default layout and + * the default reallocator. * * @param array the name of the array (NOT a pointer to the array) * @param index the index where the copied elements shall be placed * @param src the source array * @param count the number of elements to copy + * @return zero on success, non-zero on failure * @see CX_ARRAY_DECLARE() */ #define cx_array_simple_copy(array, index, src, count) \ @@ -215,21 +203,20 @@ /** * Adds an element to an array with the possibility of allocating more space. * - * The element \p elem is added to the end of the \p target array which containing - * \p size elements, already. The \p capacity must not be \c NULL and point a - * variable holding the current maximum number of elements the array can hold. + * The element \p elem is added to the end of the \p target array which contains + * \p size elements, already. The \p capacity must point to a variable denoting + * the current maximum number of elements the array can hold. * - * If the capacity is insufficient to hold the new element, and the optional - * \p reallocator is not \c NULL, an attempt increase the \p capacity is made - * and the new capacity is written back. + * If the capacity is insufficient to hold the new element, an attempt to + * increase the \p capacity is made and the new capacity is written back. * * @param target a pointer to the target array * @param size a pointer to the size of the target array - * @param capacity a pointer to the target array's capacity - must not be \c NULL + * @param capacity a pointer to the capacity of the target array * @param elem_size the size of one element * @param elem a pointer to the element to add - * @param reallocator the array reallocator to use, or \c NULL if reallocation shall not happen - * @return zero on success, non-zero error code on failure + * @param reallocator the array reallocator to use + * @return zero on success, non-zero on failure */ #define cx_array_add(target, size, capacity, elem_size, elem, reallocator) \ cx_array_copy((void**)(target), size, capacity, *(size), elem, elem_size, 1, reallocator) @@ -240,6 +227,7 @@ * * @param array the name of the array (NOT a pointer to the array) * @param elem the element to add (NOT a pointer, address is automatically taken) + * @return zero on success, non-zero on failure * @see CX_ARRAY_DECLARE() */ #define cx_array_simple_add(array, elem) \ @@ -257,16 +245,16 @@ * * @param target a pointer to the target array * @param size a pointer to the size of the target array - * @param capacity a pointer to the target array's capacity + * @param capacity a pointer to the capacity of the target array * @param cmp_func the compare function for the elements * @param src the source array * @param elem_size the size of one element * @param elem_count the number of elements to insert * @param reallocator the array reallocator to use - * @return zero on success, non-zero error code on failure + * @return zero on success, non-zero on failure */ cx_attr_nonnull -enum cx_array_result cx_array_insert_sorted( +int cx_array_insert_sorted( void **target, size_t *size, size_t *capacity, @@ -288,11 +276,11 @@ * * @param target a pointer to the target array * @param size a pointer to the size of the target array - * @param capacity a pointer to the target array's capacity + * @param capacity a pointer to the capacity of the target array * @param elem_size the size of one element * @param elem a pointer to the element to add * @param reallocator the array reallocator to use - * @return zero on success, non-zero error code on failure + * @return zero on success, non-zero on failure */ #define cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) \ cx_array_insert_sorted((void**)(target), size, capacity, cmp_func, elem, elem_size, 1, reallocator) @@ -304,6 +292,7 @@ * @param array the name of the array (NOT a pointer to the array) * @param elem the element to add (NOT a pointer, address is automatically taken) * @param cmp_func the compare function for the elements + * @return zero on success, non-zero on failure * @see CX_ARRAY_DECLARE() */ #define cx_array_simple_add_sorted(array, elem, cmp_func) \ @@ -318,6 +307,7 @@ * @param src pointer to the source array * @param n number of elements in the source array * @param cmp_func the compare function for the elements + * @return zero on success, non-zero on failure * @see CX_ARRAY_DECLARE() */ #define cx_array_simple_insert_sorted(array, src, n, cmp_func) \
--- a/tests/test_list.c Thu Nov 07 22:46:58 2024 +0100 +++ b/tests/test_list.c Mon Nov 11 21:42:14 2024 +0100 @@ -36,66 +36,41 @@ #include <stdarg.h> CX_TEST(test_array_add) { - int stackspace[5] = {1,1,2,3,5}; - int *stackarray = stackspace; - size_t stackarray_size = 3; - size_t stackarray_capacity = 5; - CX_ARRAY_DECLARE(int, heaparray); - heaparray = calloc(5, sizeof(int)); - heaparray[0] = 2; - heaparray[1] = 3; - heaparray[2] = 5; - heaparray[3] = 7; - heaparray[4] = 11; - heaparray_size = 3; - heaparray_capacity = 5; + CX_ARRAY_DECLARE(int, arr); + arr = calloc(5, sizeof(int)); + arr[0] = 2; + arr[1] = 3; + arr[2] = 5; + arr[3] = 7; + arr[4] = 11; + arr_size = 3; + arr_capacity = 5; int elem = 8, elem2 = 47; - enum cx_array_result result; + int result; CX_TEST_DO { - result = cx_array_add(&stackarray, &stackarray_size, &stackarray_capacity, sizeof(int), &elem, NULL); - CX_TEST_ASSERT(result == CX_ARRAY_SUCCESS); - CX_TEST_ASSERT(stackarray[0] == 1); - CX_TEST_ASSERT(stackarray[1] == 1); - CX_TEST_ASSERT(stackarray[2] == 2); - CX_TEST_ASSERT(stackarray[3] == 8); - CX_TEST_ASSERT(stackarray[4] == 5); - CX_TEST_ASSERT(stackarray_size == 4); - CX_TEST_ASSERT(stackarray_capacity == 5); + result = cx_array_simple_add(arr, elem); + CX_TEST_ASSERT(result == 0); + CX_TEST_ASSERT(arr[0] == 2); + CX_TEST_ASSERT(arr[1] == 3); + CX_TEST_ASSERT(arr[2] == 5); + CX_TEST_ASSERT(arr[3] == 8); + CX_TEST_ASSERT(arr[4] == 11); + CX_TEST_ASSERT(arr_size == 4); + CX_TEST_ASSERT(arr_capacity == 5); - stackarray_size = 5; - result = cx_array_add(&stackarray, &stackarray_size, &stackarray_capacity, sizeof(int), &elem2, NULL); - CX_TEST_ASSERT(result == CX_ARRAY_REALLOC_NOT_SUPPORTED); - CX_TEST_ASSERT(stackarray[0] == 1); - CX_TEST_ASSERT(stackarray[1] == 1); - CX_TEST_ASSERT(stackarray[2] == 2); - CX_TEST_ASSERT(stackarray[3] == 8); - CX_TEST_ASSERT(stackarray[4] == 5); - CX_TEST_ASSERT(stackarray_size == 5); - CX_TEST_ASSERT(stackarray_capacity == 5); - - result = cx_array_simple_add(heaparray, elem); - CX_TEST_ASSERT(result == CX_ARRAY_SUCCESS); - CX_TEST_ASSERT(heaparray[0] == 2); - CX_TEST_ASSERT(heaparray[1] == 3); - CX_TEST_ASSERT(heaparray[2] == 5); - CX_TEST_ASSERT(heaparray[3] == 8); - CX_TEST_ASSERT(heaparray[4] == 11); - CX_TEST_ASSERT(heaparray_size == 4); - CX_TEST_ASSERT(heaparray_capacity == 5); - - heaparray_size = 5; - result = cx_array_simple_add(heaparray, elem2); - CX_TEST_ASSERT(result == CX_ARRAY_SUCCESS); - CX_TEST_ASSERT(heaparray[0] == 2); - CX_TEST_ASSERT(heaparray[1] == 3); - CX_TEST_ASSERT(heaparray[2] == 5); - CX_TEST_ASSERT(heaparray[3] == 8); - CX_TEST_ASSERT(heaparray[4] == 11); - CX_TEST_ASSERT(heaparray[5] == 47); - CX_TEST_ASSERT(heaparray_size == 6); - CX_TEST_ASSERT(heaparray_capacity >= 6); + arr_size = 5; + result = cx_array_simple_add(arr, elem2); + CX_TEST_ASSERT(result == 0); + CX_TEST_ASSERT(arr[0] == 2); + CX_TEST_ASSERT(arr[1] == 3); + CX_TEST_ASSERT(arr[2] == 5); + CX_TEST_ASSERT(arr[3] == 8); + CX_TEST_ASSERT(arr[4] == 11); + CX_TEST_ASSERT(arr[5] == 47); + CX_TEST_ASSERT(arr_size == 6); + CX_TEST_ASSERT(arr_capacity >= 6); } - free(heaparray); + free(arr); } CX_TEST(test_array_insert_sorted) {