bring a generic interface to CxMap

Fri, 21 Apr 2023 19:50:43 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 21 Apr 2023 19:50:43 +0200
changeset 691
65baf7f45ac8
parent 690
2c2304622981
child 692
6ac92936cd44

bring a generic interface to CxMap

src/cx/hash_map.h file | annotate | diff | comparison | revisions
src/cx/map.h file | annotate | diff | comparison | revisions
src/hash_map.c file | annotate | diff | comparison | revisions
tests/CMakeLists.txt file | annotate | diff | comparison | revisions
tests/test_map.cpp file | annotate | diff | comparison | revisions
tests/test_map_generics.c file | annotate | diff | comparison | revisions
tests/test_map_generics.h file | annotate | diff | comparison | revisions
     1.1 --- a/src/cx/hash_map.h	Fri Apr 21 18:38:18 2023 +0200
     1.2 +++ b/src/cx/hash_map.h	Fri Apr 21 19:50:43 2023 +0200
     1.3 @@ -84,7 +84,7 @@
     1.4   */
     1.5  __attribute__((__nonnull__, __warn_unused_result__))
     1.6  CxMap *cxHashMapCreate(
     1.7 -        CxAllocator *allocator,
     1.8 +        CxAllocator const *allocator,
     1.9          size_t itemsize,
    1.10          size_t buckets
    1.11  );
     2.1 --- a/src/cx/map.h	Fri Apr 21 18:38:18 2023 +0200
     2.2 +++ b/src/cx/map.h	Fri Apr 21 19:50:43 2023 +0200
     2.3 @@ -39,6 +39,7 @@
     2.4  
     2.5  #include "common.h"
     2.6  #include "collection.h"
     2.7 +#include "string.h"
     2.8  #include "hash_key.h"
     2.9  
    2.10  #ifdef    __cplusplus
    2.11 @@ -211,108 +212,6 @@
    2.12      map->cl->clear(map);
    2.13  }
    2.14  
    2.15 -/**
    2.16 - * Puts a key/value-pair into the map.
    2.17 - *
    2.18 - * @param map the map
    2.19 - * @param key the key
    2.20 - * @param value the value
    2.21 - * @return 0 on success, non-zero value on failure
    2.22 - */
    2.23 -__attribute__((__nonnull__))
    2.24 -static inline int cxMapPut(
    2.25 -        CxMap *map,
    2.26 -        CxHashKey key,
    2.27 -        void *value
    2.28 -) {
    2.29 -    return map->cl->put(map, key, value);
    2.30 -}
    2.31 -
    2.32 -/**
    2.33 - * Retrieves a value by using a key.
    2.34 - *
    2.35 - * @param map the map
    2.36 - * @param key the key
    2.37 - * @return the value
    2.38 - */
    2.39 -__attribute__((__nonnull__, __warn_unused_result__))
    2.40 -static inline void *cxMapGet(
    2.41 -        CxMap const *map,
    2.42 -        CxHashKey key
    2.43 -) {
    2.44 -    return map->cl->get(map, key);
    2.45 -}
    2.46 -
    2.47 -/**
    2.48 - * Removes a key/value-pair from the map by using the key.
    2.49 - *
    2.50 - * Always invokes the destructor function, if any, on the removed element.
    2.51 - * If this map is storing pointers and you just want to retrieve the pointer
    2.52 - * without invoking the destructor, use cxMapRemoveAndGet().
    2.53 - * If you just want to detach the element from the map without invoking the
    2.54 - * destructor or returning the element, use cxMapDetach().
    2.55 - *
    2.56 - * @param map the map
    2.57 - * @param key the key
    2.58 - * @see cxMapRemoveAndGet()
    2.59 - * @see cxMapDetach()
    2.60 - */
    2.61 -__attribute__((__nonnull__))
    2.62 -static inline void cxMapRemove(
    2.63 -        CxMap *map,
    2.64 -        CxHashKey key
    2.65 -) {
    2.66 -    (void) map->cl->remove(map, key, true);
    2.67 -}
    2.68 -
    2.69 -/**
    2.70 - * Detaches a key/value-pair from the map by using the key
    2.71 - * without invoking the destructor.
    2.72 - *
    2.73 - * In general, you should only use this function if the map does not own
    2.74 - * the data and there is a valid reference to the data somewhere else
    2.75 - * in the program. In all other cases it is preferable to use
    2.76 - * cxMapRemove() or cxMapRemoveAndGet().
    2.77 - *
    2.78 - * @param map the map
    2.79 - * @param key the key
    2.80 - * @see cxMapRemove()
    2.81 - * @see cxMapRemoveAndGet()
    2.82 - */
    2.83 -__attribute__((__nonnull__))
    2.84 -static inline void cxMapDetach(
    2.85 -        CxMap *map,
    2.86 -        CxHashKey key
    2.87 -) {
    2.88 -    (void) map->cl->remove(map, key, false);
    2.89 -}
    2.90 -
    2.91 -/**
    2.92 - * Removes a key/value-pair from the map by using the key.
    2.93 - *
    2.94 - * This function can be used when the map is storing pointers,
    2.95 - * in order to retrieve the pointer from the map without invoking
    2.96 - * any destructor function. Sometimes you do not want the pointer
    2.97 - * to be returned - in that case (instead of suppressing the "unused
    2.98 - * result" warning) you can use cxMapDetach().
    2.99 - *
   2.100 - * If this map is not storing pointers, this function behaves like
   2.101 - * cxMapRemove() and returns \c NULL.
   2.102 - *
   2.103 - * @param map the map
   2.104 - * @param key the key
   2.105 - * @return the stored pointer or \c NULL if either the key is not present
   2.106 - * in the map or the map is not storing pointers
   2.107 - * @see cxMapStorePointers()
   2.108 - * @see cxMapDetach()
   2.109 - */
   2.110 -__attribute__((__nonnull__, __warn_unused_result__))
   2.111 -static inline void *cxMapRemoveAndGet(
   2.112 -        CxMap *map,
   2.113 -        CxHashKey key
   2.114 -) {
   2.115 -    return map->cl->remove(map, key, !map->store_pointer);
   2.116 -}
   2.117  
   2.118  // TODO: set-like map operations (union, intersect, difference)
   2.119  
   2.120 @@ -413,8 +312,644 @@
   2.121      return map->cl->mut_iterator(map);
   2.122  }
   2.123  
   2.124 -#ifdef    __cplusplus
   2.125 +#ifdef __cplusplus
   2.126 +} // end the extern "C" block here, because we want to start overloading
   2.127 +
   2.128 +/**
   2.129 + * Puts a key/value-pair into the map.
   2.130 + *
   2.131 + * @param map the map
   2.132 + * @param key the key
   2.133 + * @param value the value
   2.134 + * @return 0 on success, non-zero value on failure
   2.135 + */
   2.136 +__attribute__((__nonnull__))
   2.137 +static inline int cxMapPut(
   2.138 +        CxMap *map,
   2.139 +        CxHashKey const &key,
   2.140 +        void *value
   2.141 +) {
   2.142 +    return map->cl->put(map, key, value);
   2.143  }
   2.144 -#endif
   2.145  
   2.146 -#endif // UCX_MAP_H
   2.147 \ No newline at end of file
   2.148 +
   2.149 +/**
   2.150 + * Puts a key/value-pair into the map.
   2.151 + *
   2.152 + * @param map the map
   2.153 + * @param key the key
   2.154 + * @param value the value
   2.155 + * @return 0 on success, non-zero value on failure
   2.156 + */
   2.157 +__attribute__((__nonnull__))
   2.158 +static inline int cxMapPut(
   2.159 +        CxMap *map,
   2.160 +        cxstring const &key,
   2.161 +        void *value
   2.162 +) {
   2.163 +    return map->cl->put(map, cx_hash_key_cxstr(key), value);
   2.164 +}
   2.165 +
   2.166 +/**
   2.167 + * Puts a key/value-pair into the map.
   2.168 + *
   2.169 + * @param map the map
   2.170 + * @param key the key
   2.171 + * @param value the value
   2.172 + * @return 0 on success, non-zero value on failure
   2.173 + */
   2.174 +__attribute__((__nonnull__))
   2.175 +static inline int cxMapPut(
   2.176 +        CxMap *map,
   2.177 +        char const *key,
   2.178 +        void *value
   2.179 +) {
   2.180 +    return map->cl->put(map, cx_hash_key_str(key), value);
   2.181 +}
   2.182 +
   2.183 +/**
   2.184 + * Retrieves a value by using a key.
   2.185 + *
   2.186 + * @param map the map
   2.187 + * @param key the key
   2.188 + * @return the value
   2.189 + */
   2.190 +__attribute__((__nonnull__, __warn_unused_result__))
   2.191 +static inline void *cxMapGet(
   2.192 +        CxMap const *map,
   2.193 +        CxHashKey const &key
   2.194 +) {
   2.195 +    return map->cl->get(map, key);
   2.196 +}
   2.197 +
   2.198 +/**
   2.199 + * Retrieves a value by using a key.
   2.200 + *
   2.201 + * @param map the map
   2.202 + * @param key the key
   2.203 + * @return the value
   2.204 + */
   2.205 +__attribute__((__nonnull__, __warn_unused_result__))
   2.206 +static inline void *cxMapGet(
   2.207 +        CxMap const *map,
   2.208 +        cxstring const &key
   2.209 +) {
   2.210 +    return map->cl->get(map, cx_hash_key_cxstr(key));
   2.211 +}
   2.212 +
   2.213 +/**
   2.214 + * Retrieves a value by using a key.
   2.215 + *
   2.216 + * @param map the map
   2.217 + * @param key the key
   2.218 + * @return the value
   2.219 + */
   2.220 +__attribute__((__nonnull__, __warn_unused_result__))
   2.221 +static inline void *cxMapGet(
   2.222 +        CxMap const *map,
   2.223 +        char const *key
   2.224 +) {
   2.225 +    return map->cl->get(map, cx_hash_key_str(key));
   2.226 +}
   2.227 +
   2.228 +/**
   2.229 + * Removes a key/value-pair from the map by using the key.
   2.230 + *
   2.231 + * Always invokes the destructor function, if any, on the removed element.
   2.232 + * If this map is storing pointers and you just want to retrieve the pointer
   2.233 + * without invoking the destructor, use cxMapRemoveAndGet().
   2.234 + * If you just want to detach the element from the map without invoking the
   2.235 + * destructor or returning the element, use cxMapDetach().
   2.236 + *
   2.237 + * @param map the map
   2.238 + * @param key the key
   2.239 + * @see cxMapRemoveAndGet()
   2.240 + * @see cxMapDetach()
   2.241 + */
   2.242 +__attribute__((__nonnull__))
   2.243 +static inline void cxMapRemove(
   2.244 +        CxMap *map,
   2.245 +        CxHashKey const &key
   2.246 +) {
   2.247 +    (void) map->cl->remove(map, key, true);
   2.248 +}
   2.249 +
   2.250 +/**
   2.251 + * Removes a key/value-pair from the map by using the key.
   2.252 + *
   2.253 + * Always invokes the destructor function, if any, on the removed element.
   2.254 + * If this map is storing pointers and you just want to retrieve the pointer
   2.255 + * without invoking the destructor, use cxMapRemoveAndGet().
   2.256 + * If you just want to detach the element from the map without invoking the
   2.257 + * destructor or returning the element, use cxMapDetach().
   2.258 + *
   2.259 + * @param map the map
   2.260 + * @param key the key
   2.261 + * @see cxMapRemoveAndGet()
   2.262 + * @see cxMapDetach()
   2.263 + */
   2.264 +__attribute__((__nonnull__))
   2.265 +static inline void cxMapRemove(
   2.266 +        CxMap *map,
   2.267 +        cxstring const &key
   2.268 +) {
   2.269 +    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
   2.270 +}
   2.271 +
   2.272 +/**
   2.273 + * Removes a key/value-pair from the map by using the key.
   2.274 + *
   2.275 + * Always invokes the destructor function, if any, on the removed element.
   2.276 + * If this map is storing pointers and you just want to retrieve the pointer
   2.277 + * without invoking the destructor, use cxMapRemoveAndGet().
   2.278 + * If you just want to detach the element from the map without invoking the
   2.279 + * destructor or returning the element, use cxMapDetach().
   2.280 + *
   2.281 + * @param map the map
   2.282 + * @param key the key
   2.283 + * @see cxMapRemoveAndGet()
   2.284 + * @see cxMapDetach()
   2.285 + */
   2.286 +__attribute__((__nonnull__))
   2.287 +static inline void cxMapRemove(
   2.288 +        CxMap *map,
   2.289 +        char const *key
   2.290 +) {
   2.291 +    (void) map->cl->remove(map, cx_hash_key_str(key), true);
   2.292 +}
   2.293 +
   2.294 +/**
   2.295 + * Detaches a key/value-pair from the map by using the key
   2.296 + * without invoking the destructor.
   2.297 + *
   2.298 + * In general, you should only use this function if the map does not own
   2.299 + * the data and there is a valid reference to the data somewhere else
   2.300 + * in the program. In all other cases it is preferable to use
   2.301 + * cxMapRemove() or cxMapRemoveAndGet().
   2.302 + *
   2.303 + * @param map the map
   2.304 + * @param key the key
   2.305 + * @see cxMapRemove()
   2.306 + * @see cxMapRemoveAndGet()
   2.307 + */
   2.308 +__attribute__((__nonnull__))
   2.309 +static inline void cxMapDetach(
   2.310 +        CxMap *map,
   2.311 +        CxHashKey const &key
   2.312 +) {
   2.313 +    (void) map->cl->remove(map, key, false);
   2.314 +}
   2.315 +
   2.316 +/**
   2.317 + * Detaches a key/value-pair from the map by using the key
   2.318 + * without invoking the destructor.
   2.319 + *
   2.320 + * In general, you should only use this function if the map does not own
   2.321 + * the data and there is a valid reference to the data somewhere else
   2.322 + * in the program. In all other cases it is preferable to use
   2.323 + * cxMapRemove() or cxMapRemoveAndGet().
   2.324 + *
   2.325 + * @param map the map
   2.326 + * @param key the key
   2.327 + * @see cxMapRemove()
   2.328 + * @see cxMapRemoveAndGet()
   2.329 + */
   2.330 +__attribute__((__nonnull__))
   2.331 +static inline void cxMapDetach(
   2.332 +        CxMap *map,
   2.333 +        cxstring const &key
   2.334 +) {
   2.335 +    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
   2.336 +}
   2.337 +
   2.338 +/**
   2.339 + * Detaches a key/value-pair from the map by using the key
   2.340 + * without invoking the destructor.
   2.341 + *
   2.342 + * In general, you should only use this function if the map does not own
   2.343 + * the data and there is a valid reference to the data somewhere else
   2.344 + * in the program. In all other cases it is preferable to use
   2.345 + * cxMapRemove() or cxMapRemoveAndGet().
   2.346 + *
   2.347 + * @param map the map
   2.348 + * @param key the key
   2.349 + * @see cxMapRemove()
   2.350 + * @see cxMapRemoveAndGet()
   2.351 + */
   2.352 +__attribute__((__nonnull__))
   2.353 +static inline void cxMapDetach(
   2.354 +        CxMap *map,
   2.355 +        char const *key
   2.356 +) {
   2.357 +    (void) map->cl->remove(map, cx_hash_key_str(key), false);
   2.358 +}
   2.359 +
   2.360 +/**
   2.361 + * Removes a key/value-pair from the map by using the key.
   2.362 + *
   2.363 + * This function can be used when the map is storing pointers,
   2.364 + * in order to retrieve the pointer from the map without invoking
   2.365 + * any destructor function. Sometimes you do not want the pointer
   2.366 + * to be returned - in that case (instead of suppressing the "unused
   2.367 + * result" warning) you can use cxMapDetach().
   2.368 + *
   2.369 + * If this map is not storing pointers, this function behaves like
   2.370 + * cxMapRemove() and returns \c NULL.
   2.371 + *
   2.372 + * @param map the map
   2.373 + * @param key the key
   2.374 + * @return the stored pointer or \c NULL if either the key is not present
   2.375 + * in the map or the map is not storing pointers
   2.376 + * @see cxMapStorePointers()
   2.377 + * @see cxMapDetach()
   2.378 + */
   2.379 +__attribute__((__nonnull__, __warn_unused_result__))
   2.380 +static inline void *cxMapRemoveAndGet(
   2.381 +        CxMap *map,
   2.382 +        CxHashKey key
   2.383 +) {
   2.384 +    return map->cl->remove(map, key, !map->store_pointer);
   2.385 +}
   2.386 +
   2.387 +/**
   2.388 + * Removes a key/value-pair from the map by using the key.
   2.389 + *
   2.390 + * This function can be used when the map is storing pointers,
   2.391 + * in order to retrieve the pointer from the map without invoking
   2.392 + * any destructor function. Sometimes you do not want the pointer
   2.393 + * to be returned - in that case (instead of suppressing the "unused
   2.394 + * result" warning) you can use cxMapDetach().
   2.395 + *
   2.396 + * If this map is not storing pointers, this function behaves like
   2.397 + * cxMapRemove() and returns \c NULL.
   2.398 + *
   2.399 + * @param map the map
   2.400 + * @param key the key
   2.401 + * @return the stored pointer or \c NULL if either the key is not present
   2.402 + * in the map or the map is not storing pointers
   2.403 + * @see cxMapStorePointers()
   2.404 + * @see cxMapDetach()
   2.405 + */
   2.406 +__attribute__((__nonnull__, __warn_unused_result__))
   2.407 +static inline void *cxMapRemoveAndGet(
   2.408 +        CxMap *map,
   2.409 +        cxstring key
   2.410 +) {
   2.411 +    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
   2.412 +}
   2.413 +
   2.414 +/**
   2.415 + * Removes a key/value-pair from the map by using the key.
   2.416 + *
   2.417 + * This function can be used when the map is storing pointers,
   2.418 + * in order to retrieve the pointer from the map without invoking
   2.419 + * any destructor function. Sometimes you do not want the pointer
   2.420 + * to be returned - in that case (instead of suppressing the "unused
   2.421 + * result" warning) you can use cxMapDetach().
   2.422 + *
   2.423 + * If this map is not storing pointers, this function behaves like
   2.424 + * cxMapRemove() and returns \c NULL.
   2.425 + *
   2.426 + * @param map the map
   2.427 + * @param key the key
   2.428 + * @return the stored pointer or \c NULL if either the key is not present
   2.429 + * in the map or the map is not storing pointers
   2.430 + * @see cxMapStorePointers()
   2.431 + * @see cxMapDetach()
   2.432 + */
   2.433 +__attribute__((__nonnull__, __warn_unused_result__))
   2.434 +static inline void *cxMapRemoveAndGet(
   2.435 +        CxMap *map,
   2.436 +        char const *key
   2.437 +) {
   2.438 +    return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
   2.439 +}
   2.440 +
   2.441 +#else // __cplusplus
   2.442 +
   2.443 +/**
   2.444 + * Puts a key/value-pair into the map.
   2.445 + *
   2.446 + * @param map the map
   2.447 + * @param key the key
   2.448 + * @param value the value
   2.449 + * @return 0 on success, non-zero value on failure
   2.450 + */
   2.451 +__attribute__((__nonnull__))
   2.452 +static inline int cx_map_put(
   2.453 +        CxMap *map,
   2.454 +        CxHashKey key,
   2.455 +        void *value
   2.456 +) {
   2.457 +    return map->cl->put(map, key, value);
   2.458 +}
   2.459 +
   2.460 +/**
   2.461 + * Puts a key/value-pair into the map.
   2.462 + *
   2.463 + * @param map the map
   2.464 + * @param key the key
   2.465 + * @param value the value
   2.466 + * @return 0 on success, non-zero value on failure
   2.467 + */
   2.468 +__attribute__((__nonnull__))
   2.469 +static inline int cx_map_put_cxstr(
   2.470 +        CxMap *map,
   2.471 +        cxstring key,
   2.472 +        void *value
   2.473 +) {
   2.474 +    return map->cl->put(map, cx_hash_key_cxstr(key), value);
   2.475 +}
   2.476 +
   2.477 +/**
   2.478 + * Puts a key/value-pair into the map.
   2.479 + *
   2.480 + * @param map the map
   2.481 + * @param key the key
   2.482 + * @param value the value
   2.483 + * @return 0 on success, non-zero value on failure
   2.484 + */
   2.485 +__attribute__((__nonnull__))
   2.486 +static inline int cx_map_put_str(
   2.487 +        CxMap *map,
   2.488 +        char const *key,
   2.489 +        void *value
   2.490 +) {
   2.491 +    return map->cl->put(map, cx_hash_key_str(key), value);
   2.492 +}
   2.493 +
   2.494 +/**
   2.495 + * Puts a key/value-pair into the map.
   2.496 + *
   2.497 + * @param map the map
   2.498 + * @param key the key
   2.499 + * @param value the value
   2.500 + * @return 0 on success, non-zero value on failure
   2.501 + */
   2.502 +#define cxMapPut(map, key, value) _Generic((key), \
   2.503 +    CxHashKey: cx_map_put,                        \
   2.504 +    cxstring: cx_map_put_cxstr,                   \
   2.505 +    char*: cx_map_put_str)                        \
   2.506 +    (map, key, value)
   2.507 +
   2.508 +/**
   2.509 + * Retrieves a value by using a key.
   2.510 + *
   2.511 + * @param map the map
   2.512 + * @param key the key
   2.513 + * @return the value
   2.514 + */
   2.515 +__attribute__((__nonnull__, __warn_unused_result__))
   2.516 +static inline void *cx_map_get(
   2.517 +        CxMap const *map,
   2.518 +        CxHashKey key
   2.519 +) {
   2.520 +    return map->cl->get(map, key);
   2.521 +}
   2.522 +
   2.523 +/**
   2.524 + * Retrieves a value by using a key.
   2.525 + *
   2.526 + * @param map the map
   2.527 + * @param key the key
   2.528 + * @return the value
   2.529 + */
   2.530 +__attribute__((__nonnull__, __warn_unused_result__))
   2.531 +static inline void *cx_map_get_cxstr(
   2.532 +        CxMap const *map,
   2.533 +        cxstring key
   2.534 +) {
   2.535 +    return map->cl->get(map, cx_hash_key_cxstr(key));
   2.536 +}
   2.537 +
   2.538 +/**
   2.539 + * Retrieves a value by using a key.
   2.540 + *
   2.541 + * @param map the map
   2.542 + * @param key the key
   2.543 + * @return the value
   2.544 + */
   2.545 +__attribute__((__nonnull__, __warn_unused_result__))
   2.546 +static inline void *cx_map_get_str(
   2.547 +        CxMap const *map,
   2.548 +        char const *key
   2.549 +) {
   2.550 +    return map->cl->get(map, cx_hash_key_str(key));
   2.551 +}
   2.552 +
   2.553 +/**
   2.554 + * Retrieves a value by using a key.
   2.555 + *
   2.556 + * @param map the map
   2.557 + * @param key the key
   2.558 + * @return the value
   2.559 + */
   2.560 +#define cxMapGet(map, key) _Generic((key), \
   2.561 +    CxHashKey: cx_map_get,                 \
   2.562 +    cxstring: cx_map_get_cxstr,            \
   2.563 +    char*: cx_map_get_str)                 \
   2.564 +    (map, key)
   2.565 +
   2.566 +/**
   2.567 + * Removes a key/value-pair from the map by using the key.
   2.568 + *
   2.569 + * @param map the map
   2.570 + * @param key the key
   2.571 + */
   2.572 +__attribute__((__nonnull__))
   2.573 +static inline void cx_map_remove(
   2.574 +        CxMap *map,
   2.575 +        CxHashKey key
   2.576 +) {
   2.577 +    (void) map->cl->remove(map, key, true);
   2.578 +}
   2.579 +
   2.580 +/**
   2.581 + * Removes a key/value-pair from the map by using the key.
   2.582 + *
   2.583 + * @param map the map
   2.584 + * @param key the key
   2.585 + */
   2.586 +__attribute__((__nonnull__))
   2.587 +static inline void cx_map_remove_cxstr(
   2.588 +        CxMap *map,
   2.589 +        cxstring key
   2.590 +) {
   2.591 +    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
   2.592 +}
   2.593 +
   2.594 +/**
   2.595 + * Removes a key/value-pair from the map by using the key.
   2.596 + *
   2.597 + * @param map the map
   2.598 + * @param key the key
   2.599 + */
   2.600 +__attribute__((__nonnull__))
   2.601 +static inline void cx_map_remove_str(
   2.602 +        CxMap *map,
   2.603 +        char const *key
   2.604 +) {
   2.605 +    (void) map->cl->remove(map, cx_hash_key_str(key), true);
   2.606 +}
   2.607 +
   2.608 +/**
   2.609 + * Removes a key/value-pair from the map by using the key.
   2.610 + *
   2.611 + * Always invokes the destructor function, if any, on the removed element.
   2.612 + * If this map is storing pointers and you just want to retrieve the pointer
   2.613 + * without invoking the destructor, use cxMapRemoveAndGet().
   2.614 + * If you just want to detach the element from the map without invoking the
   2.615 + * destructor or returning the element, use cxMapDetach().
   2.616 + *
   2.617 + * @param map the map
   2.618 + * @param key the key
   2.619 + * @see cxMapRemoveAndGet()
   2.620 + * @see cxMapDetach()
   2.621 + */
   2.622 +#define cxMapRemove(map, key) _Generic((key), \
   2.623 +    CxHashKey: cx_map_remove,                 \
   2.624 +    cxstring: cx_map_remove_cxstr,            \
   2.625 +    char*: cx_map_remove_str)                 \
   2.626 +    (map, key)
   2.627 +
   2.628 +/**
   2.629 + * Detaches a key/value-pair from the map by using the key
   2.630 + * without invoking the destructor.
   2.631 + *
   2.632 + * @param map the map
   2.633 + * @param key the key
   2.634 + */
   2.635 +__attribute__((__nonnull__))
   2.636 +static inline void cx_map_detach(
   2.637 +        CxMap *map,
   2.638 +        CxHashKey key
   2.639 +) {
   2.640 +    (void) map->cl->remove(map, key, false);
   2.641 +}
   2.642 +
   2.643 +/**
   2.644 + * Detaches a key/value-pair from the map by using the key
   2.645 + * without invoking the destructor.
   2.646 + *
   2.647 + * @param map the map
   2.648 + * @param key the key
   2.649 + */
   2.650 +__attribute__((__nonnull__))
   2.651 +static inline void cx_map_detach_cxstr(
   2.652 +        CxMap *map,
   2.653 +        cxstring key
   2.654 +) {
   2.655 +    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
   2.656 +}
   2.657 +
   2.658 +/**
   2.659 + * Detaches a key/value-pair from the map by using the key
   2.660 + * without invoking the destructor.
   2.661 + *
   2.662 + * @param map the map
   2.663 + * @param key the key
   2.664 + */
   2.665 +__attribute__((__nonnull__))
   2.666 +static inline void cx_map_detach_str(
   2.667 +        CxMap *map,
   2.668 +        char const *key
   2.669 +) {
   2.670 +    (void) map->cl->remove(map, cx_hash_key_str(key), false);
   2.671 +}
   2.672 +
   2.673 +/**
   2.674 + * Detaches a key/value-pair from the map by using the key
   2.675 + * without invoking the destructor.
   2.676 + *
   2.677 + * In general, you should only use this function if the map does not own
   2.678 + * the data and there is a valid reference to the data somewhere else
   2.679 + * in the program. In all other cases it is preferable to use
   2.680 + * cxMapRemove() or cxMapRemoveAndGet().
   2.681 + *
   2.682 + * @param map the map
   2.683 + * @param key the key
   2.684 + * @see cxMapRemove()
   2.685 + * @see cxMapRemoveAndGet()
   2.686 + */
   2.687 +#define cxMapDetach(map, key) _Generic((key), \
   2.688 +    CxHashKey: cx_map_detach,                 \
   2.689 +    cxstring: cx_map_detach_cxstr,            \
   2.690 +    char*: cx_map_detach_str)                 \
   2.691 +    (map, key)
   2.692 +
   2.693 +/**
   2.694 + * Removes a key/value-pair from the map by using the key.
   2.695 + *
   2.696 + * @param map the map
   2.697 + * @param key the key
   2.698 + * @return the stored pointer or \c NULL if either the key is not present
   2.699 + * in the map or the map is not storing pointers
   2.700 + */
   2.701 +__attribute__((__nonnull__, __warn_unused_result__))
   2.702 +static inline void *cx_map_remove_and_get(
   2.703 +        CxMap *map,
   2.704 +        CxHashKey key
   2.705 +) {
   2.706 +    return map->cl->remove(map, key, !map->store_pointer);
   2.707 +}
   2.708 +
   2.709 +/**
   2.710 + * Removes a key/value-pair from the map by using the key.
   2.711 + *
   2.712 + * @param map the map
   2.713 + * @param key the key
   2.714 + * @return the stored pointer or \c NULL if either the key is not present
   2.715 + * in the map or the map is not storing pointers
   2.716 + */
   2.717 +__attribute__((__nonnull__, __warn_unused_result__))
   2.718 +static inline void *cx_map_remove_and_get_cxstr(
   2.719 +        CxMap *map,
   2.720 +        cxstring key
   2.721 +) {
   2.722 +    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
   2.723 +}
   2.724 +
   2.725 +/**
   2.726 + * Removes a key/value-pair from the map by using the key.
   2.727 + *
   2.728 + * @param map the map
   2.729 + * @param key the key
   2.730 + * @return the stored pointer or \c NULL if either the key is not present
   2.731 + * in the map or the map is not storing pointers
   2.732 + */
   2.733 +__attribute__((__nonnull__, __warn_unused_result__))
   2.734 +static inline void *cx_map_remove_and_get_str(
   2.735 +        CxMap *map,
   2.736 +        char const *key
   2.737 +) {
   2.738 +    return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
   2.739 +}
   2.740 +
   2.741 +/**
   2.742 + * Removes a key/value-pair from the map by using the key.
   2.743 + *
   2.744 + * This function can be used when the map is storing pointers,
   2.745 + * in order to retrieve the pointer from the map without invoking
   2.746 + * any destructor function. Sometimes you do not want the pointer
   2.747 + * to be returned - in that case (instead of suppressing the "unused
   2.748 + * result" warning) you can use cxMapDetach().
   2.749 + *
   2.750 + * If this map is not storing pointers, this function behaves like
   2.751 + * cxMapRemove() and returns \c NULL.
   2.752 + *
   2.753 + * @param map the map
   2.754 + * @param key the key
   2.755 + * @return the stored pointer or \c NULL if either the key is not present
   2.756 + * in the map or the map is not storing pointers
   2.757 + * @see cxMapStorePointers()
   2.758 + * @see cxMapDetach()
   2.759 + */
   2.760 +#define cxMapRemoveAndGet(map, key) _Generic((key), \
   2.761 +    CxHashKey: cx_map_remove_and_get,               \
   2.762 +    cxstring: cx_map_remove_and_get_cxstr,          \
   2.763 +    char*: cx_map_remove_and_get_str)               \
   2.764 +    (map, key)
   2.765 +
   2.766 +#endif // __cplusplus
   2.767 +
   2.768 +#endif // UCX_MAP_H
     3.1 --- a/src/hash_map.c	Fri Apr 21 18:38:18 2023 +0200
     3.2 +++ b/src/hash_map.c	Fri Apr 21 19:50:43 2023 +0200
     3.3 @@ -419,7 +419,7 @@
     3.4  };
     3.5  
     3.6  CxMap *cxHashMapCreate(
     3.7 -        CxAllocator *allocator,
     3.8 +        CxAllocator const *allocator,
     3.9          size_t itemsize,
    3.10          size_t buckets
    3.11  ) {
     4.1 --- a/tests/CMakeLists.txt	Fri Apr 21 18:38:18 2023 +0200
     4.2 +++ b/tests/CMakeLists.txt	Fri Apr 21 19:50:43 2023 +0200
     4.3 @@ -26,6 +26,7 @@
     4.4          test_tree.cpp
     4.5          test_hash_key.cpp
     4.6          test_map.cpp
     4.7 +        test_map_generics.c
     4.8          test_basic_mempool.cpp
     4.9          test_printf.cpp
    4.10          selftest.cpp
     5.1 --- a/tests/test_map.cpp	Fri Apr 21 18:38:18 2023 +0200
     5.2 +++ b/tests/test_map.cpp	Fri Apr 21 19:50:43 2023 +0200
     5.3 @@ -30,6 +30,7 @@
     5.4  #include "cx/utils.h"
     5.5  #include "cx/string.h"
     5.6  #include "util_allocator.h"
     5.7 +#include "test_map_generics.h"
     5.8  
     5.9  #include <gtest/gtest.h>
    5.10  #include <unordered_map>
    5.11 @@ -74,7 +75,7 @@
    5.12          auto keyiter = cxMapIteratorKeys(map);
    5.13          std::unordered_set<std::string> keys;
    5.14          cx_foreach(CxHashKey*, elem, keyiter) {
    5.15 -            keys.insert(std::string(reinterpret_cast<char const*>(elem->data), elem->len));
    5.16 +            keys.insert(std::string(reinterpret_cast<char const *>(elem->data), elem->len));
    5.17          }
    5.18          EXPECT_EQ(keyiter.index, map->size);
    5.19          ASSERT_EQ(keys.size(), map->size);
    5.20 @@ -103,7 +104,8 @@
    5.21          auto pairiter = cxMapIterator(map);
    5.22          std::unordered_map<std::string, std::string> pairs;
    5.23          cx_foreach(CxMapEntry*, entry, pairiter) {
    5.24 -            pairs[std::string(reinterpret_cast<char const*>(entry->key->data), entry->key->len)] = std::string((char *) entry->value);
    5.25 +            pairs[std::string(reinterpret_cast<char const *>(entry->key->data), entry->key->len)] = std::string(
    5.26 +                    (char *) entry->value);
    5.27          }
    5.28          EXPECT_EQ(pairiter.index, map->size);
    5.29          ASSERT_EQ(pairs.size(), refmap.size());
    5.30 @@ -205,26 +207,26 @@
    5.31      CxTestingAllocator allocator;
    5.32      auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 4);
    5.33  
    5.34 -    cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1");
    5.35 -    cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2");
    5.36 -    cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3");
    5.37 -    cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4");
    5.38 -    cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5");
    5.39 -    cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6");
    5.40 +    cxMapPut(map, "key 1", (void *) "val 1");
    5.41 +    cxMapPut(map, "key 2", (void *) "val 2");
    5.42 +    cxMapPut(map, "key 3", (void *) "val 3");
    5.43 +    cxMapPut(map, "key 4", (void *) "val 4");
    5.44 +    cxMapPut(map, "key 5", (void *) "val 5");
    5.45 +    cxMapPut(map, "key 6", (void *) "val 6");
    5.46  
    5.47      auto iter = cxMapMutIterator(map);
    5.48      cx_foreach(CxMapEntry*, entry, iter) {
    5.49 -        if (reinterpret_cast<char const*>(entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
    5.50 +        if (reinterpret_cast<char const *>(entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
    5.51      }
    5.52      EXPECT_EQ(map->size, 3);
    5.53      EXPECT_EQ(iter.index, map->size);
    5.54  
    5.55 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr);
    5.56 -    EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr);
    5.57 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr);
    5.58 -    EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr);
    5.59 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr);
    5.60 -    EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr);
    5.61 +    EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
    5.62 +    EXPECT_NE(cxMapGet(map, "key 2"), nullptr);
    5.63 +    EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
    5.64 +    EXPECT_NE(cxMapGet(map, "key 4"), nullptr);
    5.65 +    EXPECT_EQ(cxMapGet(map, "key 5"), nullptr);
    5.66 +    EXPECT_NE(cxMapGet(map, "key 6"), nullptr);
    5.67  
    5.68      cxMapDestroy(map);
    5.69      EXPECT_TRUE(allocator.verify());
    5.70 @@ -234,12 +236,12 @@
    5.71      CxTestingAllocator allocator;
    5.72      auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 8);
    5.73  
    5.74 -    cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1");
    5.75 -    cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2");
    5.76 -    cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3");
    5.77 -    cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4");
    5.78 -    cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5");
    5.79 -    cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6");
    5.80 +    cxMapPut(map, "key 1", (void *) "val 1");
    5.81 +    cxMapPut(map, "key 2", (void *) "val 2");
    5.82 +    cxMapPut(map, "key 3", (void *) "val 3");
    5.83 +    cxMapPut(map, "key 4", (void *) "val 4");
    5.84 +    cxMapPut(map, "key 5", (void *) "val 5");
    5.85 +    cxMapPut(map, "key 6", (void *) "val 6");
    5.86  
    5.87      // 6/8 does not exceed 0.75, therefore the function should not rehash
    5.88      int result = cxMapRehash(map);
    5.89 @@ -254,32 +256,32 @@
    5.90      CxTestingAllocator allocator;
    5.91      auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 7);
    5.92  
    5.93 -    cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1");
    5.94 -    cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2");
    5.95 -    cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3");
    5.96 -    cxMapPut(map, cx_hash_key_str("foo 4"), (void *) "val 4");
    5.97 -    cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5");
    5.98 -    cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6");
    5.99 -    cxMapPut(map, cx_hash_key_str("bar 7"), (void *) "val 7");
   5.100 -    cxMapPut(map, cx_hash_key_str("key 8"), (void *) "val 8");
   5.101 -    cxMapPut(map, cx_hash_key_str("key 9"), (void *) "val 9");
   5.102 -    cxMapPut(map, cx_hash_key_str("key 10"), (void *) "val 10");
   5.103 +    cxMapPut(map, "key 1", (void *) "val 1");
   5.104 +    cxMapPut(map, "key 2", (void *) "val 2");
   5.105 +    cxMapPut(map, "key 3", (void *) "val 3");
   5.106 +    cxMapPut(map, "foo 4", (void *) "val 4");
   5.107 +    cxMapPut(map, "key 5", (void *) "val 5");
   5.108 +    cxMapPut(map, "key 6", (void *) "val 6");
   5.109 +    cxMapPut(map, "bar 7", (void *) "val 7");
   5.110 +    cxMapPut(map, "key 8", (void *) "val 8");
   5.111 +    cxMapPut(map, "key 9", (void *) "val 9");
   5.112 +    cxMapPut(map, "key 10", (void *) "val 10");
   5.113  
   5.114      int result = cxMapRehash(map);
   5.115      EXPECT_EQ(result, 0);
   5.116      EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 25);
   5.117      EXPECT_EQ(map->size, 10);
   5.118  
   5.119 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0);
   5.120 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0);
   5.121 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0);
   5.122 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("foo 4")), "val 4"), 0);
   5.123 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0);
   5.124 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0);
   5.125 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("bar 7")), "val 7"), 0);
   5.126 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 8")), "val 8"), 0);
   5.127 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 9")), "val 9"), 0);
   5.128 -    EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 10")), "val 10"), 0);
   5.129 +    EXPECT_STREQ((char *) cxMapGet(map, "key 1"), "val 1");
   5.130 +    EXPECT_STREQ((char *) cxMapGet(map, "key 2"), "val 2");
   5.131 +    EXPECT_STREQ((char *) cxMapGet(map, "key 3"), "val 3");
   5.132 +    EXPECT_STREQ((char *) cxMapGet(map, "foo 4"), "val 4");
   5.133 +    EXPECT_STREQ((char *) cxMapGet(map, "key 5"), "val 5");
   5.134 +    EXPECT_STREQ((char *) cxMapGet(map, "key 6"), "val 6");
   5.135 +    EXPECT_STREQ((char *) cxMapGet(map, "bar 7"), "val 7");
   5.136 +    EXPECT_STREQ((char *) cxMapGet(map, "key 8"), "val 8");
   5.137 +    EXPECT_STREQ((char *) cxMapGet(map, "key 9"), "val 9");
   5.138 +    EXPECT_STREQ((char *) cxMapGet(map, "key 10"), "val 10");
   5.139  
   5.140      cxMapDestroy(map);
   5.141      EXPECT_TRUE(allocator.verify());
   5.142 @@ -289,18 +291,18 @@
   5.143      CxTestingAllocator allocator;
   5.144      auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
   5.145  
   5.146 -    cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1");
   5.147 -    cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2");
   5.148 -    cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3");
   5.149 +    cxMapPut(map, "key 1", (void *) "val 1");
   5.150 +    cxMapPut(map, "key 2", (void *) "val 2");
   5.151 +    cxMapPut(map, "key 3", (void *) "val 3");
   5.152  
   5.153      EXPECT_EQ(map->size, 3);
   5.154  
   5.155      cxMapClear(map);
   5.156  
   5.157      EXPECT_EQ(map->size, 0);
   5.158 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr);
   5.159 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr);
   5.160 -    EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr);
   5.161 +    EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
   5.162 +    EXPECT_EQ(cxMapGet(map, "key 2"), nullptr);
   5.163 +    EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
   5.164  
   5.165      cxMapDestroy(map);
   5.166      EXPECT_TRUE(allocator.verify());
   5.167 @@ -319,22 +321,22 @@
   5.168      auto s5 = CX_STR("setup");
   5.169  
   5.170      // put them into the map
   5.171 -    cxMapPut(map, cx_hash_key_str("s1"), &s1);
   5.172 -    cxMapPut(map, cx_hash_key_str("s2"), &s2);
   5.173 -    cxMapPut(map, cx_hash_key_str("s3"), &s3);
   5.174 -    cxMapPut(map, cx_hash_key_str("s4"), &s4);
   5.175 +    cxMapPut(map, "s1", &s1);
   5.176 +    cxMapPut(map, "s2", &s2);
   5.177 +    cxMapPut(map, "s3", &s3);
   5.178 +    cxMapPut(map, "s4", &s4);
   5.179  
   5.180      // overwrite a value
   5.181 -    cxMapPut(map, cx_hash_key_str("s1"), &s5);
   5.182 +    cxMapPut(map, "s1", &s5);
   5.183  
   5.184      // look up a string
   5.185 -    auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, cx_hash_key_str("s3")));
   5.186 +    auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, "s3"));
   5.187      EXPECT_EQ(s3p->length, s3.length);
   5.188      EXPECT_EQ(s3p->ptr, s3.ptr);
   5.189      EXPECT_NE(s3p, &s3);
   5.190  
   5.191      // remove a string
   5.192 -    cxMapRemove(map, cx_hash_key_str("s2"));
   5.193 +    cxMapRemove(map, "s2");
   5.194  
   5.195      // iterate
   5.196      auto ref = std::vector{s5.ptr, s3.ptr, s4.ptr};
   5.197 @@ -405,7 +407,7 @@
   5.198      {
   5.199          auto iter = cxMapMutIteratorKeys(map);
   5.200          cx_foreach(CxHashKey*, key, iter) {
   5.201 -            if (reinterpret_cast<char const*>(key->data)[4] == '1') cxIteratorFlagRemoval(iter);
   5.202 +            if (reinterpret_cast<char const *>(key->data)[4] == '1') cxIteratorFlagRemoval(iter);
   5.203          }
   5.204      }
   5.205      {
   5.206 @@ -447,3 +449,26 @@
   5.207      verify_any_destructor(map);
   5.208      EXPECT_TRUE(allocator.verify());
   5.209  }
   5.210 +
   5.211 +TEST(CxHashMap, Generics) {
   5.212 +    CxTestingAllocator allocator;
   5.213 +    auto map = test_map_generics_step_1(&allocator);
   5.214 +
   5.215 +    EXPECT_EQ(map->size, 3);
   5.216 +    EXPECT_STREQ((char *) cxMapGet(map, "test"), "test");
   5.217 +    EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
   5.218 +    EXPECT_STREQ((char *) cxMapGet(map, "hallo"), "welt");
   5.219 +
   5.220 +    test_map_generics_step_2(map);
   5.221 +
   5.222 +    EXPECT_EQ(map->size, 2);
   5.223 +    EXPECT_STREQ((char *) cxMapGet(map, "key"), "value");
   5.224 +    EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
   5.225 +
   5.226 +    test_map_generics_step_3(map);
   5.227 +
   5.228 +    EXPECT_EQ(map->size, 0);
   5.229 +
   5.230 +    cxMapDestroy(map);
   5.231 +    EXPECT_TRUE(allocator.verify());
   5.232 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tests/test_map_generics.c	Fri Apr 21 19:50:43 2023 +0200
     6.3 @@ -0,0 +1,54 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     6.8 + *
     6.9 + * Redistribution and use in source and binary forms, with or without
    6.10 + * modification, are permitted provided that the following conditions are met:
    6.11 + *
    6.12 + *   1. Redistributions of source code must retain the above copyright
    6.13 + *      notice, this list of conditions and the following disclaimer.
    6.14 + *
    6.15 + *   2. Redistributions in binary form must reproduce the above copyright
    6.16 + *      notice, this list of conditions and the following disclaimer in the
    6.17 + *      documentation and/or other materials provided with the distribution.
    6.18 + *
    6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    6.29 + * POSSIBILITY OF SUCH DAMAGE.
    6.30 + */
    6.31 +
    6.32 +#include "test_map_generics.h"
    6.33 +#include "cx/hash_map.h"
    6.34 +
    6.35 +CxMap *test_map_generics_step_1(CxAllocator const * allocator) {
    6.36 +    CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0);
    6.37 +
    6.38 +    cxMapPut(map, "test", "test");
    6.39 +    cxMapPut(map, CX_STR("foo"), "bar");
    6.40 +    cxMapPut(map, cx_str("hallo"), "welt");
    6.41 +
    6.42 +    return map;
    6.43 +}
    6.44 +
    6.45 +void test_map_generics_step_2(CxMap *map) {
    6.46 +    // note: we don't have a destructor here, so remove and detach are the same
    6.47 +    cxMapRemove(map, cx_str("test"));
    6.48 +    cxMapDetach(map, "hallo");
    6.49 +    cxMapPut(map, cx_hash_key_str("key"), "value");
    6.50 +}
    6.51 +
    6.52 +void test_map_generics_step_3(CxMap *map) {
    6.53 +    void *r;
    6.54 +    r = cxMapRemoveAndGet(map, "key");
    6.55 +    r = cxMapRemoveAndGet(map, cx_str("foo"));
    6.56 +    if (r != NULL) map->size = 47;
    6.57 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tests/test_map_generics.h	Fri Apr 21 19:50:43 2023 +0200
     7.3 @@ -0,0 +1,48 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     7.8 + *
     7.9 + * Redistribution and use in source and binary forms, with or without
    7.10 + * modification, are permitted provided that the following conditions are met:
    7.11 + *
    7.12 + *   1. Redistributions of source code must retain the above copyright
    7.13 + *      notice, this list of conditions and the following disclaimer.
    7.14 + *
    7.15 + *   2. Redistributions in binary form must reproduce the above copyright
    7.16 + *      notice, this list of conditions and the following disclaimer in the
    7.17 + *      documentation and/or other materials provided with the distribution.
    7.18 + *
    7.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    7.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    7.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    7.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    7.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    7.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    7.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    7.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    7.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    7.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    7.29 + * POSSIBILITY OF SUCH DAMAGE.
    7.30 + */
    7.31 +
    7.32 +#ifndef UCX_TEST_MAP_GENERICS_H
    7.33 +#define UCX_TEST_MAP_GENERICS_H
    7.34 +
    7.35 +#include "cx/map.h"
    7.36 +
    7.37 +#ifdef __cplusplus
    7.38 +extern "C" {
    7.39 +#endif
    7.40 +
    7.41 +CxMap *test_map_generics_step_1(CxAllocator const *);
    7.42 +
    7.43 +void test_map_generics_step_2(CxMap *);
    7.44 +
    7.45 +void test_map_generics_step_3(CxMap *);
    7.46 +
    7.47 +#ifdef __cplusplus
    7.48 +} // extern "C"
    7.49 +#endif
    7.50 +
    7.51 +#endif //UCX_TEST_MAP_GENERICS_H

mercurial