src/list.c

changeset 1436
c331add0d9f8
parent 1433
81c301a59b7c
--- a/src/list.c	Mon Oct 20 20:38:02 2025 +0200
+++ b/src/list.c	Tue Oct 21 17:06:17 2025 +0200
@@ -804,3 +804,61 @@
     if (list == NULL) return;
     list->cl->deallocate(list);
 }
+
+size_t cxListClone(CxList *dst, const CxList *src, cx_clone_func clone_func,
+    const CxAllocator *clone_allocator, void *data) {
+
+    // remember the original size
+    size_t orig_size = dst->collection.size;
+
+    // first, try to allocate the memory in the new list
+    CxIterator empl_iter = cxListEmplaceArray(dst, src->collection.size);
+
+    // get an iterator over the source elements
+    CxIterator src_iter = cxListIterator(src);
+
+    // now clone the elements
+    size_t cloned = empl_iter.elem_count;
+    if (cxCollectionStoresPointers(dst)) {
+        for (size_t i = 0 ; i < empl_iter.elem_count; i++) {
+            void *src_elem = cxIteratorCurrent(src_iter);
+            void **dest_memory = cxIteratorCurrent(empl_iter);
+            void *dest_ptr = clone_func(NULL, src_elem, clone_allocator, data);
+            if (dest_ptr == NULL) {
+                cloned = i;
+                break;
+            }
+            *dest_memory = dest_ptr;
+            cxIteratorNext(src_iter);
+            cxIteratorNext(empl_iter);
+        }
+    } else {
+        for (size_t i = 0 ; i < empl_iter.elem_count; i++) {
+            void *src_elem = cxIteratorCurrent(src_iter);
+            void *dest_memory = cxIteratorCurrent(empl_iter);
+            if (clone_func(dest_memory, src_elem, clone_allocator, data) == NULL) {
+                cloned = i;
+                break;
+            }
+            cxIteratorNext(src_iter);
+            cxIteratorNext(empl_iter);
+        }
+    }
+
+    // if we could not clone everything, free the allocated memory
+    // (disable the destructors!)
+    if (cloned < src->collection.size) {
+        cx_destructor_func destr_bak = dst->collection.simple_destructor;
+        cx_destructor_func2 destr2_bak = dst->collection.advanced_destructor;
+        dst->collection.simple_destructor = NULL;
+        dst->collection.advanced_destructor = NULL;
+        cxListRemoveArray(dst,
+            orig_size + cloned,
+            dst->collection.size - cloned - orig_size);
+        dst->collection.simple_destructor = destr_bak;
+        dst->collection.advanced_destructor = destr2_bak;
+    }
+
+    // return how many elements we have cloned
+    return cloned;
+}
\ No newline at end of file

mercurial