ucx/cx/map.h

changeset 11
0aa8cbd7912e
parent 0
1a157da63d7c
child 16
04c9f8d8f03b
--- a/ucx/cx/map.h	Fri Jan 03 21:40:57 2025 +0100
+++ b/ucx/cx/map.h	Sat Jan 04 13:03:01 2025 +0100
@@ -89,19 +89,19 @@
     /**
      * Deallocates the entire memory.
      */
-    __attribute__((__nonnull__))
-    void (*destructor)(struct cx_map_s *map);
+    cx_attr_nonnull
+    void (*deallocate)(struct cx_map_s *map);
 
     /**
      * Removes all elements.
      */
-    __attribute__((__nonnull__))
+    cx_attr_nonnull
     void (*clear)(struct cx_map_s *map);
 
     /**
      * Add or overwrite an element.
      */
-    __attribute__((__nonnull__))
+    cx_attr_nonnull
     int (*put)(
             CxMap *map,
             CxHashKey key,
@@ -111,27 +111,37 @@
     /**
      * Returns an element.
      */
-    __attribute__((__nonnull__, __warn_unused_result__))
+    cx_attr_nonnull
+    cx_attr_nodiscard
     void *(*get)(
-            CxMap const *map,
+            const CxMap *map,
             CxHashKey key
     );
 
     /**
      * Removes an element.
+     *
+     * Implementations SHALL check if \p targetbuf is set and copy the elements
+     * to the buffer without invoking any destructor.
+     * When \p targetbuf is not set, the destructors SHALL be invoked.
+     *
+     * The function SHALL return zero when the \p key was found and
+     * non-zero, otherwise. 
      */
-    __attribute__((__nonnull__))
-    void *(*remove)(
+    cx_attr_nonnull_arg(1)
+    cx_attr_access_w(3)
+    int (*remove)(
             CxMap *map,
             CxHashKey key,
-            bool destroy
+            void *targetbuf
     );
 
     /**
      * Creates an iterator for this map.
      */
-    __attribute__((__nonnull__, __warn_unused_result__))
-    CxIterator (*iterator)(CxMap const *map, enum cx_map_iterator_type type);
+    cx_attr_nonnull
+    cx_attr_nodiscard
+    CxIterator (*iterator)(const CxMap *map, enum cx_map_iterator_type type);
 };
 
 /**
@@ -141,7 +151,7 @@
     /**
      * A pointer to the key.
      */
-    CxHashKey const *key;
+    const CxHashKey *key;
     /**
      * A pointer to the value.
      */
@@ -151,7 +161,7 @@
 /**
  * A shared instance of an empty map.
  *
- * Writing to that map is undefined.
+ * Writing to that map is not allowed.
  */
 extern CxMap *const cxEmptyMap;
 
@@ -164,7 +174,7 @@
  * @param map the map
  * @see cxMapStorePointers()
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline void cxMapStoreObjects(CxMap *map) {
     map->collection.store_pointer = false;
 }
@@ -181,7 +191,7 @@
  * @param map the map
  * @see cxMapStoreObjects()
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline void cxMapStorePointers(CxMap *map) {
     map->collection.store_pointer = true;
     map->collection.elem_size = sizeof(void *);
@@ -194,19 +204,19 @@
  * @return true, if this map is storing pointers
  * @see cxMapStorePointers()
  */
-__attribute__((__nonnull__))
-static inline bool cxMapIsStoringPointers(CxMap const *map) {
+cx_attr_nonnull
+static inline bool cxMapIsStoringPointers(const CxMap *map) {
     return map->collection.store_pointer;
 }
 
 /**
  * Deallocates the memory of the specified map.
  *
- * @param map the map to be destroyed
+ * @param map the map to be freed
  */
-__attribute__((__nonnull__))
-static inline void cxMapDestroy(CxMap *map) {
-    map->cl->destructor(map);
+static inline void cxMapFree(CxMap *map) {
+    if (map == NULL) return;
+    map->cl->deallocate(map);
 }
 
 
@@ -215,7 +225,7 @@
  *
  * @param map the map to be cleared
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline void cxMapClear(CxMap *map) {
     map->cl->clear(map);
 }
@@ -226,8 +236,8 @@
  * @param map the map
  * @return the number of stored elements
  */
-__attribute__((__nonnull__))
-static inline size_t cxMapSize(CxMap const *map) {
+cx_attr_nonnull
+static inline size_t cxMapSize(const CxMap *map) {
     return map->collection.size;
 }
 
@@ -237,14 +247,15 @@
 /**
  * Creates a value iterator for a map.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
  * @return an iterator for the currently stored values
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline CxIterator cxMapIteratorValues(CxMap const *map) {
+cx_attr_nonnull
+cx_attr_nodiscard
+static inline CxIterator cxMapIteratorValues(const CxMap *map) {
     return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES);
 }
 
@@ -253,14 +264,15 @@
  *
  * The elements of the iterator are keys of type CxHashKey.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
  * @return an iterator for the currently stored keys
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline CxIterator cxMapIteratorKeys(CxMap const *map) {
+cx_attr_nonnull
+cx_attr_nodiscard
+static inline CxIterator cxMapIteratorKeys(const CxMap *map) {
     return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS);
 }
 
@@ -269,7 +281,7 @@
  *
  * The elements of the iterator are key/value pairs of type CxMapEntry.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
@@ -277,8 +289,9 @@
  * @see cxMapIteratorKeys()
  * @see cxMapIteratorValues()
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline CxIterator cxMapIterator(CxMap const *map) {
+cx_attr_nonnull
+cx_attr_nodiscard
+static inline CxIterator cxMapIterator(const CxMap *map) {
     return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS);
 }
 
@@ -286,13 +299,14 @@
 /**
  * Creates a mutating iterator over the values of a map.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
  * @return an iterator for the currently stored values
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 CxIterator cxMapMutIteratorValues(CxMap *map);
 
 /**
@@ -300,13 +314,14 @@
  *
  * The elements of the iterator are keys of type CxHashKey.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
  * @return an iterator for the currently stored keys
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 CxIterator cxMapMutIteratorKeys(CxMap *map);
 
 /**
@@ -314,7 +329,7 @@
  *
  * The elements of the iterator are key/value pairs of type CxMapEntry.
  *
- * \note An iterator iterates over all elements successively. Therefore the order
+ * \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
@@ -322,7 +337,8 @@
  * @see cxMapMutIteratorKeys()
  * @see cxMapMutIteratorValues()
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 CxIterator cxMapMutIterator(CxMap *map);
 
 #ifdef __cplusplus
@@ -336,7 +352,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cxMapPut(
         CxMap *map,
         CxHashKey const &key,
@@ -354,7 +370,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cxMapPut(
         CxMap *map,
         cxstring const &key,
@@ -371,7 +387,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cxMapPut(
         CxMap *map,
         cxmutstr const &key,
@@ -388,10 +404,11 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
 static inline int cxMapPut(
         CxMap *map,
-        char const *key,
+        const char *key,
         void *value
 ) {
     return map->cl->put(map, cx_hash_key_str(key), value);
@@ -404,9 +421,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cxMapGet(
-        CxMap const *map,
+        const CxMap *map,
         CxHashKey const &key
 ) {
     return map->cl->get(map, key);
@@ -419,9 +437,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cxMapGet(
-        CxMap const *map,
+        const CxMap *map,
         cxstring const &key
 ) {
     return map->cl->get(map, cx_hash_key_cxstr(key));
@@ -434,9 +453,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cxMapGet(
-        CxMap const *map,
+        const CxMap *map,
         cxmutstr const &key
 ) {
     return map->cl->get(map, cx_hash_key_cxstr(key));
@@ -449,10 +469,12 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
+cx_attr_cstr_arg(2)
 static inline void *cxMapGet(
-        CxMap const *map,
-        char const *key
+        const CxMap *map,
+        const char *key
 ) {
     return map->cl->get(map, cx_hash_key_str(key));
 }
@@ -460,285 +482,191 @@
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * Always invokes the destructor function, if any, on the removed element.
- * If this map is storing pointers and you just want to retrieve the pointer
- * without invoking the destructor, use cxMapRemoveAndGet().
- * If you just want to detach the element from the map without invoking the
- * destructor or returning the element, use cxMapDetach().
+ * Always invokes the destructors functions, if any, on the removed element.
  *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapRemoveAndGet()
- * @see cxMapDetach()
  */
-__attribute__((__nonnull__))
-static inline void cxMapRemove(
+cx_attr_nonnull
+static inline int cxMapRemove(
         CxMap *map,
         CxHashKey const &key
 ) {
-    (void) map->cl->remove(map, key, true);
+    return map->cl->remove(map, key, nullptr);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * Always invokes the destructor function, if any, on the removed element.
- * If this map is storing pointers and you just want to retrieve the pointer
- * without invoking the destructor, use cxMapRemoveAndGet().
- * If you just want to detach the element from the map without invoking the
- * destructor or returning the element, use cxMapDetach().
+ * Always invokes the destructors functions, if any, on the removed element.
  *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapRemoveAndGet()
- * @see cxMapDetach()
  */
-__attribute__((__nonnull__))
-static inline void cxMapRemove(
+cx_attr_nonnull
+static inline int cxMapRemove(
         CxMap *map,
         cxstring const &key
 ) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), nullptr);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * Always invokes the destructor function, if any, on the removed element.
- * If this map is storing pointers and you just want to retrieve the pointer
- * without invoking the destructor, use cxMapRemoveAndGet().
- * If you just want to detach the element from the map without invoking the
- * destructor or returning the element, use cxMapDetach().
+ * Always invokes the destructors functions, if any, on the removed element.
  *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapRemoveAndGet()
- * @see cxMapDetach()
  */
-__attribute__((__nonnull__))
-static inline void cxMapRemove(
+cx_attr_nonnull
+static inline int cxMapRemove(
         CxMap *map,
         cxmutstr const &key
 ) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), nullptr);
+}
+
+/**
+ * Removes a key/value-pair from the map by using the key.
+ *
+ * Always invokes the destructors functions, if any, on the removed element.
+ *
+ * @param map the map
+ * @param key the key
+ * @return zero on success, non-zero if the key was not found
+ * 
+ * @see cxMapRemoveAndGet()
+ */
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
+static inline int cxMapRemove(
+        CxMap *map,
+        const char *key
+) {
+    return map->cl->remove(map, cx_hash_key_str(key), nullptr);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * Always invokes the destructor function, if any, on the removed element.
- * If this map is storing pointers and you just want to retrieve the pointer
- * without invoking the destructor, use cxMapRemoveAndGet().
- * If you just want to detach the element from the map without invoking the
- * destructor or returning the element, use cxMapDetach().
- *
- * @param map the map
- * @param key the key
- * @see cxMapRemoveAndGet()
- * @see cxMapDetach()
- */
-__attribute__((__nonnull__))
-static inline void cxMapRemove(
-        CxMap *map,
-        char const *key
-) {
-    (void) map->cl->remove(map, cx_hash_key_str(key), true);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
  *
- * In general, you should only use this function if the map does not own
- * the data and there is a valid reference to the data somewhere else
- * in the program. In all other cases it is preferable to use
- * cxMapRemove() or cxMapRemoveAndGet().
- *
- * @param map the map
- * @param key the key
- * @see cxMapRemove()
- * @see cxMapRemoveAndGet()
- */
-__attribute__((__nonnull__))
-static inline void cxMapDetach(
-        CxMap *map,
-        CxHashKey const &key
-) {
-    (void) map->cl->remove(map, key, false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * In general, you should only use this function if the map does not own
- * the data and there is a valid reference to the data somewhere else
- * in the program. In all other cases it is preferable to use
- * cxMapRemove() or cxMapRemoveAndGet().
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
  *
  * @param map the map
  * @param key the key
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
+ * 
+ * @see cxMapStorePointers()
  * @see cxMapRemove()
- * @see cxMapRemoveAndGet()
- */
-__attribute__((__nonnull__))
-static inline void cxMapDetach(
-        CxMap *map,
-        cxstring const &key
-) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * In general, you should only use this function if the map does not own
- * the data and there is a valid reference to the data somewhere else
- * in the program. In all other cases it is preferable to use
- * cxMapRemove() or cxMapRemoveAndGet().
- *
- * @param map the map
- * @param key the key
- * @see cxMapRemove()
- * @see cxMapRemoveAndGet()
  */
-__attribute__((__nonnull__))
-static inline void cxMapDetach(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cxMapRemoveAndGet(
         CxMap *map,
-        cxmutstr const &key
+        CxHashKey key,
+        void *targetbuf
 ) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * In general, you should only use this function if the map does not own
- * the data and there is a valid reference to the data somewhere else
- * in the program. In all other cases it is preferable to use
- * cxMapRemove() or cxMapRemoveAndGet().
- *
- * @param map the map
- * @param key the key
- * @see cxMapRemove()
- * @see cxMapRemoveAndGet()
- */
-__attribute__((__nonnull__))
-static inline void cxMapDetach(
-        CxMap *map,
-        char const *key
-) {
-    (void) map->cl->remove(map, cx_hash_key_str(key), false);
+    return map->cl->remove(map, key, targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * This function can be used when the map is storing pointers,
- * in order to retrieve the pointer from the map without invoking
- * any destructor function. Sometimes you do not want the pointer
- * to be returned - in that case (instead of suppressing the "unused
- * result" warning) you can use cxMapDetach().
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
  *
- * If this map is not storing pointers, this function behaves like
- * cxMapRemove() and returns \c NULL.
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
  *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapStorePointers()
- * @see cxMapDetach()
+ * @see cxMapRemove()
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cxMapRemoveAndGet(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cxMapRemoveAndGet(
         CxMap *map,
-        CxHashKey key
+        cxstring key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, key, !map->store_pointer);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * This function can be used when the map is storing pointers,
- * in order to retrieve the pointer from the map without invoking
- * any destructor function. Sometimes you do not want the pointer
- * to be returned - in that case (instead of suppressing the "unused
- * result" warning) you can use cxMapDetach().
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
  *
- * If this map is not storing pointers, this function behaves like
- * cxMapRemove() and returns \c NULL.
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
  *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapStorePointers()
- * @see cxMapDetach()
+ * @see cxMapRemove()
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cxMapRemoveAndGet(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cxMapRemoveAndGet(
         CxMap *map,
-        cxstring key
+        cxmutstr key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * This function can be used when the map is storing pointers,
- * in order to retrieve the pointer from the map without invoking
- * any destructor function. Sometimes you do not want the pointer
- * to be returned - in that case (instead of suppressing the "unused
- * result" warning) you can use cxMapDetach().
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
  *
- * If this map is not storing pointers, this function behaves like
- * cxMapRemove() and returns \c NULL.
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
  *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapStorePointers()
- * @see cxMapDetach()
+ * @see cxMapRemove()
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cxMapRemoveAndGet(
+cx_attr_nonnull
+cx_attr_access_w(3)
+cx_attr_cstr_arg(2)
+static inline int cxMapRemoveAndGet(
         CxMap *map,
-        cxmutstr key
+        const char *key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
-}
-
-/**
- * Removes a key/value-pair from the map by using the key.
- *
- * This function can be used when the map is storing pointers,
- * in order to retrieve the pointer from the map without invoking
- * any destructor function. Sometimes you do not want the pointer
- * to be returned - in that case (instead of suppressing the "unused
- * result" warning) you can use cxMapDetach().
- *
- * If this map is not storing pointers, this function behaves like
- * cxMapRemove() and returns \c NULL.
- *
- * @param map the map
- * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
- * @see cxMapStorePointers()
- * @see cxMapDetach()
- */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cxMapRemoveAndGet(
-        CxMap *map,
-        char const *key
-) {
-    return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
+    return map->cl->remove(map, cx_hash_key_str(key), targetbuf);
 }
 
 #else // __cplusplus
@@ -751,7 +679,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cx_map_put(
         CxMap *map,
         CxHashKey key,
@@ -768,7 +696,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cx_map_put_cxstr(
         CxMap *map,
         cxstring key,
@@ -785,7 +713,7 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
 static inline int cx_map_put_mustr(
         CxMap *map,
         cxmutstr key,
@@ -802,10 +730,11 @@
  * @param value the value
  * @return 0 on success, non-zero value on failure
  */
-__attribute__((__nonnull__))
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
 static inline int cx_map_put_str(
         CxMap *map,
-        char const *key,
+        const char *key,
         void *value
 ) {
     return map->cl->put(map, cx_hash_key_str(key), value);
@@ -824,7 +753,7 @@
     cxstring: cx_map_put_cxstr,                   \
     cxmutstr: cx_map_put_mustr,                   \
     char*: cx_map_put_str,                        \
-    char const*: cx_map_put_str)                  \
+    const char*: cx_map_put_str)                  \
     (map, key, value)
 
 /**
@@ -834,9 +763,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cx_map_get(
-        CxMap const *map,
+        const CxMap *map,
         CxHashKey key
 ) {
     return map->cl->get(map, key);
@@ -849,9 +779,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cx_map_get_cxstr(
-        CxMap const *map,
+        const CxMap *map,
         cxstring key
 ) {
     return map->cl->get(map, cx_hash_key_cxstr(key));
@@ -864,9 +795,10 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
 static inline void *cx_map_get_mustr(
-        CxMap const *map,
+        const CxMap *map,
         cxmutstr key
 ) {
     return map->cl->get(map, cx_hash_key_cxstr(key));
@@ -879,10 +811,12 @@
  * @param key the key
  * @return the value
  */
-__attribute__((__nonnull__, __warn_unused_result__))
+cx_attr_nonnull
+cx_attr_nodiscard
+cx_attr_cstr_arg(2)
 static inline void *cx_map_get_str(
-        CxMap const *map,
-        char const *key
+        const CxMap *map,
+        const char *key
 ) {
     return map->cl->get(map, cx_hash_key_str(key));
 }
@@ -899,259 +833,223 @@
     cxstring: cx_map_get_cxstr,            \
     cxmutstr: cx_map_get_mustr,            \
     char*: cx_map_get_str,                 \
-    char const*: cx_map_get_str)           \
+    const char*: cx_map_get_str)           \
     (map, key)
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * Always invokes the destructors functions, if any, on the removed element.
+ *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__))
-static inline void cx_map_remove(
+cx_attr_nonnull
+static inline int cx_map_remove(
         CxMap *map,
         CxHashKey key
 ) {
-    (void) map->cl->remove(map, key, true);
+    return map->cl->remove(map, key, NULL);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * Always invokes the destructors functions, if any, on the removed element.
+ *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__))
-static inline void cx_map_remove_cxstr(
+cx_attr_nonnull
+static inline int cx_map_remove_cxstr(
         CxMap *map,
         cxstring key
 ) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), NULL);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * Always invokes the destructors functions, if any, on the removed element.
+ *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__))
-static inline void cx_map_remove_mustr(
+cx_attr_nonnull
+static inline int cx_map_remove_mustr(
         CxMap *map,
         cxmutstr key
 ) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), NULL);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * Always invokes the destructors functions, if any, on the removed element.
+ *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__))
-static inline void cx_map_remove_str(
+cx_attr_nonnull
+cx_attr_cstr_arg(2)
+static inline int cx_map_remove_str(
         CxMap *map,
-        char const *key
+        const char *key
 ) {
-    (void) map->cl->remove(map, cx_hash_key_str(key), true);
+    return map->cl->remove(map, cx_hash_key_str(key), NULL);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * Always invokes the destructor function, if any, on the removed element.
- * If this map is storing pointers and you just want to retrieve the pointer
- * without invoking the destructor, use cxMapRemoveAndGet().
- * If you just want to detach the element from the map without invoking the
- * destructor or returning the element, use cxMapDetach().
+ * Always invokes the destructors functions, if any, on the removed element.
  *
  * @param map the map
  * @param key the key
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapRemoveAndGet()
- * @see cxMapDetach()
  */
 #define cxMapRemove(map, key) _Generic((key), \
     CxHashKey: cx_map_remove,                 \
     cxstring: cx_map_remove_cxstr,            \
     cxmutstr: cx_map_remove_mustr,            \
     char*: cx_map_remove_str,                 \
-    char const*: cx_map_remove_str)           \
-    (map, key)
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * @param map the map
- * @param key the key
- */
-__attribute__((__nonnull__))
-static inline void cx_map_detach(
-        CxMap *map,
-        CxHashKey key
-) {
-    (void) map->cl->remove(map, key, false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * @param map the map
- * @param key the key
- */
-__attribute__((__nonnull__))
-static inline void cx_map_detach_cxstr(
-        CxMap *map,
-        cxstring key
-) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * @param map the map
- * @param key the key
- */
-__attribute__((__nonnull__))
-static inline void cx_map_detach_mustr(
-        CxMap *map,
-        cxmutstr key
-) {
-    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * @param map the map
- * @param key the key
- */
-__attribute__((__nonnull__))
-static inline void cx_map_detach_str(
-        CxMap *map,
-        char const *key
-) {
-    (void) map->cl->remove(map, cx_hash_key_str(key), false);
-}
-
-/**
- * Detaches a key/value-pair from the map by using the key
- * without invoking the destructor.
- *
- * In general, you should only use this function if the map does not own
- * the data and there is a valid reference to the data somewhere else
- * in the program. In all other cases it is preferable to use
- * cxMapRemove() or cxMapRemoveAndGet().
- *
- * @param map the map
- * @param key the key
- * @see cxMapRemove()
- * @see cxMapRemoveAndGet()
- */
-#define cxMapDetach(map, key) _Generic((key), \
-    CxHashKey: cx_map_detach,                 \
-    cxstring: cx_map_detach_cxstr,            \
-    cxmutstr: cx_map_detach_mustr,            \
-    char*: cx_map_detach_str,                 \
-    char const*: cx_map_detach_str)           \
+    const char*: cx_map_remove_str)           \
     (map, key)
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
+ *
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
+ *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cx_map_remove_and_get(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cx_map_remove_and_get(
         CxMap *map,
-        CxHashKey key
+        CxHashKey key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, key, !map->collection.store_pointer);
+    return map->cl->remove(map, key, targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
+ *
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
+ *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cx_map_remove_and_get_cxstr(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cx_map_remove_and_get_cxstr(
         CxMap *map,
-        cxstring key
+        cxstring key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->collection.store_pointer);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
+ *
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
+ *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cx_map_remove_and_get_mustr(
+cx_attr_nonnull
+cx_attr_access_w(3)
+static inline int cx_map_remove_and_get_mustr(
         CxMap *map,
-        cxmutstr key
+        cxmutstr key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->collection.store_pointer);
+    return map->cl->remove(map, cx_hash_key_cxstr(key), targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
+ *
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
+ *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
  */
-__attribute__((__nonnull__, __warn_unused_result__))
-static inline void *cx_map_remove_and_get_str(
+cx_attr_nonnull
+cx_attr_access_w(3)
+cx_attr_cstr_arg(2)
+static inline int cx_map_remove_and_get_str(
         CxMap *map,
-        char const *key
+        const char *key,
+        void *targetbuf
 ) {
-    return map->cl->remove(map, cx_hash_key_str(key), !map->collection.store_pointer);
+    return map->cl->remove(map, cx_hash_key_str(key), targetbuf);
 }
 
 /**
  * Removes a key/value-pair from the map by using the key.
  *
- * This function can be used when the map is storing pointers,
- * in order to retrieve the pointer from the map without invoking
- * any destructor function. Sometimes you do not want the pointer
- * to be returned - in that case (instead of suppressing the "unused
- * result" warning) you can use cxMapDetach().
+ * This function will copy the contents to the target buffer
+ * which must be guaranteed to be large enough to hold the element.
+ * The destructor functions, if any, will \em not be called.
  *
- * If this map is not storing pointers, this function behaves like
- * cxMapRemove() and returns \c NULL.
+ * If this map is storing pointers, the element is the pointer itself
+ * and not the object it points to.
  *
  * @param map the map
  * @param key the key
- * @return the stored pointer or \c NULL if either the key is not present
- * in the map or the map is not storing pointers
+ * @param targetbuf the buffer where the element shall be copied to
+ * @return zero on success, non-zero if the key was not found
+ * 
  * @see cxMapStorePointers()
- * @see cxMapDetach()
+ * @see cxMapRemove()
  */
-#define cxMapRemoveAndGet(map, key) _Generic((key), \
+#define cxMapRemoveAndGet(map, key, targetbuf) _Generic((key), \
     CxHashKey: cx_map_remove_and_get,               \
     cxstring: cx_map_remove_and_get_cxstr,          \
     cxmutstr: cx_map_remove_and_get_mustr,          \
     char*: cx_map_remove_and_get_str,               \
-    char const*: cx_map_remove_and_get_str)         \
-    (map, key)
+    const char*: cx_map_remove_and_get_str)         \
+    (map, key, targetbuf)
 
 #endif // __cplusplus
 

mercurial