ucx/cx/map.h

branch
dav-2
changeset 886
da79af4baec8
parent 854
1c8401ece69e
child 889
42cdbf9bbd49
--- a/ucx/cx/map.h	Tue Sep 09 16:01:30 2025 +0200
+++ b/ucx/cx/map.h	Tue Sep 09 20:56:47 2025 +0200
@@ -185,8 +185,11 @@
 
     /**
      * Add or overwrite an element.
+     * If the @p value is @c NULL, the implementation
+     * 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.
      */
-    int (*put)(
+    void *(*put)(
             CxMap *map,
             CxHashKey key,
             void *value
@@ -277,12 +280,12 @@
  * @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
+ * @param map the map to create the iterator for (can be @c NULL)
  * @return an iterator for the currently stored values
  */
-cx_attr_nonnull
 cx_attr_nodiscard
 static inline CxMapIterator cxMapIteratorValues(const CxMap *map) {
+    if (map == NULL) map = cxEmptyMap;
     return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES);
 }
 
@@ -295,12 +298,12 @@
  * @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
+ * @param map the map to create the iterator for (can be @c NULL)
  * @return an iterator for the currently stored keys
  */
-cx_attr_nonnull
 cx_attr_nodiscard
 static inline CxMapIterator cxMapIteratorKeys(const CxMap *map) {
+    if (map == NULL) map = cxEmptyMap;
     return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS);
 }
 
@@ -313,14 +316,14 @@
  * @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
+ * @param map the map to create the iterator for (can be @c NULL)
  * @return an iterator for the currently stored entries
  * @see cxMapIteratorKeys()
  * @see cxMapIteratorValues()
  */
-cx_attr_nonnull
 cx_attr_nodiscard
 static inline CxMapIterator cxMapIterator(const CxMap *map) {
+    if (map == NULL) map = cxEmptyMap;
     return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS);
 }
 
@@ -335,10 +338,9 @@
  * @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
+ * @param map the map to create the iterator for (can be @c NULL)
  * @return an iterator for the currently stored values
  */
-cx_attr_nonnull
 cx_attr_nodiscard
 cx_attr_export
 CxMapIterator cxMapMutIteratorValues(CxMap *map);
@@ -352,10 +354,9 @@
  * @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
+ * @param map the map to create the iterator for (can be @c NULL)
  * @return an iterator for the currently stored keys
  */
-cx_attr_nonnull
 cx_attr_nodiscard
 cx_attr_export
 CxMapIterator cxMapMutIteratorKeys(CxMap *map);
@@ -369,12 +370,11 @@
  * @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
+ * @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_nonnull
 cx_attr_nodiscard
 cx_attr_export
 CxMapIterator cxMapMutIterator(CxMap *map);
@@ -387,7 +387,7 @@
         CxHashKey const &key,
         void *value
 ) {
-    return map->cl->put(map, key, value);
+    return map->cl->put(map, key, value) == NULL;
 }
 
 cx_attr_nonnull
@@ -396,7 +396,7 @@
         cxstring const &key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_cxstr(key), value);
+    return map->cl->put(map, cx_hash_key_cxstr(key), value) == NULL;
 }
 
 cx_attr_nonnull
@@ -405,7 +405,7 @@
         cxmutstr const &key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_cxstr(key), value);
+    return map->cl->put(map, cx_hash_key_cxstr(key), value) == NULL;
 }
 
 cx_attr_nonnull
@@ -415,7 +415,40 @@
         const char *key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_str(key), value);
+    return map->cl->put(map, cx_hash_key_str(key), value) == NULL;
+}
+
+cx_attr_nonnull
+static inline void *cxMapEmplace(
+        CxMap *map,
+        CxHashKey const &key
+) {
+    return map->cl->put(map, key, NULL);
+}
+
+cx_attr_nonnull
+static inline void *cxMapEmplace(
+        CxMap *map,
+        cxstring const &key
+) {
+    return map->cl->put(map, cx_hash_key_cxstr(key), NULL);
+}
+
+cx_attr_nonnull
+static inline void *cxMapEmplace(
+        CxMap *map,
+        cxmutstr const &key
+) {
+    return map->cl->put(map, cx_hash_key_cxstr(key), NULL);
+}
+
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
+static inline void *cxMapEmplace(
+        CxMap *map,
+        const char *key
+) {
+    return map->cl->put(map, cx_hash_key_str(key), NULL);
 }
 
 cx_attr_nonnull
@@ -540,7 +573,7 @@
         CxHashKey key,
         void *value
 ) {
-    return map->cl->put(map, key, value);
+    return map->cl->put(map, key, value) == NULL;
 }
 
 /**
@@ -552,7 +585,7 @@
         cxstring key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_cxstr(key), value);
+    return map->cl->put(map, cx_hash_key_cxstr(key), value) == NULL;
 }
 
 /**
@@ -564,7 +597,7 @@
         cxmutstr key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_cxstr(key), value);
+    return map->cl->put(map, cx_hash_key_cxstr(key), value) == NULL;
 }
 
 /**
@@ -577,7 +610,7 @@
         const char *key,
         void *value
 ) {
-    return map->cl->put(map, cx_hash_key_str(key), value);
+    return map->cl->put(map, cx_hash_key_str(key), value) == NULL;
 }
 
 /**
@@ -608,6 +641,77 @@
     (map, key, value)
 
 /**
+ * @copydoc cxMapEmplace()
+ */
+cx_attr_nonnull
+static inline void *cx_map_emplace(
+        CxMap *map,
+        CxHashKey key
+) {
+    return map->cl->put(map, key, NULL);
+}
+
+/**
+ * @copydoc cxMapEmplace()
+ */
+cx_attr_nonnull
+static inline void *cx_map_emplace_cxstr(
+        CxMap *map,
+        cxstring key
+) {
+    return map->cl->put(map, cx_hash_key_cxstr(key), NULL);
+}
+
+/**
+ * @copydoc cxMapEmplace()
+ */
+cx_attr_nonnull
+static inline void *cx_map_emplace_mustr(
+        CxMap *map,
+        cxmutstr key
+) {
+    return map->cl->put(map, cx_hash_key_cxstr(key), NULL);
+}
+
+/**
+ * @copydoc cxMapEmplace()
+ */
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
+static inline void *cx_map_emplace_str(
+        CxMap *map,
+        const char *key
+) {
+    return map->cl->put(map, cx_hash_key_str(key), NULL);
+}
+
+/**
+ * Allocates memory for a value in the map associated with the specified key.
+ *
+ * A possible existing value will be overwritten.
+ * If destructor functions are specified, they are called for
+ * the overwritten element.
+ *
+ * If the map is storing pointers, this function returns a @c void** pointer,
+ * meaning a pointer to that pointer.
+ *
+ * The @p key is always copied.
+ *
+ * @param map (@c CxMap*) the map
+ * @param key (@c CxHashKey, @c char*, @c cxstring, or @c cxmutstr) the key
+ * @return the pointer to the allocated memory or @c NULL if allocation fails
+ * @retval zero success
+ * @retval non-zero value on memory allocation failure
+ */
+#define cxMapEmplace(map, key) _Generic((key), \
+    CxHashKey: cx_map_emplace,                 \
+    cxstring: cx_map_emplace_cxstr,            \
+    cxmutstr: cx_map_emplace_mustr,            \
+    char*: cx_map_emplace_str,                 \
+    const char*: cx_map_emplace_str)           \
+    (map, key)
+
+/**
  * @copydoc cxMapGet()
  */
 cx_attr_nonnull

mercurial