src/map.c

changeset 1445
e8089a590b71
parent 1444
dd9dcbb39c2f
--- a/src/map.c	Sat Oct 25 21:12:59 2025 +0200
+++ b/src/map.c	Sat Oct 25 21:33:56 2025 +0200
@@ -29,6 +29,8 @@
 #include "cx/map.h"
 #include <string.h>
 
+#include "cx/list.h"
+
 // <editor-fold desc="empty map implementation">
 
 static void cx_empty_map_noop(cx_attr_unused CxMap *map) {
@@ -172,3 +174,93 @@
     }
     return 0;
 }
+
+int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) {
+    const bool map_was_not_empty = cxMapSize(dst) > 0;
+    CxMapIterator src_iter = cxMapIterator(minuend);
+    if (cxCollectionStoresPointers(dst)) {
+        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* dst_ptr = clone_func(NULL, entry->value, clone_allocator, data);
+                if (dst_ptr == NULL) {
+                    cx_map_remove_uninitialized_entry(dst, *(entry->key));
+                    return 1;
+                }
+                *dst_mem = dst_ptr;
+            }
+        }
+    } else {
+        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;
+                }
+                if (NULL == clone_func(dst_mem, entry->value, clone_allocator, data)) {
+                    cx_map_remove_uninitialized_entry(dst, *entry->key);
+                    return 1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+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;
+    CxMapIterator src_iter = cxMapIterator(src);
+    if (cxCollectionStoresPointers(dst)) {
+        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* dst_ptr = clone_func(NULL, entry->value, clone_allocator, data);
+                if (dst_ptr == NULL) {
+                    cx_map_remove_uninitialized_entry(dst, *(entry->key));
+                    return 1;
+                }
+                *dst_mem = dst_ptr;
+            }
+        }
+    } else {
+        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;
+                }
+                if (NULL == clone_func(dst_mem, entry->value, clone_allocator, data)) {
+                    cx_map_remove_uninitialized_entry(dst, *entry->key);
+                    return 1;
+                }
+            }
+        }
+    }
+    return 0;
+}

mercurial