src/map.c

changeset 1450
09a73312d5ec
parent 1449
bbca398783ed
--- 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;

mercurial