--- a/src/map.c Sun Oct 26 12:50:43 2025 +0100 +++ b/src/map.c Sun Oct 26 13:08:42 2025 +0100 @@ -148,7 +148,7 @@ const CxMapEntry *entry = cxIteratorCurrent(src_iter); void **dst_mem = cxMapEmplace(dst, *(entry->key)); if (dst_mem == NULL) { - return 1; + return 1; // LCOV_EXCL_LINE } void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; void *dst_ptr = clone_func(target, entry->value, clone_allocator, data); @@ -168,27 +168,32 @@ cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; - const bool map_was_not_empty = cxMapSize(dst) > 0; + // if the destination map already contains something, + // remove what does not belong to the difference + CxMapIterator dst_iter = cxMapIteratorKeys(dst); + cx_foreach(const CxHashKey *, key, dst_iter) { + if (cxMapContains(subtrahend, *key)) { + cxIteratorFlagRemoval(dst_iter); + } + } + CxMapIterator src_iter = cxMapIterator(minuend); cx_foreach(const CxMapEntry *, entry, src_iter) { if (cxMapContains(subtrahend, *entry->key)) { - if (map_was_not_empty) { - cxMapRemove(dst, *entry->key); - } - } else { - void** dst_mem = cxMapEmplace(dst, *entry->key); - if (dst_mem == NULL) { - return 1; - } - void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; - void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); - if (dst_ptr == NULL) { - cx_map_remove_uninitialized_entry(dst, *(entry->key)); - return 1; - } - if (cxCollectionStoresPointers(dst)) { - *dst_mem = dst_ptr; - } + continue; + } + void** dst_mem = cxMapEmplace(dst, *entry->key); + if (dst_mem == NULL) { + return 1; // LCOV_EXCL_LINE + } + void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; + void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); + if (dst_ptr == NULL) { + cx_map_remove_uninitialized_entry(dst, *(entry->key)); + return 1; + } + if (cxCollectionStoresPointers(dst)) { + *dst_mem = dst_ptr; } } return 0; @@ -196,27 +201,34 @@ int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { - const bool map_was_not_empty = cxMapSize(dst) > 0; + if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; + + // if the destination map already contains something, + // remove what does not belong to the difference + CxMapIterator dst_iter = cxMapIteratorKeys(dst); + cx_foreach(const CxHashKey *, key, dst_iter) { + if (cxListContains(keys, key)) { + cxIteratorFlagRemoval(dst_iter); + } + } + CxMapIterator src_iter = cxMapIterator(src); cx_foreach(const CxMapEntry *, entry, src_iter) { if (cxListContains(keys, entry->key)) { - if (map_was_not_empty) { - cxMapRemove(dst, *entry->key); - } - } else { - void** dst_mem = cxMapEmplace(dst, *entry->key); - if (dst_mem == NULL) { - return 1; - } - void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; - void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); - if (dst_ptr == NULL) { - cx_map_remove_uninitialized_entry(dst, *(entry->key)); - return 1; - } - if (cxCollectionStoresPointers(dst)) { - *dst_mem = dst_ptr; - } + continue; + } + void** dst_mem = cxMapEmplace(dst, *entry->key); + if (dst_mem == NULL) { + return 1; // LCOV_EXCL_LINE + } + void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; + void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); + if (dst_ptr == NULL) { + cx_map_remove_uninitialized_entry(dst, *(entry->key)); + return 1; + } + if (cxCollectionStoresPointers(dst)) { + *dst_mem = dst_ptr; } } return 0;