# HG changeset patch # User Mike Becker # Date 1761168487 -7200 # Node ID dde4903c0fd74438ef931f84db8c25d942cd5dcb # Parent c331add0d9f8fa6a9829007e900a39ce7d3c1bcd untested draft of cxMapClone() - relates to #743 diff -r c331add0d9f8 -r dde4903c0fd7 src/cx/map.h --- 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 diff -r c331add0d9f8 -r dde4903c0fd7 src/map.c --- 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