Wed, 23 Nov 2022 22:40:55 +0100
#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 |
1.1 --- a/src/array_list.c Sun Nov 20 21:08:36 2022 +0100 1.2 +++ b/src/array_list.c Wed Nov 23 22:40:55 2022 +0100 1.3 @@ -185,6 +185,29 @@ 1.4 ); 1.5 } 1.6 1.7 +static size_t cx_arl_add_array( 1.8 + struct cx_list_s *list, 1.9 + void const *array, 1.10 + size_t n 1.11 +) { 1.12 + cx_array_list *arl = (cx_array_list *) list; 1.13 + if (CX_ARRAY_COPY_SUCCESS == cx_array_copy( 1.14 + &arl->data, 1.15 + &list->size, 1.16 + &list->capacity, 1.17 + list->size, 1.18 + array, 1.19 + list->itemsize, 1.20 + n, 1.21 + &arl->reallocator 1.22 + )) { 1.23 + return n; 1.24 + } else { 1.25 + // array list implementation is "all or nothing" 1.26 + return 0; 1.27 + } 1.28 +} 1.29 + 1.30 static int cx_arl_insert( 1.31 struct cx_list_s *list, 1.32 size_t index, 1.33 @@ -385,6 +408,7 @@ 1.34 static cx_list_class cx_array_list_class = { 1.35 cx_arl_destructor, 1.36 cx_arl_add, 1.37 + cx_arl_add_array, 1.38 cx_arl_insert, 1.39 cx_arl_insert_iter, 1.40 cx_arl_remove,
2.1 --- a/src/cx/linked_list.h Sun Nov 20 21:08:36 2022 +0100 2.2 +++ b/src/cx/linked_list.h Wed Nov 23 22:40:55 2022 +0100 2.3 @@ -80,27 +80,6 @@ 2.4 ) __attribute__((__nonnull__)); 2.5 2.6 /** 2.7 - * Creates a linked list using the data from an array. 2.8 - * 2.9 - * @remark Elements added to the list are copied, therefore a possible destructor 2.10 - * MUST NOT free the memory pointed to by its argument. 2.11 - * 2.12 - * @param allocator the allocator for allocating the list nodes 2.13 - * @param comparator the comparator for the elements 2.14 - * @param item_size the size of one item in the array 2.15 - * @param num_items the number of items 2.16 - * @param array the array data 2.17 - * @return the created list 2.18 - */ 2.19 -CxList *cxLinkedListFromArray( 2.20 - CxAllocator const *allocator, 2.21 - CxListComparator comparator, 2.22 - size_t item_size, 2.23 - size_t num_items, 2.24 - void const *array 2.25 -) __attribute__((__nonnull__)); 2.26 - 2.27 -/** 2.28 * Finds the node at a certain index. 2.29 * 2.30 * This function can be used to start at an arbitrary position within the list.
3.1 --- a/src/cx/list.h Sun Nov 20 21:08:36 2022 +0100 3.2 +++ b/src/cx/list.h Wed Nov 23 22:40:55 2022 +0100 3.3 @@ -130,6 +130,15 @@ 3.4 ); 3.5 3.6 /** 3.7 + * Member function for adding multiple elements. 3.8 + */ 3.9 + size_t (*add_array)( 3.10 + struct cx_list_s *list, 3.11 + void const *array, 3.12 + size_t n 3.13 + ); 3.14 + 3.15 + /** 3.16 * Member function for inserting an element. 3.17 */ 3.18 int (*insert)( 3.19 @@ -209,6 +218,7 @@ 3.20 * @param list the list 3.21 * @param elem a pointer to the element to add 3.22 * @return zero on success, non-zero on memory allocation failure 3.23 + * @see cxListAddArray() 3.24 */ 3.25 __attribute__((__nonnull__)) 3.26 static inline int cxListAdd( 3.27 @@ -219,6 +229,28 @@ 3.28 } 3.29 3.30 /** 3.31 + * Adds multiple items to the end of the list. 3.32 + * 3.33 + * This method is more efficient than invoking cxListAdd() multiple times. 3.34 + * 3.35 + * If there is not enough memory to add all elements, the returned value is 3.36 + * less than \p n. 3.37 + * 3.38 + * @param list the list 3.39 + * @param array a pointer to the elements to add 3.40 + * @param n the number of elements to add 3.41 + * @return the number of added elements 3.42 + */ 3.43 +__attribute__((__nonnull__)) 3.44 +static inline size_t cxListAddArray( 3.45 + CxList *list, 3.46 + void const *array, 3.47 + size_t n 3.48 +) { 3.49 + return list->cl->add_array(list, array, n); 3.50 +} 3.51 + 3.52 +/** 3.53 * Inserts an item at the specified index. 3.54 * 3.55 * If \p index equals the list \c size, this is effectively cxListAdd().
4.1 --- a/src/linked_list.c Sun Nov 20 21:08:36 2022 +0100 4.2 +++ b/src/linked_list.c Wed Nov 23 22:40:55 2022 +0100 4.3 @@ -540,6 +540,20 @@ 4.4 return cx_ll_insert(list, list->size, elem); 4.5 } 4.6 4.7 +static size_t cx_ll_add_array( 4.8 + struct cx_list_s *list, 4.9 + void const *array, 4.10 + size_t n 4.11 +) { 4.12 + // TODO: redirect to cx_ll_insert_array 4.13 + cx_for_n (i, n) { 4.14 + if (cx_ll_add(list, ((char const *) array) + i * list->itemsize)) { 4.15 + return i; 4.16 + } 4.17 + } 4.18 + return n; 4.19 +} 4.20 + 4.21 static int cx_pll_insert( 4.22 struct cx_list_s *list, 4.23 size_t index, 4.24 @@ -727,6 +741,7 @@ 4.25 static cx_list_class cx_linked_list_class = { 4.26 cx_ll_destructor, 4.27 cx_ll_add, 4.28 + cx_ll_add_array, 4.29 cx_ll_insert, 4.30 cx_ll_insert_iter, 4.31 cx_ll_remove, 4.32 @@ -741,6 +756,7 @@ 4.33 static cx_list_class cx_pointer_linked_list_class = { 4.34 cx_ll_destructor, 4.35 cx_pll_add, 4.36 + cx_ll_add_array, 4.37 cx_pll_insert, 4.38 cx_pll_insert_iter, 4.39 cx_ll_remove, 4.40 @@ -786,22 +802,3 @@ 4.41 4.42 return (CxList *) list; 4.43 } 4.44 - 4.45 -CxList *cxLinkedListFromArray( 4.46 - CxAllocator const *allocator, 4.47 - CxListComparator comparator, 4.48 - size_t item_size, 4.49 - size_t num_items, 4.50 - void const *array 4.51 -) { 4.52 - CxList *list = cxLinkedListCreate(allocator, comparator, item_size); 4.53 - if (list == NULL) return NULL; 4.54 - cx_for_n (i, num_items) { 4.55 - if (0 != cxListAdd(list, ((const unsigned char *) array) + i * item_size)) { 4.56 - cx_ll_destructor(list); 4.57 - cxFree(allocator, list); 4.58 - return NULL; 4.59 - } 4.60 - } 4.61 - return list; 4.62 -}
5.1 --- a/test/test_list.cpp Sun Nov 20 21:08:36 2022 +0100 5.2 +++ b/test/test_list.cpp Wed Nov 23 22:40:55 2022 +0100 5.3 @@ -569,28 +569,21 @@ 5.4 } 5.5 5.6 auto linkedListFromTestData() const -> CxList * { 5.7 - // TODO: replace with cxListAddArray 5.8 - return autofree( 5.9 - cxLinkedListFromArray( 5.10 - &testingAllocator, 5.11 - cx_cmp_int, 5.12 - sizeof(int), 5.13 - testdata_len, 5.14 - testdata.data.data() 5.15 - ) 5.16 - ); 5.17 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 5.18 + cxListAddArray(list, testdata.data.data(), testdata_len); 5.19 + return list; 5.20 } 5.21 5.22 auto pointerLinkedListFromTestData() const -> CxList * { 5.23 auto list = autofree(cxPointerLinkedListCreate(&testingAllocator, cx_cmp_int)); 5.24 + // note: cannot use cxListAddArray() because we don't have a list of pointers 5.25 cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 5.26 return list; 5.27 } 5.28 5.29 auto arrayListFromTestData() const -> CxList * { 5.30 auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 5.31 - // TODO: replace with cxListAddArray 5.32 - cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 5.33 + cxListAddArray(list, testdata.data.data(), testdata_len); 5.34 return list; 5.35 } 5.36 5.37 @@ -796,18 +789,6 @@ 5.38 verifyCreate(list); 5.39 } 5.40 5.41 -TEST_F(LinkedList, cxLinkedListFromArray) { 5.42 - CxList *expected = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 5.43 - cx_for_n (i, testdata_len) cxListAdd(expected, &testdata.data[i]); 5.44 - CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cx_cmp_int, sizeof(int), 5.45 - testdata_len, testdata.data.data())); 5.46 - ASSERT_NE(list, nullptr); 5.47 - EXPECT_EQ(list->itemsize, sizeof(int)); 5.48 - EXPECT_EQ(list->capacity, (size_t) -1); 5.49 - EXPECT_EQ(list->size, testdata_len); 5.50 - EXPECT_EQ(cxListCompare(list, expected), 0); 5.51 -} 5.52 - 5.53 TEST_F(ArrayList, cxArrayListCreate) { 5.54 CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 5.55 ASSERT_NE(list, nullptr); 5.56 @@ -905,13 +886,15 @@ 5.57 5.58 TEST_F(LinkedList, InsertViaIterator) { 5.59 int fivenums[] = {0, 1, 2, 3, 4, 5}; 5.60 - CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cx_cmp_int, sizeof(int), 5, fivenums)); 5.61 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 5.62 + cxListAddArray(list, fivenums, 5); 5.63 verifyInsertViaIterator(list); 5.64 } 5.65 5.66 TEST_F(PointerLinkedList, InsertViaIterator) { 5.67 int fivenums[] = {0, 1, 2, 3, 4, 5}; 5.68 CxList *list = autofree(cxPointerLinkedListCreate(&testingAllocator, cx_cmp_int)); 5.69 + // note: don't use cxListAddArray() here, because we don't have a list of pointers 5.70 cx_for_n (i, 5) cxListAdd(list, &fivenums[i]); 5.71 verifyInsertViaIterator(list); 5.72 } 5.73 @@ -919,8 +902,7 @@ 5.74 TEST_F(ArrayList, InsertViaIterator) { 5.75 int fivenums[] = {0, 1, 2, 3, 4, 5}; 5.76 CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 5.77 - // TODO: replace with cxListAddArray 5.78 - cx_for_n (i, 5) cxListAdd(list, &fivenums[i]); 5.79 + cxListAddArray(list, fivenums, 5); 5.80 verifyInsertViaIterator(list); 5.81 } 5.82