diff -r 591377a27fa3 -r da79af4baec8 ucx/cx/map.h --- 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