Thu, 25 Jan 2024 22:01:12 +0100
add cx_array_add() + fix type of cx_array_default_reallocator
CHANGELOG | file | annotate | diff | comparison | revisions | |
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/CHANGELOG Wed Jan 24 22:19:05 2024 +0100 +++ b/CHANGELOG Thu Jan 25 22:01:12 2024 +0100 @@ -2,6 +2,7 @@ ------------------------ * adds tree.h * adds cx_array_default_reallocator + * adds cx_array_add() * adds cx_linked_list_find_node() * adds cxListFindRemove() * adds cxBufferReset()
--- a/src/array_list.c Wed Jan 24 22:19:05 2024 +0100 +++ b/src/array_list.c Thu Jan 25 22:01:12 2024 +0100 @@ -42,10 +42,12 @@ return realloc(array, capacity * elem_size); } -struct cx_array_reallocator_s cx_array_default_reallocator = { +struct cx_array_reallocator_s cx_array_default_reallocator_impl = { cx_array_default_realloc, NULL, NULL, 0, 0 }; +struct cx_array_reallocator_s *cx_array_default_reallocator = &cx_array_default_reallocator_impl; + // LOW LEVEL ARRAY LIST FUNCTIONS enum cx_array_copy_result cx_array_copy(
--- a/src/cx/array_list.h Wed Jan 24 22:19:05 2024 +0100 +++ b/src/cx/array_list.h Thu Jan 25 22:01:12 2024 +0100 @@ -96,7 +96,7 @@ /** * A default stdlib-based array reallocator. */ -extern struct cx_array_reallocator_s cx_array_default_reallocator; +extern struct cx_array_reallocator_s *cx_array_default_reallocator; /** * Return codes for cx_array_copy(). @@ -117,7 +117,7 @@ * capacity is used. * * If the capacity is insufficient to hold the new data, a reallocation - * attempt is made, unless the allocator is set to \c NULL, in which case + * attempt is made, unless the \p reallocator is set to \c NULL, in which case * this function ultimately returns a failure. * * @param target the target array @@ -143,6 +143,28 @@ struct cx_array_reallocator_s *reallocator ) __attribute__((__nonnull__(1, 2, 5))); +/** + * 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. + * + * 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. + * + * @param target 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 elem_size the size of one element + * @param elem the element to add + * @param reallocator the array re-allocator to use, or \c NULL + * if re-allocation shall not happen + * @return zero on success, non-zero error code 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) /** * Swaps two array elements.
--- a/tests/test_list.c Wed Jan 24 22:19:05 2024 +0100 +++ b/tests/test_list.c Thu Jan 25 22:01:12 2024 +0100 @@ -36,6 +36,68 @@ #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; + int *heaparray = calloc(5, sizeof(int)); + heaparray[0] = 2; + heaparray[1] = 3; + heaparray[2] = 5; + heaparray[3] = 7; + heaparray[4] = 11; + size_t heaparray_size = 3; + size_t heaparray_capacity = 5; + int elem = 8, elem2 = 47; + enum cx_array_copy_result result; + CX_TEST_DO { + result = cx_array_add(&stackarray, &stackarray_size, &stackarray_capacity, sizeof(int), &elem, NULL); + CX_TEST_ASSERT(result == CX_ARRAY_COPY_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); + + stackarray_size = 5; + result = cx_array_add(&stackarray, &stackarray_size, &stackarray_capacity, sizeof(int), &elem2, NULL); + CX_TEST_ASSERT(result == CX_ARRAY_COPY_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_add(&heaparray, &heaparray_size, &heaparray_capacity, sizeof(int), &elem, cx_array_default_reallocator); + CX_TEST_ASSERT(result == CX_ARRAY_COPY_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_add(&heaparray, &heaparray_size, &heaparray_capacity, sizeof(int), &elem2, cx_array_default_reallocator); + CX_TEST_ASSERT(result == CX_ARRAY_COPY_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); + } + free(heaparray); +} + typedef struct node { struct node *next; struct node *prev; @@ -1344,6 +1406,8 @@ CxTestSuite *cx_test_suite_array_list(void) { CxTestSuite *suite = cx_test_suite_new("array_list"); + cx_test_register(suite, test_array_add); + cx_test_register(suite, test_list_arl_create); cx_test_register(suite, test_list_arl_create_simple); cx_test_register(suite, test_list_arl_create_simple_for_pointers);