untested draft of cxMapClone() - relates to #743

Wed, 22 Oct 2025 23:28:07 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 22 Oct 2025 23:28:07 +0200
changeset 1437
dde4903c0fd7
parent 1436
c331add0d9f8
child 1438
2ca9e03ceeec

untested draft of cxMapClone() - relates to #743

src/cx/map.h file | annotate | diff | comparison | revisions
src/map.c file | annotate | diff | comparison | revisions
--- a/src/cx/map.h	Tue Oct 21 17:06:17 2025 +0200
+++ b/src/cx/map.h	Wed Oct 22 23:28:07 2025 +0200
@@ -464,6 +464,32 @@
  */
 #define cxMapRemoveAndGet(map, key, targetbuf) cx_map_remove(map, CX_HASH_KEY(key), targetbuf)
 
+
+/**
+ * Performs a deep clone of one map into another.
+ *
+ * If the destination map already contains entries, the cloned entries
+ * are added to that map, possibly overwriting existing elements when
+ * the keys already exist.
+ *
+ * When elements in the destination map need to be replaced, any destructor
+ * function is called on the replaced elements before replacing them.
+ *
+ * @attention If the cloned elements need to be destroyed by a destructor
+ * function, you must make sure that the destination map also uses this
+ * destructor function.
+ *
+ * @param dst the destination map
+ * @param src the source map
+ * @param clone_func the clone function for the values
+ * @param clone_allocator the allocator that is passed to the clone function
+ * @param data optional additional data that is passed to the clone function
+ * @return the number of elements that have been successfully cloned
+ */
+cx_attr_nonnull_arg(1, 2, 3)
+CX_EXPORT size_t cxMapClone(CxMap *dst, const CxMap *src,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
 #ifdef    __cplusplus
 } // extern "C"
 #endif
--- a/src/map.c	Tue Oct 21 17:06:17 2025 +0200
+++ b/src/map.c	Wed Oct 22 23:28:07 2025 +0200
@@ -127,3 +127,39 @@
     if (map == NULL) return;
     map->cl->deallocate(map);
 }
+
+size_t cxMapClone(CxMap *dst, const CxMap *src, cx_clone_func clone_func,
+        const CxAllocator *clone_allocator, void *data) {
+    CxMapIterator src_iter = cxMapIterator(src);
+    size_t i = 0;
+    if (cxCollectionStoresPointers(dst)) {
+        for (; i < cxMapSize(src); i++) {
+            const CxMapEntry *entry = cxIteratorCurrent(src_iter);
+            void **dst_mem = cxMapEmplace(dst, *(entry->key));
+            if (dst_mem == NULL) {
+                return i;
+            }
+            void *dst_ptr = clone_func(NULL, entry->value, clone_allocator, data);
+            if (dst_ptr == NULL) {
+                // TODO: remove the entry to avoid calling destructors on uninitialized memory
+                return i;
+            }
+            *dst_mem = dst_ptr;
+            cxIteratorNext(src_iter);
+        }
+    } else {
+        for (; i < cxMapSize(src); i++) {
+            const CxMapEntry *entry = cxIteratorCurrent(src_iter);
+            void *dst_mem = cxMapEmplace(dst, *(entry->key));
+            if (dst_mem == NULL) {
+                return i;
+            }
+            if (clone_func(dst_mem, entry->value, clone_allocator, data) == NULL) {
+                // TODO: remove the entry to avoid calling destructors on uninitialized memory
+                return i;
+            }
+            cxIteratorNext(src_iter);
+        }
+    }
+    return i;
+}
\ No newline at end of file

mercurial