add cx_array_add() + fix type of cx_array_default_reallocator

Thu, 25 Jan 2024 22:01:12 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 25 Jan 2024 22:01:12 +0100
changeset 818
2be8fe3d5a2d
parent 817
949908c97474
child 819
5da2ead43077

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);

mercurial