Fri, 21 Apr 2023 19:50:43 +0200
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