#224 add cxListAddArray()

Wed, 23 Nov 2022 22:40:55 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 23 Nov 2022 22:40:55 +0100
changeset 629
6c81ee4f11ad
parent 628
1e2be40f0cb5
child 630
ac5e7f789048

#224 add cxListAddArray()

This also replaces cxLinkedListFromArray().

src/array_list.c file | annotate | diff | comparison | revisions
src/cx/linked_list.h file | annotate | diff | comparison | revisions
src/cx/list.h file | annotate | diff | comparison | revisions
src/linked_list.c file | annotate | diff | comparison | revisions
test/test_list.cpp file | annotate | diff | comparison | revisions
--- a/src/array_list.c	Sun Nov 20 21:08:36 2022 +0100
+++ b/src/array_list.c	Wed Nov 23 22:40:55 2022 +0100
@@ -185,6 +185,29 @@
     );
 }
 
+static size_t cx_arl_add_array(
+        struct cx_list_s *list,
+        void const *array,
+        size_t n
+) {
+    cx_array_list *arl = (cx_array_list *) list;
+    if (CX_ARRAY_COPY_SUCCESS == cx_array_copy(
+            &arl->data,
+            &list->size,
+            &list->capacity,
+            list->size,
+            array,
+            list->itemsize,
+            n,
+            &arl->reallocator
+    )) {
+        return n;
+    } else {
+        // array list implementation is "all or nothing"
+        return 0;
+    }
+}
+
 static int cx_arl_insert(
         struct cx_list_s *list,
         size_t index,
@@ -385,6 +408,7 @@
 static cx_list_class cx_array_list_class = {
         cx_arl_destructor,
         cx_arl_add,
+        cx_arl_add_array,
         cx_arl_insert,
         cx_arl_insert_iter,
         cx_arl_remove,
--- a/src/cx/linked_list.h	Sun Nov 20 21:08:36 2022 +0100
+++ b/src/cx/linked_list.h	Wed Nov 23 22:40:55 2022 +0100
@@ -80,27 +80,6 @@
 ) __attribute__((__nonnull__));
 
 /**
- * Creates a linked list using the data from an array.
- *
- * @remark Elements added to the list are copied, therefore a possible destructor
- * MUST NOT free the memory pointed to by its argument.
- *
- * @param allocator the allocator for allocating the list nodes
- * @param comparator the comparator for the elements
- * @param item_size the size of one item in the array
- * @param num_items the number of items
- * @param array the array data
- * @return the created list
- */
-CxList *cxLinkedListFromArray(
-        CxAllocator const *allocator,
-        CxListComparator comparator,
-        size_t item_size,
-        size_t num_items,
-        void const *array
-) __attribute__((__nonnull__));
-
-/**
  * Finds the node at a certain index.
  *
  * This function can be used to start at an arbitrary position within the list.
--- a/src/cx/list.h	Sun Nov 20 21:08:36 2022 +0100
+++ b/src/cx/list.h	Wed Nov 23 22:40:55 2022 +0100
@@ -130,6 +130,15 @@
     );
 
     /**
+     * Member function for adding multiple elements.
+     */
+    size_t (*add_array)(
+            struct cx_list_s *list,
+            void const *array,
+            size_t n
+    );
+
+    /**
      * Member function for inserting an element.
      */
     int (*insert)(
@@ -209,6 +218,7 @@
  * @param list the list
  * @param elem a pointer to the element to add
  * @return zero on success, non-zero on memory allocation failure
+ * @see cxListAddArray()
  */
 __attribute__((__nonnull__))
 static inline int cxListAdd(
@@ -219,6 +229,28 @@
 }
 
 /**
+ * Adds multiple items to the end of the list.
+ *
+ * This method is more efficient than invoking cxListAdd() multiple times.
+ *
+ * If there is not enough memory to add all elements, the returned value is
+ * less than \p n.
+ *
+ * @param list the list
+ * @param array a pointer to the elements to add
+ * @param n the number of elements to add
+ * @return the number of added elements
+ */
+__attribute__((__nonnull__))
+static inline size_t cxListAddArray(
+        CxList *list,
+        void const *array,
+        size_t n
+) {
+    return list->cl->add_array(list, array, n);
+}
+
+/**
  * Inserts an item at the specified index.
  *
  * If \p index equals the list \c size, this is effectively cxListAdd().
--- a/src/linked_list.c	Sun Nov 20 21:08:36 2022 +0100
+++ b/src/linked_list.c	Wed Nov 23 22:40:55 2022 +0100
@@ -540,6 +540,20 @@
     return cx_ll_insert(list, list->size, elem);
 }
 
+static size_t cx_ll_add_array(
+        struct cx_list_s *list,
+        void const *array,
+        size_t n
+) {
+    // TODO: redirect to cx_ll_insert_array
+    cx_for_n (i, n) {
+        if (cx_ll_add(list, ((char const *) array) + i * list->itemsize)) {
+            return i;
+        }
+    }
+    return n;
+}
+
 static int cx_pll_insert(
         struct cx_list_s *list,
         size_t index,
@@ -727,6 +741,7 @@
 static cx_list_class cx_linked_list_class = {
         cx_ll_destructor,
         cx_ll_add,
+        cx_ll_add_array,
         cx_ll_insert,
         cx_ll_insert_iter,
         cx_ll_remove,
@@ -741,6 +756,7 @@
 static cx_list_class cx_pointer_linked_list_class = {
         cx_ll_destructor,
         cx_pll_add,
+        cx_ll_add_array,
         cx_pll_insert,
         cx_pll_insert_iter,
         cx_ll_remove,
@@ -786,22 +802,3 @@
 
     return (CxList *) list;
 }
-
-CxList *cxLinkedListFromArray(
-        CxAllocator const *allocator,
-        CxListComparator comparator,
-        size_t item_size,
-        size_t num_items,
-        void const *array
-) {
-    CxList *list = cxLinkedListCreate(allocator, comparator, item_size);
-    if (list == NULL) return NULL;
-    cx_for_n (i, num_items) {
-        if (0 != cxListAdd(list, ((const unsigned char *) array) + i * item_size)) {
-            cx_ll_destructor(list);
-            cxFree(allocator, list);
-            return NULL;
-        }
-    }
-    return list;
-}
--- a/test/test_list.cpp	Sun Nov 20 21:08:36 2022 +0100
+++ b/test/test_list.cpp	Wed Nov 23 22:40:55 2022 +0100
@@ -569,28 +569,21 @@
     }
 
     auto linkedListFromTestData() const -> CxList * {
-        // TODO: replace with cxListAddArray
-        return autofree(
-                cxLinkedListFromArray(
-                        &testingAllocator,
-                        cx_cmp_int,
-                        sizeof(int),
-                        testdata_len,
-                        testdata.data.data()
-                )
-        );
+        auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
+        cxListAddArray(list, testdata.data.data(), testdata_len);
+        return list;
     }
 
     auto pointerLinkedListFromTestData() const -> CxList * {
         auto list = autofree(cxPointerLinkedListCreate(&testingAllocator, cx_cmp_int));
+        // note: cannot use cxListAddArray() because we don't have a list of pointers
         cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]);
         return list;
     }
 
     auto arrayListFromTestData() const -> CxList * {
         auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len));
-        // TODO: replace with cxListAddArray
-        cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]);
+        cxListAddArray(list, testdata.data.data(), testdata_len);
         return list;
     }
 
@@ -796,18 +789,6 @@
     verifyCreate(list);
 }
 
-TEST_F(LinkedList, cxLinkedListFromArray) {
-    CxList *expected = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
-    cx_for_n (i, testdata_len) cxListAdd(expected, &testdata.data[i]);
-    CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cx_cmp_int, sizeof(int),
-                                                  testdata_len, testdata.data.data()));
-    ASSERT_NE(list, nullptr);
-    EXPECT_EQ(list->itemsize, sizeof(int));
-    EXPECT_EQ(list->capacity, (size_t) -1);
-    EXPECT_EQ(list->size, testdata_len);
-    EXPECT_EQ(cxListCompare(list, expected), 0);
-}
-
 TEST_F(ArrayList, cxArrayListCreate) {
     CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8));
     ASSERT_NE(list, nullptr);
@@ -905,13 +886,15 @@
 
 TEST_F(LinkedList, InsertViaIterator) {
     int fivenums[] = {0, 1, 2, 3, 4, 5};
-    CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cx_cmp_int, sizeof(int), 5, fivenums));
+    CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)));
+    cxListAddArray(list, fivenums, 5);
     verifyInsertViaIterator(list);
 }
 
 TEST_F(PointerLinkedList, InsertViaIterator) {
     int fivenums[] = {0, 1, 2, 3, 4, 5};
     CxList *list = autofree(cxPointerLinkedListCreate(&testingAllocator, cx_cmp_int));
+    // note: don't use cxListAddArray() here, because we don't have a list of pointers
     cx_for_n (i, 5) cxListAdd(list, &fivenums[i]);
     verifyInsertViaIterator(list);
 }
@@ -919,8 +902,7 @@
 TEST_F(ArrayList, InsertViaIterator) {
     int fivenums[] = {0, 1, 2, 3, 4, 5};
     CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4));
-    // TODO: replace with cxListAddArray
-    cx_for_n (i, 5) cxListAdd(list, &fivenums[i]);
+    cxListAddArray(list, fivenums, 5);
     verifyInsertViaIterator(list);
 }
 

mercurial