ucx/cx/map.h

changeset 113
dde28a806552
parent 112
c3f2f16fa4b8
--- a/ucx/cx/map.h	Sun Oct 19 21:20:08 2025 +0200
+++ b/ucx/cx/map.h	Mon Nov 10 21:52:51 2025 +0100
@@ -41,6 +41,11 @@
 #include "string.h"
 #include "hash_key.h"
 
+#ifndef UCX_LIST_H
+// forward-declare CxList
+typedef struct cx_list_s CxList;
+#endif
+
 #ifdef    __cplusplus
 extern "C" {
 #endif
@@ -111,16 +116,7 @@
     /**
      * Handle for the source map.
      */
-    union {
-        /**
-         * Access for mutating iterators.
-         */
-        CxMap *m;
-        /**
-         * Access for normal iterators.
-         */
-        const CxMap *c;
-    } map;
+    CxMap *map;
 
     /**
      * Handle for the current element.
@@ -189,19 +185,12 @@
      * shall only allocate memory instead of adding an existing value to the map.
      * Returns a pointer to the allocated memory or @c NULL if allocation fails.
      */
-    void *(*put)(
-            CxMap *map,
-            CxHashKey key,
-            void *value
-    );
+    void *(*put)(CxMap *map, CxHashKey key, void *value);
 
     /**
      * Returns an element.
      */
-    void *(*get)(
-            const CxMap *map,
-            CxHashKey key
-    );
+    void *(*get)(const CxMap *map, CxHashKey key);
 
     /**
      * Removes an element.
@@ -213,11 +202,7 @@
      * The function SHALL return zero when the @p key was found and
      * non-zero, otherwise. 
      */
-    int (*remove)(
-            CxMap *map,
-            CxHashKey key,
-            void *targetbuf
-    );
+    int (*remove)(CxMap *map, CxHashKey key, void *targetbuf);
 
     /**
      * Creates an iterator for this map.
@@ -233,8 +218,7 @@
  * You can use this as a placeholder for initializing CxMap pointers
  * for which you do not want to reserve memory right from the beginning.
  */
-cx_attr_export
-extern CxMap *const cxEmptyMap;
+CX_EXPORT extern CxMap *const cxEmptyMap;
 
 /**
  * Deallocates the memory of the specified map.
@@ -243,8 +227,7 @@
  *
  * @param map the map to be freed
  */
-cx_attr_export
-void cxMapFree(CxMap *map);
+CX_EXPORT void cxMapFree(CxMap *map);
 
 
 /**
@@ -255,9 +238,7 @@
  * @param map the map to be cleared
  */
 cx_attr_nonnull
-static inline void cxMapClear(CxMap *map) {
-    map->cl->clear(map);
-}
+CX_EXPORT void cxMapClear(CxMap *map);
 
 /**
  * Returns the number of elements in this map.
@@ -266,9 +247,7 @@
  * @return the number of stored elements
  */
 cx_attr_nonnull
-static inline size_t cxMapSize(const CxMap *map) {
-    return map->collection.size;
-}
+CX_EXPORT size_t cxMapSize(const CxMap *map);
 
 /**
  * Creates a value iterator for a map.
@@ -284,10 +263,7 @@
  * @return an iterator for the currently stored values
  */
 cx_attr_nodiscard
-static inline CxMapIterator cxMapIteratorValues(const CxMap *map) {
-    if (map == NULL) map = cxEmptyMap;
-    return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES);
-}
+CX_EXPORT CxMapIterator cxMapIteratorValues(const CxMap *map);
 
 /**
  * Creates a key iterator for a map.
@@ -302,10 +278,7 @@
  * @return an iterator for the currently stored keys
  */
 cx_attr_nodiscard
-static inline CxMapIterator cxMapIteratorKeys(const CxMap *map) {
-    if (map == NULL) map = cxEmptyMap;
-    return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS);
-}
+CX_EXPORT CxMapIterator cxMapIteratorKeys(const CxMap *map);
 
 /**
  * Creates an iterator for a map.
@@ -322,62 +295,7 @@
  * @see cxMapIteratorValues()
  */
 cx_attr_nodiscard
-static inline CxMapIterator cxMapIterator(const CxMap *map) {
-    if (map == NULL) map = cxEmptyMap;
-    return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS);
-}
-
-
-/**
- * Creates a mutating iterator over the values of a map.
- *
- * When the map is storing pointers, those pointers are returned.
- * Otherwise, the iterator iterates over pointers to the memory within the map where the
- * respective elements are stored.
- *
- * @note An iterator iterates over all elements successively. Therefore, the order
- * highly depends on the map implementation and may change arbitrarily when the contents change.
- *
- * @param map the map to create the iterator for (can be @c NULL)
- * @return an iterator for the currently stored values
- */
-cx_attr_nodiscard
-cx_attr_export
-CxMapIterator cxMapMutIteratorValues(CxMap *map);
-
-/**
- * Creates a mutating iterator over the keys of a map.
- *
- * The elements of the iterator are keys of type CxHashKey, and the pointer returned
- * during iterator shall be treated as @c const @c CxHashKey* .
- *
- * @note An iterator iterates over all elements successively. Therefore, the order
- * highly depends on the map implementation and may change arbitrarily when the contents change.
- *
- * @param map the map to create the iterator for (can be @c NULL)
- * @return an iterator for the currently stored keys
- */
-cx_attr_nodiscard
-cx_attr_export
-CxMapIterator cxMapMutIteratorKeys(CxMap *map);
-
-/**
- * Creates a mutating iterator for a map.
- *
- * The elements of the iterator are key/value pairs of type CxMapEntry, and the pointer returned
- * during iterator shall be treated as @c const @c CxMapEntry* .
- *
- * @note An iterator iterates over all elements successively. Therefore, the order
- * highly depends on the map implementation and may change arbitrarily when the contents change.
- *
- * @param map the map to create the iterator for (can be @c NULL)
- * @return an iterator for the currently stored entries
- * @see cxMapMutIteratorKeys()
- * @see cxMapMutIteratorValues()
- */
-cx_attr_nodiscard
-cx_attr_export
-CxMapIterator cxMapMutIterator(CxMap *map);
+CX_EXPORT CxMapIterator cxMapIterator(const CxMap *map);
 
 /**
  * Puts a key/value-pair into the map.
@@ -400,13 +318,7 @@
  * @see cxMapPut()
  */
 cx_attr_nonnull
-static inline int cx_map_put(
-        CxMap *map,
-        CxHashKey key,
-        void *value
-) {
-    return map->cl->put(map, key, value) == NULL;
-}
+CX_EXPORT int cx_map_put(CxMap *map, CxHashKey key, void *value);
 
 /**
  * Puts a key/value-pair into the map.
@@ -450,12 +362,7 @@
  * @see cxMapEmplace()
  */
 cx_attr_nonnull
-static inline void *cx_map_emplace(
-        CxMap *map,
-        CxHashKey key
-) {
-    return map->cl->put(map, key, NULL);
-}
+CX_EXPORT void *cx_map_emplace(CxMap *map, CxHashKey key);
 
 /**
  * Allocates memory for a value in the map associated with the specified key.
@@ -490,14 +397,8 @@
  * @return the value
  * @see cxMapGet()
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline void *cx_map_get(
-        const CxMap *map,
-        CxHashKey key
-) {
-    return map->cl->get(map, key);
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT void *cx_map_get(const CxMap *map, CxHashKey key);
 
 /**
  * Retrieves a value by using a key.
@@ -508,12 +409,23 @@
  *
  * @param map (@c CxMap*) the map
  * @param key (any supported key type) the key
- * @return (@c void*) the value
+ * @return (@c void*) the value or @c NULL when no value with that @p key exists
  * @see CX_HASH_KEY()
  */
 #define cxMapGet(map, key) cx_map_get(map, CX_HASH_KEY(key))
 
 /**
+ * Checks if a map contains a specific key.
+ *
+ * @param map (@c CxMap*) the map
+ * @param key (any supported key type) the key
+ * @retval true if the key exists in the map
+ * @retval false if the key does not exist in the map
+ * @see CX_HASH_KEY()
+ */
+#define cxMapContains(map, key) (cxMapGet(map, key) != NULL)
+
+/**
  * Removes a key/value-pair from the map by using the key.
  *
  * Invokes the destructor functions, if any, on the removed element if and only if the
@@ -529,13 +441,7 @@
  * @see cxMapRemoveAndGet()
  */
 cx_attr_nonnull_arg(1)
-static inline int cx_map_remove(
-        CxMap *map,
-        CxHashKey key,
-        void *targetbuf
-) {
-    return map->cl->remove(map, key, targetbuf);
-}
+CX_EXPORT int cx_map_remove(CxMap *map, CxHashKey key, void *targetbuf);
 
 /**
  * Removes a key/value-pair from the map by using the key.
@@ -574,6 +480,246 @@
  */
 #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
+ * @retval zero when all elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3)
+CX_EXPORT int cxMapClone(CxMap *dst, const CxMap *src,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+
+/**
+ * Clones entries of a map if their key is not present in another map.
+ *
+ * @param dst the destination map
+ * @param minuend the map to subtract the entries from
+ * @param subtrahend the map containing the elements to be subtracted
+ * @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
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3, 4)
+CX_EXPORT int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+/**
+ * Clones entries of a map if their key is not present in a list.
+ *
+ * Note that the list must contain keys of type @c CxKey
+ * (or pointers to such keys) and must use @c cx_hash_key_cmp
+ * as the compare function.
+ * Generic key types cannot be processed in this case.
+ *
+ * @param dst the destination map
+ * @param src the source map
+ * @param keys the list of @c CxKey items
+ * @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
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3, 4)
+CX_EXPORT int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+
+/**
+ * Clones entries of a map only if their key is present in another map.
+ *
+ * @param dst the destination map
+ * @param src the map to clone the entries from
+ * @param other the map to check for existence of the keys
+ * @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
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3, 4)
+CX_EXPORT int cxMapIntersection(CxMap *dst, const CxMap *src, const CxMap *other,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+/**
+ * Clones entries of a map only if their key is present in a list.
+ *
+ * Note that the list must contain keys of type @c CxKey
+ * (or pointers to such keys) and must use @c cx_hash_key_cmp
+ * as the compare function.
+ * Generic key types cannot be processed in this case.
+ *
+ * @param dst the destination map
+ * @param src the source map
+ * @param keys the list of @c CxKey items
+ * @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
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3, 4)
+CX_EXPORT int cxMapListIntersection(CxMap *dst, const CxMap *src, const CxList *keys,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+/**
+ * Clones entries into a map if their key does not exist yet.
+ *
+ * If you want to calculate the union of two maps into a fresh new map,
+ * you can proceed as follows:
+ * 1. Clone the first map into a fresh, empty map.
+ * 2. Use this function to clone the second map into the result from step 1.
+ *
+ * @param dst the destination map
+ * @param src the map to clone the entries from
+ * @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
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull_arg(1, 2, 3)
+CX_EXPORT int cxMapUnion(CxMap *dst, const CxMap *src,
+        cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data);
+
+/**
+ * Performs a shallow clone of one map into another.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * 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
+ * @retval zero when all elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ * @see cxMapClone()
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapCloneSimple(CxMap *dst, const CxMap *src);
+
+/**
+ * Clones entries of a map if their key is not present in another map.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * @param dst the destination map
+ * @param minuend the map to subtract the entries from
+ * @param subtrahend the map containing the elements to be subtracted
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapDifferenceSimple(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend);
+
+/**
+ * Clones entries of a map if their key is not present in a list.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * Note that the list must contain keys of type @c CxKey
+ * (or pointers to such keys) and must use @c cx_hash_key_cmp
+ * as the compare function.
+ * Generic key types cannot be processed in this case.
+ *
+ * @param dst the destination map
+ * @param src the source map
+ * @param keys the list of @c CxKey items
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ * @see cxMapListDifference()
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapListDifferenceSimple(CxMap *dst, const CxMap *src, const CxList *keys);
+
+
+/**
+ * Clones entries of a map only if their key is present in another map.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * @param dst the destination map
+ * @param src the map to clone the entries from
+ * @param other the map to check for existence of the keys
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapIntersectionSimple(CxMap *dst, const CxMap *src, const CxMap *other);
+
+/**
+ * Clones entries of a map only if their key is present in a list.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * Note that the list must contain keys of type @c CxKey
+ * (or pointers to such keys) and must use @c cx_hash_key_cmp
+ * as the compare function.
+ * Generic key types cannot be processed in this case.
+ *
+ * @param dst the destination map
+ * @param src the source map
+ * @param keys the list of @c CxKey items
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapListIntersectionSimple(CxMap *dst, const CxMap *src, const CxList *keys);
+
+/**
+ * Clones entries into a map if their key does not exist yet.
+ *
+ * This function uses the default allocator, if needed, and performs
+ * shallow clones with @c memcpy().
+ *
+ * If you want to calculate the union of two maps into a fresh new map,
+ * you can proceed as follows:
+ * 1. Clone the first map into a fresh, empty map.
+ * 2. Use this function to clone the second map into the result from step 1.
+ *
+ * @param dst the destination map
+ * @param src the map to clone the entries from
+ * @retval zero when the elements were successfully cloned
+ * @retval non-zero when an allocation error occurred
+ */
+cx_attr_nonnull
+CX_EXPORT int cxMapUnionSimple(CxMap *dst, const CxMap *src);
+
 #ifdef    __cplusplus
 } // extern "C"
 #endif

mercurial