# HG changeset patch # User Mike Becker # Date 1640708658 -3600 # Node ID 9138acaa494b56bac3314febd3b3aa15a4e11e57 # Parent 4bd19279778c10d95b8ba0edb4257ac1f0e36a76 add cxLinkedListFromArray() and cxListCompare() diff -r 4bd19279778c -r 9138acaa494b src/cx/linked_list.h --- a/src/cx/linked_list.h Tue Dec 28 14:25:05 2021 +0100 +++ b/src/cx/linked_list.h Tue Dec 28 17:24:18 2021 +0100 @@ -59,7 +59,7 @@ CxAllocator allocator, CxListComparator comparator, size_t item_size -); +) __attribute__((__nonnull__)); /** * Allocates a linked list for storing pointers. @@ -73,7 +73,25 @@ CxList cxPointerLinkedListCreate( CxAllocator allocator, CxListComparator comparator -); +) __attribute__((__nonnull__)); + +/** + * Creates a linked list using the data from an array. + * + * @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 allocator, + CxListComparator comparator, + size_t item_size, + size_t num_items, + const void *array +) __attribute__((__nonnull__)); /** * Deallocates the memory of the entire list. @@ -82,7 +100,7 @@ * * @param list the list */ -void cxLinkedListDestroy(CxList list); +void cxLinkedListDestroy(CxList list) __attribute__((__nonnull__)); /** * Finds the node at a certain index. @@ -386,6 +404,8 @@ /** * Compares two lists element wise. * + * \note Both list must have the same structure. + * * @param begin_left the begin of the left list (\c NULL denotes an empty list) * @param begin_right the begin of the right list (\c NULL denotes an empty list) * @param loc_advance the location of the pointer to advance diff -r 4bd19279778c -r 9138acaa494b src/cx/list.h --- a/src/cx/list.h Tue Dec 28 14:25:05 2021 +0100 +++ b/src/cx/list.h Tue Dec 28 17:24:18 2021 +0100 @@ -81,12 +81,23 @@ /** * Member function for finding an element. */ - size_t (*find)(cx_list_s *list, void *elem); + size_t (*find)( + cx_list_s *list, + void *elem + ); /** * Member function for sorting the list in place. */ void (*sort)(cx_list_s *list); + + /** + * Member function for comparing this list to another list of the same type. + */ + int (*compare)( + cx_list_s *list, + cx_list_s *other + ); } cx_list_class; /** @@ -205,6 +216,22 @@ list->cl->sort(list); } +/** + * Compares a list to another list of the same type. + * + * First, the list sizes are compared. If they match, the lists are compared element-wise. + * + * @param list the list + * @param other the list to compare to + * @return zero, if both lists are equal element wise, negative if the first list is smaller, zero if the first list is larger + */ +static inline int cxListCompare( + CxList list, + CxList other +) { + return list->cl->compare(list, other); +} + #ifdef __cplusplus } /* extern "C" */ #endif diff -r 4bd19279778c -r 9138acaa494b src/linked_list.c --- a/src/linked_list.c Tue Dec 28 14:25:05 2021 +0100 +++ b/src/linked_list.c Tue Dec 28 17:24:18 2021 +0100 @@ -613,13 +613,36 @@ true, list->cmpfunc); } +static int cx_ll_compare( + cx_list_s *list, + cx_list_s *other +) { + cx_linked_list *left = (cx_linked_list *) list; + cx_linked_list *right = (cx_linked_list *) other; + return cx_linked_list_compare(left->begin, right->begin, + CX_LL_LOC_NEXT, CX_LL_LOC_DATA, + false, list->cmpfunc); +} + +static int cx_pll_compare( + cx_list_s *list, + cx_list_s *other +) { + cx_linked_list *left = (cx_linked_list *) list; + cx_linked_list *right = (cx_linked_list *) other; + return cx_linked_list_compare(left->begin, right->begin, + CX_LL_LOC_NEXT, CX_LL_LOC_DATA, + true, list->cmpfunc); +} + static cx_list_class cx_linked_list_class = { cx_ll_add, cx_ll_insert, cx_ll_remove, cx_ll_at, cx_ll_find, - cx_ll_sort + cx_ll_sort, + cx_ll_compare }; static cx_list_class cx_pointer_linked_list_class = { @@ -628,7 +651,8 @@ cx_ll_remove, cx_pll_at, cx_pll_find, - cx_pll_sort + cx_pll_sort, + cx_pll_compare }; CxList cxLinkedListCreate( @@ -674,6 +698,24 @@ return (CxList) list; } +CxList cxLinkedListFromArray( + CxAllocator allocator, + CxListComparator comparator, + size_t item_size, + size_t num_items, + const void *array +) { + CxList list = cxLinkedListCreate(allocator, comparator, item_size); + if (list == NULL) return NULL; + for (size_t i = 0; i < num_items; i++) { + if (0 != cxListAdd(list, ((const unsigned char *) array) + i * item_size)) { + cxLinkedListDestroy(list); + return NULL; + } + } + return list; +} + void cxLinkedListDestroy(CxList list) { cx_linked_list *ll = (cx_linked_list *) list; diff -r 4bd19279778c -r 9138acaa494b test/test_list.c --- a/test/test_list.c Tue Dec 28 14:25:05 2021 +0100 +++ b/test/test_list.c Tue Dec 28 17:24:18 2021 +0100 @@ -570,6 +570,19 @@ CU_ASSERT_TRUE(cxTestingAllocatorVerify()) } +void test_hl_linked_list_from_array(void) { + cxTestingAllocatorReset(); + + int data[] = {2, 4, 5, 7, 10, 15}; + + CxList expected = cxLinkedListCreate(cxTestingAllocator, (CxListComparator) cmp_int, sizeof(int)); + for (int i = 0; i < 5; i++) cxListAdd(expected, &data[i]); + + CxList list = cxLinkedListFromArray(cxTestingAllocator, (CxListComparator) cmp_int, sizeof(int), 5, data); + + CU_ASSERT_TRUE(0 == cxListCompare(list, expected)) +} + void test_hl_linked_list_add(void) { cxTestingAllocatorReset(); @@ -994,6 +1007,7 @@ suite = CU_add_suite("high level linked list", NULL, NULL); cu_add_test(suite, test_hl_linked_list_create); + cu_add_test(suite, test_hl_linked_list_from_array); cu_add_test(suite, test_hl_linked_list_add); cu_add_test(suite, test_hl_linked_list_insert); cu_add_test(suite, test_hl_linked_list_remove);