ucx/list.c

changeset 870
e167cf006213
parent 845
f3ab28ed22e5
child 943
9b5948aa5b90
--- a/ucx/list.c	Tue Oct 21 12:34:17 2025 +0200
+++ b/ucx/list.c	Tue Oct 21 16:20:51 2025 +0200
@@ -29,6 +29,7 @@
 #include "cx/list.h"
 
 #include <string.h>
+#include <assert.h>
 
 // <editor-fold desc="Store Pointers Functionality">
 
@@ -114,7 +115,7 @@
         const void *elem,
         int prepend
 ) {
-    struct cx_list_s *list = iter->src_handle.m;
+    struct cx_list_s *list = iter->src_handle;
     return list->climpl->insert_iter(iter, &elem, prepend);
 }
 
@@ -245,7 +246,7 @@
         cx_attr_unused bool backwards
 ) {
     CxIterator iter = {0};
-    iter.src_handle.c = list;
+    iter.src_handle = (void*) list;
     iter.index = index;
     iter.base.valid = cx_emptyl_iter_valid;
     return iter;
@@ -299,16 +300,17 @@
         const void *data,
         size_t n
 ) {
-    size_t elem_size = list->collection.elem_size;
     const char *src = data;
     size_t i = 0;
     for (; i < n; i++) {
         if (NULL == invoke_list_func(
-            insert_element, list, index + i,
-            src + i * elem_size)
+            insert_element, list, index + i, src)
         ) {
             return i; // LCOV_EXCL_LINE
         }
+        if (src != NULL) {
+            src += list->collection.elem_size;
+        }
     }
     return i;
 }
@@ -566,36 +568,174 @@
     }
 }
 
-CxIterator cxListMutIteratorAt(
-        CxList *list,
-        size_t index
-) {
-    if (list == NULL) list = cxEmptyList;
-    CxIterator it = list->cl->iterator(list, index, false);
-    it.base.mutating = true;
-    return it;
+size_t cxListSize(const CxList *list) {
+    return list->collection.size;
+}
+
+int cxListAdd(CxList *list, const void *elem) {
+    list->collection.sorted = false;
+    return list->cl->insert_element(list, list->collection.size, elem) == NULL;
+}
+
+size_t cxListAddArray(CxList *list, const void *array, size_t n) {
+    list->collection.sorted = false;
+    return list->cl->insert_array(list, list->collection.size, array, n);
+}
+
+int cxListInsert(CxList *list, size_t index, const void *elem) {
+    list->collection.sorted = false;
+    return list->cl->insert_element(list, index, elem) == NULL;
+}
+
+void *cxListEmplaceAt(CxList *list, size_t index) {
+    list->collection.sorted = false;
+    return list->cl->insert_element(list, index, NULL);
+}
+
+void *cxListEmplace(CxList *list) {
+    list->collection.sorted = false;
+    return list->cl->insert_element(list, list->collection.size, NULL);
+}
+
+static bool cx_list_emplace_iterator_valid(const void *it) {
+    const CxIterator *iter = it;
+    return iter->index < iter->elem_count;
+}
+
+CxIterator cxListEmplaceArrayAt(CxList *list, size_t index, size_t n) {
+    list->collection.sorted = false;
+    size_t c = list->cl->insert_array(list, index, NULL, n);
+    CxIterator iter = list->cl->iterator(list, index, false);
+    // tweak the fields of this iterator
+    iter.elem_count = c;
+    iter.index = 0;
+    // replace the valid function to abort iteration when c is reached
+    iter.base.valid = cx_list_emplace_iterator_valid;
+    // if we are storing pointers, we want to return the pure pointers.
+    // therefore, we must unwrap the "current" method
+    if (list->collection.store_pointer) {
+        iter.base.current = iter.base.current_impl;
+    }
+    return iter;
+}
+
+CxIterator cxListEmplaceArray(CxList *list, size_t n) {
+    return cxListEmplaceArrayAt(list, list->collection.size, n);
+}
+
+int cxListInsertSorted(CxList *list, const void *elem) {
+    assert(cxCollectionSorted(list));
+    list->collection.sorted = true;
+    const void *data = list->collection.store_pointer ? &elem : elem;
+    return list->cl->insert_sorted(list, data, 1) == 0;
+}
+
+int cxListInsertUnique(CxList *list, const void *elem) {
+    if (cxCollectionSorted(list)) {
+        list->collection.sorted = true;
+        const void *data = list->collection.store_pointer ? &elem : elem;
+        return list->cl->insert_unique(list, data, 1) == 0;
+    } else {
+        if (cxListContains(list, elem)) {
+            return 0;
+        } else {
+            return cxListAdd(list, elem);
+        }
+    }
+}
+
+size_t cxListInsertArray(CxList *list, size_t index, const void *array, size_t n) {
+    list->collection.sorted = false;
+    return list->cl->insert_array(list, index, array, n);
 }
 
-CxIterator cxListMutBackwardsIteratorAt(
-        CxList *list,
-        size_t index
-) {
-    if (list == NULL) list = cxEmptyList;
-    CxIterator it = list->cl->iterator(list, index, true);
-    it.base.mutating = true;
-    return it;
+size_t cxListInsertSortedArray(CxList *list, const void *array, size_t n) {
+    assert(cxCollectionSorted(list));
+    list->collection.sorted = true;
+    return list->cl->insert_sorted(list, array, n);
+}
+
+size_t cxListInsertUniqueArray(CxList *list, const void *array, size_t n) {
+    if (cxCollectionSorted(list)) {
+        list->collection.sorted = true;
+        return list->cl->insert_unique(list, array, n);
+    } else {
+        const char *source = array;
+        for (size_t i = 0 ; i < n; i++) {
+            // note: this also checks elements added in a previous iteration
+            const void *data = list->collection.store_pointer ?
+                    *((const void**)source) : source;
+            if (!cxListContains(list, data)) {
+                if (cxListAdd(list, data)) {
+                    return i; // LCOV_EXCL_LINE
+                }
+            }
+            source += list->collection.elem_size;
+        }
+        return n;
+    }
+}
+
+int cxListInsertAfter(CxIterator *iter, const void *elem) {
+    CxList* list = (CxList*)iter->src_handle;
+    list->collection.sorted = false;
+    return list->cl->insert_iter(iter, elem, 0);
+}
+
+int cxListInsertBefore(CxIterator *iter, const void *elem) {
+    CxList* list = (CxList*)iter->src_handle;
+    list->collection.sorted = false;
+    return list->cl->insert_iter(iter, elem, 1);
+}
+
+int cxListRemove(CxList *list, size_t index) {
+    return list->cl->remove(list, index, 1, NULL) == 0;
 }
 
-void cxListFree(CxList *list) {
-    if (list == NULL) return;
-    list->cl->deallocate(list);
+int cxListRemoveAndGet(CxList *list, size_t index, void *targetbuf) {
+    return list->cl->remove(list, index, 1, targetbuf) == 0;
+}
+
+int cxListRemoveAndGetFirst(CxList *list, void *targetbuf) {
+    return list->cl->remove(list, 0, 1, targetbuf) == 0;
+}
+
+int cxListRemoveAndGetLast(CxList *list, void *targetbuf) {
+    // note: index may wrap - member function will catch that
+    return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0;
+}
+
+size_t cxListRemoveArray(CxList *list, size_t index, size_t num) {
+    return list->cl->remove(list, index, num, NULL);
+}
+
+size_t cxListRemoveArrayAndGet(CxList *list, size_t index, size_t num, void *targetbuf) {
+    return list->cl->remove(list, index, num, targetbuf);
 }
 
-int cxListSet(
-        CxList *list,
-        size_t index,
-        const void *elem
-) {
+void cxListClear(CxList *list) {
+    list->cl->clear(list);
+    list->collection.sorted = true; // empty lists are always sorted
+}
+
+int cxListSwap(CxList *list, size_t i, size_t j) {
+    list->collection.sorted = false;
+    return list->cl->swap(list, i, j);
+}
+
+void *cxListAt(const CxList *list, size_t index) {
+    return list->cl->at(list, index);
+}
+
+void *cxListFirst(const CxList *list) {
+    return list->cl->at(list, 0);
+}
+
+void *cxListLast(const CxList *list) {
+    return list->cl->at(list, list->collection.size - 1);
+}
+
+int cxListSet(CxList *list, size_t index, const void *elem) {
     if (index >= list->collection.size) {
         return 1;
     }
@@ -611,3 +751,56 @@
 
     return 0;
 }
+
+CxIterator cxListIteratorAt(const CxList *list, size_t index) {
+    if (list == NULL) list = cxEmptyList;
+    return list->cl->iterator(list, index, false);
+}
+
+CxIterator cxListBackwardsIteratorAt(const CxList *list, size_t index) {
+    if (list == NULL) list = cxEmptyList;
+    return list->cl->iterator(list, index, true);
+}
+
+CxIterator cxListIterator(const CxList *list) {
+    if (list == NULL) list = cxEmptyList;
+    return list->cl->iterator(list, 0, false);
+}
+
+CxIterator cxListBackwardsIterator(const CxList *list) {
+    if (list == NULL) list = cxEmptyList;
+    return list->cl->iterator(list, list->collection.size - 1, true);
+}
+
+size_t cxListFind(const CxList *list, const void *elem) {
+    return list->cl->find_remove((CxList*)list, elem, false);
+}
+
+bool cxListContains(const CxList* list, const void* elem) {
+    return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size;
+}
+
+bool cxListIndexValid(const CxList *list, size_t index) {
+    return index < list->collection.size;
+}
+
+size_t cxListFindRemove(CxList *list, const void *elem) {
+    return list->cl->find_remove(list, elem, true);
+}
+
+void cxListSort(CxList *list) {
+    if (list->collection.sorted) return;
+    list->cl->sort(list);
+    list->collection.sorted = true;
+}
+
+void cxListReverse(CxList *list) {
+    // still sorted, but not according to the cmp_func
+    list->collection.sorted = false;
+    list->cl->reverse(list);
+}
+
+void cxListFree(CxList *list) {
+    if (list == NULL) return;
+    list->cl->deallocate(list);
+}

mercurial