add cxLinkedListFromArray() and cxListCompare()

Tue, 28 Dec 2021 17:24:18 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 28 Dec 2021 17:24:18 +0100
changeset 488
9138acaa494b
parent 487
4bd19279778c
child 489
af6be1e123aa

add cxLinkedListFromArray() and cxListCompare()

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.c file | annotate | diff | comparison | revisions
--- 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
--- 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
--- 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;
 
--- 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);

mercurial