Thu, 26 Jan 2023 20:59:36 +0100
add new pointer list wrapper - resolves #234
since we need a thread local variable, this drops C99 support
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/array_list.c | file | annotate | diff | comparison | revisions | |
src/cx/iterator.h | file | annotate | diff | comparison | revisions | |
src/cx/list.h | file | annotate | diff | comparison | revisions | |
src/linked_list.c | file | annotate | diff | comparison | revisions | |
src/list.c | file | annotate | diff | comparison | revisions | |
test/test_list.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/CMakeLists.txt Wed Jan 25 19:19:29 2023 +0100 1.2 +++ b/CMakeLists.txt Thu Jan 26 20:59:36 2023 +0100 1.3 @@ -3,7 +3,7 @@ 1.4 1.5 # Configuration 1.6 set(CMAKE_C_STANDARD 11) 1.7 -set(CMAKE_C_STANDARD_REQUIRED 99) 1.8 +set(CMAKE_C_STANDARD_REQUIRED 11) 1.9 1.10 option(GCC_MORE_WARNINGS "Enable -Wall -Wextra -pedantic when using gcc." OFF) 1.11 if (GCC_MORE_WARNINGS AND CMAKE_COMPILER_IS_GNUCC)
2.1 --- a/src/array_list.c Wed Jan 25 19:19:29 2023 +0100 2.2 +++ b/src/array_list.c Thu Jan 26 20:59:36 2023 +0100 2.3 @@ -224,6 +224,14 @@ 2.4 } 2.5 } 2.6 2.7 +static int cx_arl_insert_element( 2.8 + struct cx_list_s *list, 2.9 + size_t index, 2.10 + void const *element 2.11 +) { 2.12 + return 1 != cx_arl_insert_array(list, index, element, 1); 2.13 +} 2.14 + 2.15 static int cx_arl_insert_iter( 2.16 struct cx_mut_iterator_s *iter, 2.17 void const *elem, 2.18 @@ -231,11 +239,10 @@ 2.19 ) { 2.20 struct cx_list_s *list = iter->src_handle; 2.21 if (iter->index < list->size) { 2.22 - int result = 1 != cx_arl_insert_array( 2.23 + int result = cx_arl_insert_element( 2.24 list, 2.25 iter->index + 1 - prepend, 2.26 - elem, 2.27 - 1 2.28 + elem 2.29 ); 2.30 if (result == 0 && prepend != 0) { 2.31 iter->index++; 2.32 @@ -243,7 +250,7 @@ 2.33 } 2.34 return result; 2.35 } else { 2.36 - int result = 1 != cx_arl_insert_array(list, list->size, elem, 1); 2.37 + int result = cx_arl_insert_element(list, list->size, elem); 2.38 iter->index = list->size; 2.39 return result; 2.40 } 2.41 @@ -407,6 +414,7 @@ 2.42 2.43 static cx_list_class cx_array_list_class = { 2.44 cx_arl_destructor, 2.45 + cx_arl_insert_element, 2.46 cx_arl_insert_array, 2.47 cx_arl_insert_iter, 2.48 cx_arl_remove,
3.1 --- a/src/cx/iterator.h Wed Jan 25 19:19:29 2023 +0100 3.2 +++ b/src/cx/iterator.h Thu Jan 26 20:59:36 2023 +0100 3.3 @@ -56,6 +56,12 @@ 3.4 void *(*current)(void const *); 3.5 3.6 /** 3.7 + * Original implementation in case the function needs to be wrapped. 3.8 + */ 3.9 + __attribute__ ((__nonnull__)) 3.10 + void *(*current_impl)(void const *); 3.11 + 3.12 + /** 3.13 * Advances the iterator. 3.14 */ 3.15 __attribute__ ((__nonnull__))
4.1 --- a/src/cx/list.h Wed Jan 25 19:19:29 2023 +0100 4.2 +++ b/src/cx/list.h Thu Jan 26 20:59:36 2023 +0100 4.3 @@ -65,7 +65,11 @@ 4.4 /** 4.5 * The list class definition. 4.6 */ 4.7 - cx_list_class *cl; 4.8 + cx_list_class const *cl; 4.9 + /** 4.10 + * The actual implementation in case the list class is delegating. 4.11 + */ 4.12 + cx_list_class const *climpl; 4.13 /** 4.14 * The allocator to use. 4.15 */ 4.16 @@ -122,6 +126,16 @@ 4.17 void (*destructor)(struct cx_list_s *list); 4.18 4.19 /** 4.20 + * Member function for inserting a single elements. 4.21 + * Implementors SHOULD see to performant implementations for corner cases. 4.22 + */ 4.23 + int (*insert_element)( 4.24 + struct cx_list_s *list, 4.25 + size_t index, 4.26 + void const *data 4.27 + ); 4.28 + 4.29 + /** 4.30 * Member function for inserting multiple elements. 4.31 * Implementors SHOULD see to performant implementations for corner cases. 4.32 */ 4.33 @@ -198,6 +212,43 @@ 4.34 typedef struct cx_list_s CxList; 4.35 4.36 /** 4.37 + * Advises the list to store copies of the objects (default mode of operation). 4.38 + * 4.39 + * Retrieving objects from this list will yield pointers to the copies stored 4.40 + * within this list. 4.41 + * 4.42 + * @param list the list 4.43 + * @see cxListStorePointers() 4.44 + */ 4.45 +__attribute__((__nonnull__)) 4.46 +void cxListStoreObjects(CxList *list); 4.47 + 4.48 +/** 4.49 + * Advises the list to only store pointers to the objects. 4.50 + * 4.51 + * Retrieving objects from this list will yield the original pointers stored. 4.52 + * 4.53 + * @note This function forcibly sets the element size to the size of a pointer. 4.54 + * Invoking this function on a non-empty list that already stores copies of 4.55 + * objects is undefined. 4.56 + * 4.57 + * @param list the list 4.58 + * @see cxListStoreObjects() 4.59 + */ 4.60 +__attribute__((__nonnull__)) 4.61 +void cxListStorePointers(CxList *list); 4.62 + 4.63 +/** 4.64 + * Returns true, if this list is storing pointers instead of the actual data. 4.65 + * 4.66 + * @param list 4.67 + * @return 4.68 + * @see cxListStorePointers() 4.69 + */ 4.70 +__attribute__((__nonnull__)) 4.71 +bool cxListIsStoringPointers(CxList *list); 4.72 + 4.73 +/** 4.74 * Adds an item to the end of the list. 4.75 * 4.76 * @param list the list 4.77 @@ -210,7 +261,7 @@ 4.78 CxList *list, 4.79 void const *elem 4.80 ) { 4.81 - return list->cl->insert_array(list, list->size, elem, 1) != 1; 4.82 + return list->cl->insert_element(list, list->size, elem); 4.83 } 4.84 4.85 /** 4.86 @@ -221,6 +272,9 @@ 4.87 * If there is not enough memory to add all elements, the returned value is 4.88 * less than \p n. 4.89 * 4.90 + * If this list is storing pointers instead of objects \p array is expected to 4.91 + * be an array of pointers. 4.92 + * 4.93 * @param list the list 4.94 * @param array a pointer to the elements to add 4.95 * @param n the number of elements to add 4.96 @@ -254,7 +308,7 @@ 4.97 size_t index, 4.98 void const *elem 4.99 ) { 4.100 - return list->cl->insert_array(list, index, elem, 1) != 1; 4.101 + return list->cl->insert_element(list, index, elem); 4.102 } 4.103 4.104 /** 4.105 @@ -267,6 +321,9 @@ 4.106 * If there is not enough memory to add all elements, the returned value is 4.107 * less than \p n. 4.108 * 4.109 + * If this list is storing pointers instead of objects \p array is expected to 4.110 + * be an array of pointers. 4.111 + * 4.112 * @param list the list 4.113 * @param index the index where to add the elements 4.114 * @param array a pointer to the elements to add
5.1 --- a/src/linked_list.c Wed Jan 25 19:19:29 2023 +0100 5.2 +++ b/src/linked_list.c Thu Jan 26 20:59:36 2023 +0100 5.3 @@ -546,6 +546,14 @@ 5.4 return n; 5.5 } 5.6 5.7 +static int cx_ll_insert_element( 5.8 + struct cx_list_s *list, 5.9 + size_t index, 5.10 + void const *element 5.11 +) { 5.12 + return 1 != cx_ll_insert_array(list, index, element, 1); 5.13 +} 5.14 + 5.15 static int cx_ll_remove( 5.16 struct cx_list_s *list, 5.17 size_t index 5.18 @@ -682,7 +690,7 @@ 5.19 iter->index += prepend * (0 == result); 5.20 return result; 5.21 } else { 5.22 - int result = cx_ll_insert_array(list, list->size, elem, 1) != 1; 5.23 + int result = cx_ll_insert_element(list, list->size, elem); 5.24 iter->index = list->size; 5.25 return result; 5.26 } 5.27 @@ -702,6 +710,7 @@ 5.28 5.29 static cx_list_class cx_linked_list_class = { 5.30 cx_ll_destructor, 5.31 + cx_ll_insert_element, 5.32 cx_ll_insert_array, 5.33 cx_ll_insert_iter, 5.34 cx_ll_remove,
6.1 --- a/src/list.c Wed Jan 25 19:19:29 2023 +0100 6.2 +++ b/src/list.c Thu Jan 26 20:59:36 2023 +0100 6.3 @@ -30,6 +30,158 @@ 6.4 6.5 #include <string.h> 6.6 6.7 +// <editor-fold desc="Store Pointers Functionality"> 6.8 + 6.9 +static _Thread_local CxListComparator cx_pl_cmpfunc_impl; 6.10 + 6.11 +static int cx_pl_cmpfunc( 6.12 + void const *l, 6.13 + void const *r 6.14 +) { 6.15 + void *const *lptr = l; 6.16 + void *const *rptr = r; 6.17 + void const *left = lptr == NULL ? NULL : *lptr; 6.18 + void const *right = rptr == NULL ? NULL : *rptr; 6.19 + return cx_pl_cmpfunc_impl(left, right); 6.20 +} 6.21 + 6.22 +static void cx_pl_hack_cmpfunc(struct cx_list_s const *list) { 6.23 + // cast away const - this is the hacky thing 6.24 + struct cx_list_s *l = (struct cx_list_s *) list; 6.25 + cx_pl_cmpfunc_impl = l->cmpfunc; 6.26 + l->cmpfunc = cx_pl_cmpfunc; 6.27 +} 6.28 + 6.29 +static void cx_pl_unhack_cmpfunc(struct cx_list_s const *list) { 6.30 + // cast away const - this is the hacky thing 6.31 + struct cx_list_s *l = (struct cx_list_s *) list; 6.32 + l->cmpfunc = cx_pl_cmpfunc_impl; 6.33 +} 6.34 + 6.35 +static void cx_pl_destructor(struct cx_list_s *list) { 6.36 + list->climpl->destructor(list); 6.37 +} 6.38 + 6.39 +static int cx_pl_insert_element( 6.40 + struct cx_list_s *list, 6.41 + size_t index, 6.42 + void const *element 6.43 +) { 6.44 + return list->climpl->insert_element(list, index, &element); 6.45 +} 6.46 + 6.47 +static size_t cx_pl_insert_array( 6.48 + struct cx_list_s *list, 6.49 + size_t index, 6.50 + void const *array, 6.51 + size_t n 6.52 +) { 6.53 + return list->climpl->insert_array(list, index, array, n); 6.54 +} 6.55 + 6.56 +static int cx_pl_insert_iter( 6.57 + struct cx_mut_iterator_s *iter, 6.58 + void const *elem, 6.59 + int prepend 6.60 +) { 6.61 + struct cx_list_s *list = iter->src_handle; 6.62 + return list->climpl->insert_iter(iter, &elem, prepend); 6.63 +} 6.64 + 6.65 +static int cx_pl_remove( 6.66 + struct cx_list_s *list, 6.67 + size_t index 6.68 +) { 6.69 + return list->climpl->remove(list, index); 6.70 +} 6.71 + 6.72 +static void *cx_pl_at( 6.73 + struct cx_list_s const *list, 6.74 + size_t index 6.75 +) { 6.76 + void **ptr = list->climpl->at(list, index); 6.77 + return ptr == NULL ? NULL : *ptr; 6.78 +} 6.79 + 6.80 +static size_t cx_pl_find( 6.81 + struct cx_list_s const *list, 6.82 + void const *elem 6.83 +) { 6.84 + cx_pl_hack_cmpfunc(list); 6.85 + size_t ret = list->climpl->find(list, &elem); 6.86 + cx_pl_unhack_cmpfunc(list); 6.87 + return ret; 6.88 +} 6.89 + 6.90 +static void cx_pl_sort(struct cx_list_s *list) { 6.91 + cx_pl_hack_cmpfunc(list); 6.92 + list->climpl->sort(list); 6.93 + cx_pl_unhack_cmpfunc(list); 6.94 +} 6.95 + 6.96 +static int cx_pl_compare( 6.97 + struct cx_list_s const *list, 6.98 + struct cx_list_s const *other 6.99 +) { 6.100 + cx_pl_hack_cmpfunc(list); 6.101 + int ret = list->climpl->compare(list, other); 6.102 + cx_pl_unhack_cmpfunc(list); 6.103 + return ret; 6.104 +} 6.105 + 6.106 +static void cx_pl_reverse(struct cx_list_s *list) { 6.107 + list->climpl->reverse(list); 6.108 +} 6.109 + 6.110 +static void *cx_pl_iter_current(void const *it) { 6.111 + struct cx_iterator_s const *iter = it; 6.112 + void **ptr = iter->base.current_impl(it); 6.113 + return ptr == NULL ? NULL : *ptr; 6.114 +} 6.115 + 6.116 +static struct cx_iterator_s cx_pl_iterator( 6.117 + struct cx_list_s const *list, 6.118 + size_t index 6.119 +) { 6.120 + struct cx_iterator_s iter = list->climpl->iterator(list, index); 6.121 + iter.base.current_impl = iter.base.current; 6.122 + iter.base.current = cx_pl_iter_current; 6.123 + return iter; 6.124 +} 6.125 + 6.126 +static cx_list_class cx_pointer_list_class = { 6.127 + cx_pl_destructor, 6.128 + cx_pl_insert_element, 6.129 + cx_pl_insert_array, 6.130 + cx_pl_insert_iter, 6.131 + cx_pl_remove, 6.132 + cx_pl_at, 6.133 + cx_pl_find, 6.134 + cx_pl_sort, 6.135 + cx_pl_compare, 6.136 + cx_pl_reverse, 6.137 + cx_pl_iterator, 6.138 +}; 6.139 + 6.140 +void cxListStoreObjects(CxList *list) { 6.141 + if (list->climpl != NULL) { 6.142 + list->cl = list->climpl; 6.143 + list->climpl = NULL; 6.144 + } 6.145 +} 6.146 + 6.147 +void cxListStorePointers(CxList *list) { 6.148 + list->itemsize = sizeof(void *); 6.149 + list->climpl = list->cl; 6.150 + list->cl = &cx_pointer_list_class; 6.151 +} 6.152 + 6.153 +bool cxListIsStoringPointers(CxList *list) { 6.154 + return list->climpl != NULL; 6.155 +} 6.156 + 6.157 +// </editor-fold> 6.158 + 6.159 void cxListDestroy(CxList *list) { 6.160 switch (list->content_destructor_type) { 6.161 case CX_DESTRUCTOR_SIMPLE: {
7.1 --- a/test/test_list.cpp Wed Jan 25 19:19:29 2023 +0100 7.2 +++ b/test/test_list.cpp Thu Jan 26 20:59:36 2023 +0100 7.3 @@ -573,6 +573,14 @@ 7.4 return list; 7.5 } 7.6 7.7 + auto pointerLinkedListFromTestData() const -> CxList * { 7.8 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 7.9 + cxListStorePointers(list); 7.10 + // note: cannot use cxListAddArray() because we don't have a list of pointers 7.11 + cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 7.12 + return list; 7.13 + } 7.14 + 7.15 auto arrayListFromTestData() const -> CxList * { 7.16 auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 7.17 cxListAddArray(list, testdata.data.data(), testdata_len); 7.18 @@ -625,21 +633,37 @@ 7.19 EXPECT_EQ(*(int *) cxListAt(list, 3), 42); 7.20 } 7.21 7.22 - static void verifyInsertArray(CxList *list) { 7.23 + static void verifyInsertArray( 7.24 + CxList *list, 7.25 + bool pointers = false 7.26 + ) { 7.27 int a[5] = {5, 47, 11, 13, 42}; 7.28 int b[5] = {9, 18, 72, 50, 7}; 7.29 + int *aptr[5]; 7.30 + int *bptr[5]; 7.31 + cx_for_n(i, 5) { 7.32 + aptr[i] = &a[i]; 7.33 + bptr[i] = &b[i]; 7.34 + } 7.35 7.36 size_t inserted; 7.37 7.38 - inserted = cxListInsertArray(list, 0, a, 5); 7.39 + if (pointers) { 7.40 + inserted = cxListInsertArray(list, 0, aptr, 5); 7.41 + } else { 7.42 + inserted = cxListInsertArray(list, 0, a, 5); 7.43 + } 7.44 EXPECT_EQ(inserted, 5); 7.45 EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 7.46 EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 7.47 EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 7.48 EXPECT_EQ(*(int *) cxListAt(list, 3), 13); 7.49 EXPECT_EQ(*(int *) cxListAt(list, 4), 42); 7.50 - 7.51 - inserted = cxListInsertArray(list, 3, b, 5); 7.52 + if (pointers) { 7.53 + inserted = cxListInsertArray(list, 3, bptr, 5); 7.54 + } else { 7.55 + inserted = cxListInsertArray(list, 3, b, 5); 7.56 + } 7.57 EXPECT_EQ(inserted, 5); 7.58 EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 7.59 EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 7.60 @@ -787,9 +811,26 @@ 7.61 class LinkedList : public HighLevelTest { 7.62 }; 7.63 7.64 +class PointerLinkedList : public HighLevelTest { 7.65 +}; 7.66 + 7.67 class ArrayList : public HighLevelTest { 7.68 }; 7.69 7.70 +TEST_F(PointerLinkedList, cxListStorePointers) { 7.71 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47)); 7.72 + EXPECT_FALSE(cxListIsStoringPointers(list)); 7.73 + cxListStorePointers(list); 7.74 + EXPECT_EQ(list->itemsize, sizeof(void *)); 7.75 + EXPECT_NE(list->cl, nullptr); 7.76 + EXPECT_NE(list->climpl, nullptr); 7.77 + EXPECT_TRUE(cxListIsStoringPointers(list)); 7.78 + cxListStoreObjects(list); 7.79 + EXPECT_NE(list->cl, nullptr); 7.80 + EXPECT_EQ(list->climpl, nullptr); 7.81 + EXPECT_FALSE(cxListIsStoringPointers(list)); 7.82 +} 7.83 + 7.84 TEST_F(LinkedList, cxLinkedListCreate) { 7.85 CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 7.86 ASSERT_NE(list, nullptr); 7.87 @@ -807,12 +848,18 @@ 7.88 } 7.89 7.90 TEST_F(LinkedList, cxListAdd) { 7.91 - CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 7.92 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 7.93 verifyAdd(list, false); 7.94 } 7.95 7.96 +TEST_F(PointerLinkedList, cxListAdd) { 7.97 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 7.98 + cxListStorePointers(list); 7.99 + verifyAdd(list, true); 7.100 +} 7.101 + 7.102 TEST_F(ArrayList, cxListAdd) { 7.103 - CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 7.104 + auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 7.105 verifyAdd(list, false); 7.106 } 7.107 7.108 @@ -820,6 +867,12 @@ 7.109 verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 7.110 } 7.111 7.112 +TEST_F(PointerLinkedList, cxListInsert) { 7.113 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 7.114 + cxListStorePointers(list); 7.115 + verifyInsert(list); 7.116 +} 7.117 + 7.118 TEST_F(ArrayList, cxListInsert) { 7.119 verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2))); 7.120 } 7.121 @@ -828,6 +881,12 @@ 7.122 verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 7.123 } 7.124 7.125 +TEST_F(PointerLinkedList, cxListInsertArray) { 7.126 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 7.127 + cxListStorePointers(list); 7.128 + verifyInsertArray(list, true); 7.129 +} 7.130 + 7.131 TEST_F(ArrayList, cxListInsertArray) { 7.132 verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4))); 7.133 } 7.134 @@ -836,6 +895,10 @@ 7.135 verifyRemove(linkedListFromTestData()); 7.136 } 7.137 7.138 +TEST_F(PointerLinkedList, cxListRemove) { 7.139 + verifyRemove(pointerLinkedListFromTestData()); 7.140 +} 7.141 + 7.142 TEST_F(ArrayList, cxListRemove) { 7.143 verifyRemove(arrayListFromTestData()); 7.144 } 7.145 @@ -844,6 +907,10 @@ 7.146 verifyAt(linkedListFromTestData()); 7.147 } 7.148 7.149 +TEST_F(PointerLinkedList, cxListAt) { 7.150 + verifyAt(pointerLinkedListFromTestData()); 7.151 +} 7.152 + 7.153 TEST_F(ArrayList, cxListAt) { 7.154 verifyAt(arrayListFromTestData()); 7.155 } 7.156 @@ -852,6 +919,10 @@ 7.157 verifyFind(linkedListFromTestData()); 7.158 } 7.159 7.160 +TEST_F(PointerLinkedList, cxListFind) { 7.161 + verifyFind(pointerLinkedListFromTestData()); 7.162 +} 7.163 + 7.164 TEST_F(ArrayList, cxListFind) { 7.165 verifyFind(arrayListFromTestData()); 7.166 } 7.167 @@ -860,6 +931,10 @@ 7.168 verifySort(linkedListFromTestData()); 7.169 } 7.170 7.171 +TEST_F(PointerLinkedList, cxListSort) { 7.172 + verifySort(pointerLinkedListFromTestData()); 7.173 +} 7.174 + 7.175 TEST_F(ArrayList, cxListSort) { 7.176 verifySort(arrayListFromTestData()); 7.177 } 7.178 @@ -868,6 +943,10 @@ 7.179 verifyIterator(linkedListFromTestData()); 7.180 } 7.181 7.182 +TEST_F(PointerLinkedList, Iterator) { 7.183 + verifyIterator(pointerLinkedListFromTestData()); 7.184 +} 7.185 + 7.186 TEST_F(ArrayList, Iterator) { 7.187 verifyIterator(arrayListFromTestData()); 7.188 } 7.189 @@ -879,6 +958,15 @@ 7.190 verifyInsertViaIterator(list); 7.191 } 7.192 7.193 +TEST_F(PointerLinkedList, InsertViaIterator) { 7.194 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 7.195 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 7.196 + cxListStorePointers(list); 7.197 + // note: cannot use cxListAddArray() because we don't have a list of pointers 7.198 + cx_for_n(i, 5) cxListAdd(list, &fivenums[i]); 7.199 + verifyInsertViaIterator(list); 7.200 +} 7.201 + 7.202 TEST_F(ArrayList, InsertViaIterator) { 7.203 int fivenums[] = {0, 1, 2, 3, 4, 5}; 7.204 CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 7.205 @@ -890,6 +978,10 @@ 7.206 verifyReverse(linkedListFromTestData()); 7.207 } 7.208 7.209 +TEST_F(PointerLinkedList, cxListReverse) { 7.210 + verifyReverse(pointerLinkedListFromTestData()); 7.211 +} 7.212 + 7.213 TEST_F(ArrayList, cxListReverse) { 7.214 verifyReverse(arrayListFromTestData()); 7.215 } 7.216 @@ -900,20 +992,86 @@ 7.217 verifyCompare(left, right); 7.218 } 7.219 7.220 +TEST_F(LinkedList, cxListCompareWithPtrList) { 7.221 + auto left = linkedListFromTestData(); 7.222 + auto right = pointerLinkedListFromTestData(); 7.223 + verifyCompare(left, right); 7.224 +} 7.225 + 7.226 TEST_F(LinkedList, cxListCompareWithArrayList) { 7.227 auto left = linkedListFromTestData(); 7.228 auto right = arrayListFromTestData(); 7.229 verifyCompare(left, right); 7.230 } 7.231 7.232 +TEST_F(PointerLinkedList, cxListCompare) { 7.233 + auto left = pointerLinkedListFromTestData(); 7.234 + auto right = pointerLinkedListFromTestData(); 7.235 + verifyCompare(left, right); 7.236 +} 7.237 + 7.238 +TEST_F(PointerLinkedList, cxListCompareWithNormalList) { 7.239 + auto left = pointerLinkedListFromTestData(); 7.240 + auto right = linkedListFromTestData(); 7.241 + verifyCompare(left, right); 7.242 +} 7.243 + 7.244 +TEST_F(PointerLinkedList, cxListCompareWithArrayList) { 7.245 + auto left = pointerLinkedListFromTestData(); 7.246 + auto right = arrayListFromTestData(); 7.247 + verifyCompare(left, right); 7.248 +} 7.249 + 7.250 TEST_F(ArrayList, cxListCompare) { 7.251 auto left = arrayListFromTestData(); 7.252 auto right = arrayListFromTestData(); 7.253 verifyCompare(left, right); 7.254 } 7.255 7.256 -TEST_F(ArrayList, cxListCompareWithLinkedList) { 7.257 +TEST_F(ArrayList, cxListCompareWithPtrList) { 7.258 + auto left = arrayListFromTestData(); 7.259 + auto right = pointerLinkedListFromTestData(); 7.260 + verifyCompare(left, right); 7.261 +} 7.262 + 7.263 +TEST_F(ArrayList, cxListCompareWithNormalList) { 7.264 auto left = arrayListFromTestData(); 7.265 auto right = linkedListFromTestData(); 7.266 verifyCompare(left, right); 7.267 } 7.268 + 7.269 +TEST_F(PointerLinkedList, NoDestructor) { 7.270 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 7.271 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 7.272 + cxListStorePointers(list); 7.273 + cxListAdd(list, item); 7.274 + ASSERT_FALSE(testingAllocator.verify()); 7.275 + cxListDestroy(list); 7.276 + EXPECT_FALSE(testingAllocator.verify()); 7.277 + cxFree(&testingAllocator, item); 7.278 + EXPECT_TRUE(testingAllocator.verify()); 7.279 +} 7.280 + 7.281 +TEST_F(PointerLinkedList, SimpleDestructor) { 7.282 + int item = 0; 7.283 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 7.284 + cxListStorePointers(list); 7.285 + list->content_destructor_type = CX_DESTRUCTOR_SIMPLE; 7.286 + list->simple_destructor = [](void *elem) { *(int *) elem = 42; }; 7.287 + cxListAdd(list, &item); 7.288 + cxListDestroy(list); 7.289 + EXPECT_EQ(item, 42); 7.290 +} 7.291 + 7.292 +TEST_F(PointerLinkedList, AdvancedDestructor) { 7.293 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 7.294 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 7.295 + cxListStorePointers(list); 7.296 + list->content_destructor_type = CX_DESTRUCTOR_ADVANCED; 7.297 + list->advanced_destructor.data = &testingAllocator; 7.298 + list->advanced_destructor.func = (cx_destructor_func2) cxFree; 7.299 + cxListAdd(list, item); 7.300 + ASSERT_FALSE(testingAllocator.verify()); 7.301 + cxListDestroy(list); 7.302 + EXPECT_TRUE(testingAllocator.verify()); 7.303 +}