add single instance mode
[uwplayer.git] / ucx / cx / map.h
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above copyright
13  *      notice, this list of conditions and the following disclaimer in the
14  *      documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 /**
29  * \file map.h
30  * \brief Interface for map implementations.
31  * \author Mike Becker
32  * \author Olaf Wintermann
33  * \version 3.0
34  * \copyright 2-Clause BSD License
35  */
36
37 #ifndef UCX_MAP_H
38 #define UCX_MAP_H
39
40 #include "common.h"
41 #include "collection.h"
42 #include "string.h"
43 #include "hash_key.h"
44
45 #ifdef    __cplusplus
46 extern "C" {
47 #endif
48
49 /** Type for the UCX map. */
50 typedef struct cx_map_s CxMap;
51
52 /** Type for a map entry. */
53 typedef struct cx_map_entry_s CxMapEntry;
54
55 /** Type for map class definitions. */
56 typedef struct cx_map_class_s cx_map_class;
57
58 /** Structure for the UCX map. */
59 struct cx_map_s {
60     CX_COLLECTION_MEMBERS
61     /** The map class definition. */
62     cx_map_class *cl;
63 };
64
65 /**
66  * The type of iterator for a map.
67  */
68 enum cx_map_iterator_type {
69     /**
70      * Iterates over key/value pairs.
71      */
72     CX_MAP_ITERATOR_PAIRS,
73     /**
74      * Iterates over keys only.
75      */
76     CX_MAP_ITERATOR_KEYS,
77     /**
78      * Iterates over values only.
79      */
80     CX_MAP_ITERATOR_VALUES
81 };
82
83 /**
84  * The class definition for arbitrary maps.
85  */
86 struct cx_map_class_s {
87     /**
88      * Deallocates the entire memory.
89      */
90     __attribute__((__nonnull__))
91     void (*destructor)(struct cx_map_s *map);
92
93     /**
94      * Removes all elements.
95      */
96     __attribute__((__nonnull__))
97     void (*clear)(struct cx_map_s *map);
98
99     /**
100      * Add or overwrite an element.
101      */
102     __attribute__((__nonnull__))
103     int (*put)(
104             CxMap *map,
105             CxHashKey key,
106             void *value
107     );
108
109     /**
110      * Returns an element.
111      */
112     __attribute__((__nonnull__, __warn_unused_result__))
113     void *(*get)(
114             CxMap const *map,
115             CxHashKey key
116     );
117
118     /**
119      * Removes an element.
120      */
121     __attribute__((__nonnull__))
122     void *(*remove)(
123             CxMap *map,
124             CxHashKey key,
125             bool destroy
126     );
127
128     /**
129      * Creates an iterator for this map.
130      */
131     __attribute__((__nonnull__, __warn_unused_result__))
132     CxIterator (*iterator)(CxMap const *map, enum cx_map_iterator_type type);
133 };
134
135 /**
136  * A map entry.
137  */
138 struct cx_map_entry_s {
139     /**
140      * A pointer to the key.
141      */
142     CxHashKey const *key;
143     /**
144      * A pointer to the value.
145      */
146     void *value;
147 };
148
149 /**
150  * A shared instance of an empty map.
151  *
152  * Writing to that map is undefined.
153  */
154 extern CxMap *const cxEmptyMap;
155
156 /**
157  * Advises the map to store copies of the objects (default mode of operation).
158  *
159  * Retrieving objects from this map will yield pointers to the copies stored
160  * within this list.
161  *
162  * @param map the map
163  * @see cxMapStorePointers()
164  */
165 __attribute__((__nonnull__))
166 static inline void cxMapStoreObjects(CxMap *map) {
167     map->store_pointer = false;
168 }
169
170 /**
171  * Advises the map to only store pointers to the objects.
172  *
173  * Retrieving objects from this list will yield the original pointers stored.
174  *
175  * @note This function forcibly sets the element size to the size of a pointer.
176  * Invoking this function on a non-empty map that already stores copies of
177  * objects is undefined.
178  *
179  * @param map the map
180  * @see cxMapStoreObjects()
181  */
182 __attribute__((__nonnull__))
183 static inline void cxMapStorePointers(CxMap *map) {
184     map->store_pointer = true;
185     map->item_size = sizeof(void *);
186 }
187
188
189 /**
190  * Deallocates the memory of the specified map.
191  *
192  * @param map the map to be destroyed
193  */
194 __attribute__((__nonnull__))
195 static inline void cxMapDestroy(CxMap *map) {
196     map->cl->destructor(map);
197 }
198
199
200 /**
201  * Clears a map by removing all elements.
202  *
203  * @param map the map to be cleared
204  */
205 __attribute__((__nonnull__))
206 static inline void cxMapClear(CxMap *map) {
207     map->cl->clear(map);
208 }
209
210
211 // TODO: set-like map operations (union, intersect, difference)
212
213 /**
214  * Creates a value iterator for a map.
215  *
216  * \note An iterator iterates over all elements successively. Therefore the order
217  * highly depends on the map implementation and may change arbitrarily when the contents change.
218  *
219  * @param map the map to create the iterator for
220  * @return an iterator for the currently stored values
221  */
222 __attribute__((__nonnull__, __warn_unused_result__))
223 static inline CxIterator cxMapIteratorValues(CxMap const *map) {
224     return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES);
225 }
226
227 /**
228  * Creates a key iterator for a map.
229  *
230  * The elements of the iterator are keys of type CxHashKey.
231  *
232  * \note An iterator iterates over all elements successively. Therefore the order
233  * highly depends on the map implementation and may change arbitrarily when the contents change.
234  *
235  * @param map the map to create the iterator for
236  * @return an iterator for the currently stored keys
237  */
238 __attribute__((__nonnull__, __warn_unused_result__))
239 static inline CxIterator cxMapIteratorKeys(CxMap const *map) {
240     return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS);
241 }
242
243 /**
244  * Creates an iterator for a map.
245  *
246  * The elements of the iterator are key/value pairs of type CxMapEntry.
247  *
248  * \note An iterator iterates over all elements successively. Therefore the order
249  * highly depends on the map implementation and may change arbitrarily when the contents change.
250  *
251  * @param map the map to create the iterator for
252  * @return an iterator for the currently stored entries
253  * @see cxMapIteratorKeys()
254  * @see cxMapIteratorValues()
255  */
256 __attribute__((__nonnull__, __warn_unused_result__))
257 static inline CxIterator cxMapIterator(CxMap const *map) {
258     return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS);
259 }
260
261
262 /**
263  * Creates a mutating iterator over the values of a map.
264  *
265  * \note An iterator iterates over all elements successively. Therefore the order
266  * highly depends on the map implementation and may change arbitrarily when the contents change.
267  *
268  * @param map the map to create the iterator for
269  * @return an iterator for the currently stored values
270  */
271 __attribute__((__nonnull__, __warn_unused_result__))
272 CxMutIterator cxMapMutIteratorValues(CxMap *map);
273
274 /**
275  * Creates a mutating iterator over the keys of a map.
276  *
277  * The elements of the iterator are keys of type CxHashKey.
278  *
279  * \note An iterator iterates over all elements successively. Therefore the order
280  * highly depends on the map implementation and may change arbitrarily when the contents change.
281  *
282  * @param map the map to create the iterator for
283  * @return an iterator for the currently stored keys
284  */
285 __attribute__((__nonnull__, __warn_unused_result__))
286 CxMutIterator cxMapMutIteratorKeys(CxMap *map);
287
288 /**
289  * Creates a mutating iterator for a map.
290  *
291  * The elements of the iterator are key/value pairs of type CxMapEntry.
292  *
293  * \note An iterator iterates over all elements successively. Therefore the order
294  * highly depends on the map implementation and may change arbitrarily when the contents change.
295  *
296  * @param map the map to create the iterator for
297  * @return an iterator for the currently stored entries
298  * @see cxMapMutIteratorKeys()
299  * @see cxMapMutIteratorValues()
300  */
301 __attribute__((__nonnull__, __warn_unused_result__))
302 CxMutIterator cxMapMutIterator(CxMap *map);
303
304 #ifdef __cplusplus
305 } // end the extern "C" block here, because we want to start overloading
306
307 /**
308  * Puts a key/value-pair into the map.
309  *
310  * @param map the map
311  * @param key the key
312  * @param value the value
313  * @return 0 on success, non-zero value on failure
314  */
315 __attribute__((__nonnull__))
316 static inline int cxMapPut(
317         CxMap *map,
318         CxHashKey const &key,
319         void *value
320 ) {
321     return map->cl->put(map, key, value);
322 }
323
324
325 /**
326  * Puts a key/value-pair into the map.
327  *
328  * @param map the map
329  * @param key the key
330  * @param value the value
331  * @return 0 on success, non-zero value on failure
332  */
333 __attribute__((__nonnull__))
334 static inline int cxMapPut(
335         CxMap *map,
336         cxstring const &key,
337         void *value
338 ) {
339     return map->cl->put(map, cx_hash_key_cxstr(key), value);
340 }
341
342 /**
343  * Puts a key/value-pair into the map.
344  *
345  * @param map the map
346  * @param key the key
347  * @param value the value
348  * @return 0 on success, non-zero value on failure
349  */
350 __attribute__((__nonnull__))
351 static inline int cxMapPut(
352         CxMap *map,
353         cxmutstr const &key,
354         void *value
355 ) {
356     return map->cl->put(map, cx_hash_key_cxstr(key), value);
357 }
358
359 /**
360  * Puts a key/value-pair into the map.
361  *
362  * @param map the map
363  * @param key the key
364  * @param value the value
365  * @return 0 on success, non-zero value on failure
366  */
367 __attribute__((__nonnull__))
368 static inline int cxMapPut(
369         CxMap *map,
370         char const *key,
371         void *value
372 ) {
373     return map->cl->put(map, cx_hash_key_str(key), value);
374 }
375
376 /**
377  * Retrieves a value by using a key.
378  *
379  * @param map the map
380  * @param key the key
381  * @return the value
382  */
383 __attribute__((__nonnull__, __warn_unused_result__))
384 static inline void *cxMapGet(
385         CxMap const *map,
386         CxHashKey const &key
387 ) {
388     return map->cl->get(map, key);
389 }
390
391 /**
392  * Retrieves a value by using a key.
393  *
394  * @param map the map
395  * @param key the key
396  * @return the value
397  */
398 __attribute__((__nonnull__, __warn_unused_result__))
399 static inline void *cxMapGet(
400         CxMap const *map,
401         cxstring const &key
402 ) {
403     return map->cl->get(map, cx_hash_key_cxstr(key));
404 }
405
406 /**
407  * Retrieves a value by using a key.
408  *
409  * @param map the map
410  * @param key the key
411  * @return the value
412  */
413 __attribute__((__nonnull__, __warn_unused_result__))
414 static inline void *cxMapGet(
415         CxMap const *map,
416         cxmutstr const &key
417 ) {
418     return map->cl->get(map, cx_hash_key_cxstr(key));
419 }
420
421 /**
422  * Retrieves a value by using a key.
423  *
424  * @param map the map
425  * @param key the key
426  * @return the value
427  */
428 __attribute__((__nonnull__, __warn_unused_result__))
429 static inline void *cxMapGet(
430         CxMap const *map,
431         char const *key
432 ) {
433     return map->cl->get(map, cx_hash_key_str(key));
434 }
435
436 /**
437  * Removes a key/value-pair from the map by using the key.
438  *
439  * Always invokes the destructor function, if any, on the removed element.
440  * If this map is storing pointers and you just want to retrieve the pointer
441  * without invoking the destructor, use cxMapRemoveAndGet().
442  * If you just want to detach the element from the map without invoking the
443  * destructor or returning the element, use cxMapDetach().
444  *
445  * @param map the map
446  * @param key the key
447  * @see cxMapRemoveAndGet()
448  * @see cxMapDetach()
449  */
450 __attribute__((__nonnull__))
451 static inline void cxMapRemove(
452         CxMap *map,
453         CxHashKey const &key
454 ) {
455     (void) map->cl->remove(map, key, true);
456 }
457
458 /**
459  * Removes a key/value-pair from the map by using the key.
460  *
461  * Always invokes the destructor function, if any, on the removed element.
462  * If this map is storing pointers and you just want to retrieve the pointer
463  * without invoking the destructor, use cxMapRemoveAndGet().
464  * If you just want to detach the element from the map without invoking the
465  * destructor or returning the element, use cxMapDetach().
466  *
467  * @param map the map
468  * @param key the key
469  * @see cxMapRemoveAndGet()
470  * @see cxMapDetach()
471  */
472 __attribute__((__nonnull__))
473 static inline void cxMapRemove(
474         CxMap *map,
475         cxstring const &key
476 ) {
477     (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
478 }
479
480 /**
481  * Removes a key/value-pair from the map by using the key.
482  *
483  * Always invokes the destructor function, if any, on the removed element.
484  * If this map is storing pointers and you just want to retrieve the pointer
485  * without invoking the destructor, use cxMapRemoveAndGet().
486  * If you just want to detach the element from the map without invoking the
487  * destructor or returning the element, use cxMapDetach().
488  *
489  * @param map the map
490  * @param key the key
491  * @see cxMapRemoveAndGet()
492  * @see cxMapDetach()
493  */
494 __attribute__((__nonnull__))
495 static inline void cxMapRemove(
496         CxMap *map,
497         cxmutstr const &key
498 ) {
499     (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
500 }
501
502 /**
503  * Removes a key/value-pair from the map by using the key.
504  *
505  * Always invokes the destructor function, if any, on the removed element.
506  * If this map is storing pointers and you just want to retrieve the pointer
507  * without invoking the destructor, use cxMapRemoveAndGet().
508  * If you just want to detach the element from the map without invoking the
509  * destructor or returning the element, use cxMapDetach().
510  *
511  * @param map the map
512  * @param key the key
513  * @see cxMapRemoveAndGet()
514  * @see cxMapDetach()
515  */
516 __attribute__((__nonnull__))
517 static inline void cxMapRemove(
518         CxMap *map,
519         char const *key
520 ) {
521     (void) map->cl->remove(map, cx_hash_key_str(key), true);
522 }
523
524 /**
525  * Detaches a key/value-pair from the map by using the key
526  * without invoking the destructor.
527  *
528  * In general, you should only use this function if the map does not own
529  * the data and there is a valid reference to the data somewhere else
530  * in the program. In all other cases it is preferable to use
531  * cxMapRemove() or cxMapRemoveAndGet().
532  *
533  * @param map the map
534  * @param key the key
535  * @see cxMapRemove()
536  * @see cxMapRemoveAndGet()
537  */
538 __attribute__((__nonnull__))
539 static inline void cxMapDetach(
540         CxMap *map,
541         CxHashKey const &key
542 ) {
543     (void) map->cl->remove(map, key, false);
544 }
545
546 /**
547  * Detaches a key/value-pair from the map by using the key
548  * without invoking the destructor.
549  *
550  * In general, you should only use this function if the map does not own
551  * the data and there is a valid reference to the data somewhere else
552  * in the program. In all other cases it is preferable to use
553  * cxMapRemove() or cxMapRemoveAndGet().
554  *
555  * @param map the map
556  * @param key the key
557  * @see cxMapRemove()
558  * @see cxMapRemoveAndGet()
559  */
560 __attribute__((__nonnull__))
561 static inline void cxMapDetach(
562         CxMap *map,
563         cxstring const &key
564 ) {
565     (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
566 }
567
568 /**
569  * Detaches a key/value-pair from the map by using the key
570  * without invoking the destructor.
571  *
572  * In general, you should only use this function if the map does not own
573  * the data and there is a valid reference to the data somewhere else
574  * in the program. In all other cases it is preferable to use
575  * cxMapRemove() or cxMapRemoveAndGet().
576  *
577  * @param map the map
578  * @param key the key
579  * @see cxMapRemove()
580  * @see cxMapRemoveAndGet()
581  */
582 __attribute__((__nonnull__))
583 static inline void cxMapDetach(
584         CxMap *map,
585         cxmutstr const &key
586 ) {
587     (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
588 }
589
590 /**
591  * Detaches a key/value-pair from the map by using the key
592  * without invoking the destructor.
593  *
594  * In general, you should only use this function if the map does not own
595  * the data and there is a valid reference to the data somewhere else
596  * in the program. In all other cases it is preferable to use
597  * cxMapRemove() or cxMapRemoveAndGet().
598  *
599  * @param map the map
600  * @param key the key
601  * @see cxMapRemove()
602  * @see cxMapRemoveAndGet()
603  */
604 __attribute__((__nonnull__))
605 static inline void cxMapDetach(
606         CxMap *map,
607         char const *key
608 ) {
609     (void) map->cl->remove(map, cx_hash_key_str(key), false);
610 }
611
612 /**
613  * Removes a key/value-pair from the map by using the key.
614  *
615  * This function can be used when the map is storing pointers,
616  * in order to retrieve the pointer from the map without invoking
617  * any destructor function. Sometimes you do not want the pointer
618  * to be returned - in that case (instead of suppressing the "unused
619  * result" warning) you can use cxMapDetach().
620  *
621  * If this map is not storing pointers, this function behaves like
622  * cxMapRemove() and returns \c NULL.
623  *
624  * @param map the map
625  * @param key the key
626  * @return the stored pointer or \c NULL if either the key is not present
627  * in the map or the map is not storing pointers
628  * @see cxMapStorePointers()
629  * @see cxMapDetach()
630  */
631 __attribute__((__nonnull__, __warn_unused_result__))
632 static inline void *cxMapRemoveAndGet(
633         CxMap *map,
634         CxHashKey key
635 ) {
636     return map->cl->remove(map, key, !map->store_pointer);
637 }
638
639 /**
640  * Removes a key/value-pair from the map by using the key.
641  *
642  * This function can be used when the map is storing pointers,
643  * in order to retrieve the pointer from the map without invoking
644  * any destructor function. Sometimes you do not want the pointer
645  * to be returned - in that case (instead of suppressing the "unused
646  * result" warning) you can use cxMapDetach().
647  *
648  * If this map is not storing pointers, this function behaves like
649  * cxMapRemove() and returns \c NULL.
650  *
651  * @param map the map
652  * @param key the key
653  * @return the stored pointer or \c NULL if either the key is not present
654  * in the map or the map is not storing pointers
655  * @see cxMapStorePointers()
656  * @see cxMapDetach()
657  */
658 __attribute__((__nonnull__, __warn_unused_result__))
659 static inline void *cxMapRemoveAndGet(
660         CxMap *map,
661         cxstring key
662 ) {
663     return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
664 }
665
666 /**
667  * Removes a key/value-pair from the map by using the key.
668  *
669  * This function can be used when the map is storing pointers,
670  * in order to retrieve the pointer from the map without invoking
671  * any destructor function. Sometimes you do not want the pointer
672  * to be returned - in that case (instead of suppressing the "unused
673  * result" warning) you can use cxMapDetach().
674  *
675  * If this map is not storing pointers, this function behaves like
676  * cxMapRemove() and returns \c NULL.
677  *
678  * @param map the map
679  * @param key the key
680  * @return the stored pointer or \c NULL if either the key is not present
681  * in the map or the map is not storing pointers
682  * @see cxMapStorePointers()
683  * @see cxMapDetach()
684  */
685 __attribute__((__nonnull__, __warn_unused_result__))
686 static inline void *cxMapRemoveAndGet(
687         CxMap *map,
688         cxmutstr key
689 ) {
690     return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
691 }
692
693 /**
694  * Removes a key/value-pair from the map by using the key.
695  *
696  * This function can be used when the map is storing pointers,
697  * in order to retrieve the pointer from the map without invoking
698  * any destructor function. Sometimes you do not want the pointer
699  * to be returned - in that case (instead of suppressing the "unused
700  * result" warning) you can use cxMapDetach().
701  *
702  * If this map is not storing pointers, this function behaves like
703  * cxMapRemove() and returns \c NULL.
704  *
705  * @param map the map
706  * @param key the key
707  * @return the stored pointer or \c NULL if either the key is not present
708  * in the map or the map is not storing pointers
709  * @see cxMapStorePointers()
710  * @see cxMapDetach()
711  */
712 __attribute__((__nonnull__, __warn_unused_result__))
713 static inline void *cxMapRemoveAndGet(
714         CxMap *map,
715         char const *key
716 ) {
717     return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
718 }
719
720 #else // __cplusplus
721
722 /**
723  * Puts a key/value-pair into the map.
724  *
725  * @param map the map
726  * @param key the key
727  * @param value the value
728  * @return 0 on success, non-zero value on failure
729  */
730 __attribute__((__nonnull__))
731 static inline int cx_map_put(
732         CxMap *map,
733         CxHashKey key,
734         void *value
735 ) {
736     return map->cl->put(map, key, value);
737 }
738
739 /**
740  * Puts a key/value-pair into the map.
741  *
742  * @param map the map
743  * @param key the key
744  * @param value the value
745  * @return 0 on success, non-zero value on failure
746  */
747 __attribute__((__nonnull__))
748 static inline int cx_map_put_cxstr(
749         CxMap *map,
750         cxstring key,
751         void *value
752 ) {
753     return map->cl->put(map, cx_hash_key_cxstr(key), value);
754 }
755
756 /**
757  * Puts a key/value-pair into the map.
758  *
759  * @param map the map
760  * @param key the key
761  * @param value the value
762  * @return 0 on success, non-zero value on failure
763  */
764 __attribute__((__nonnull__))
765 static inline int cx_map_put_mustr(
766         CxMap *map,
767         cxmutstr key,
768         void *value
769 ) {
770     return map->cl->put(map, cx_hash_key_cxstr(key), value);
771 }
772
773 /**
774  * Puts a key/value-pair into the map.
775  *
776  * @param map the map
777  * @param key the key
778  * @param value the value
779  * @return 0 on success, non-zero value on failure
780  */
781 __attribute__((__nonnull__))
782 static inline int cx_map_put_str(
783         CxMap *map,
784         char const *key,
785         void *value
786 ) {
787     return map->cl->put(map, cx_hash_key_str(key), value);
788 }
789
790 /**
791  * Puts a key/value-pair into the map.
792  *
793  * @param map the map
794  * @param key the key
795  * @param value the value
796  * @return 0 on success, non-zero value on failure
797  */
798 #define cxMapPut(map, key, value) _Generic((key), \
799     CxHashKey: cx_map_put,                        \
800     cxstring: cx_map_put_cxstr,                   \
801     cxmutstr: cx_map_put_mustr,                   \
802     char*: cx_map_put_str,                        \
803     char const*: cx_map_put_str)                  \
804     (map, key, value)
805
806 /**
807  * Retrieves a value by using a key.
808  *
809  * @param map the map
810  * @param key the key
811  * @return the value
812  */
813 __attribute__((__nonnull__, __warn_unused_result__))
814 static inline void *cx_map_get(
815         CxMap const *map,
816         CxHashKey key
817 ) {
818     return map->cl->get(map, key);
819 }
820
821 /**
822  * Retrieves a value by using a key.
823  *
824  * @param map the map
825  * @param key the key
826  * @return the value
827  */
828 __attribute__((__nonnull__, __warn_unused_result__))
829 static inline void *cx_map_get_cxstr(
830         CxMap const *map,
831         cxstring key
832 ) {
833     return map->cl->get(map, cx_hash_key_cxstr(key));
834 }
835
836 /**
837  * Retrieves a value by using a key.
838  *
839  * @param map the map
840  * @param key the key
841  * @return the value
842  */
843 __attribute__((__nonnull__, __warn_unused_result__))
844 static inline void *cx_map_get_mustr(
845         CxMap const *map,
846         cxmutstr key
847 ) {
848     return map->cl->get(map, cx_hash_key_cxstr(key));
849 }
850
851 /**
852  * Retrieves a value by using a key.
853  *
854  * @param map the map
855  * @param key the key
856  * @return the value
857  */
858 __attribute__((__nonnull__, __warn_unused_result__))
859 static inline void *cx_map_get_str(
860         CxMap const *map,
861         char const *key
862 ) {
863     return map->cl->get(map, cx_hash_key_str(key));
864 }
865
866 /**
867  * Retrieves a value by using a key.
868  *
869  * @param map the map
870  * @param key the key
871  * @return the value
872  */
873 #define cxMapGet(map, key) _Generic((key), \
874     CxHashKey: cx_map_get,                 \
875     cxstring: cx_map_get_cxstr,            \
876     cxmutstr: cx_map_get_mustr,            \
877     char*: cx_map_get_str,                 \
878     char const*: cx_map_get_str)           \
879     (map, key)
880
881 /**
882  * Removes a key/value-pair from the map by using the key.
883  *
884  * @param map the map
885  * @param key the key
886  */
887 __attribute__((__nonnull__))
888 static inline void cx_map_remove(
889         CxMap *map,
890         CxHashKey key
891 ) {
892     (void) map->cl->remove(map, key, true);
893 }
894
895 /**
896  * Removes a key/value-pair from the map by using the key.
897  *
898  * @param map the map
899  * @param key the key
900  */
901 __attribute__((__nonnull__))
902 static inline void cx_map_remove_cxstr(
903         CxMap *map,
904         cxstring key
905 ) {
906     (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
907 }
908
909 /**
910  * Removes a key/value-pair from the map by using the key.
911  *
912  * @param map the map
913  * @param key the key
914  */
915 __attribute__((__nonnull__))
916 static inline void cx_map_remove_mustr(
917         CxMap *map,
918         cxmutstr key
919 ) {
920     (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
921 }
922
923 /**
924  * Removes a key/value-pair from the map by using the key.
925  *
926  * @param map the map
927  * @param key the key
928  */
929 __attribute__((__nonnull__))
930 static inline void cx_map_remove_str(
931         CxMap *map,
932         char const *key
933 ) {
934     (void) map->cl->remove(map, cx_hash_key_str(key), true);
935 }
936
937 /**
938  * Removes a key/value-pair from the map by using the key.
939  *
940  * Always invokes the destructor function, if any, on the removed element.
941  * If this map is storing pointers and you just want to retrieve the pointer
942  * without invoking the destructor, use cxMapRemoveAndGet().
943  * If you just want to detach the element from the map without invoking the
944  * destructor or returning the element, use cxMapDetach().
945  *
946  * @param map the map
947  * @param key the key
948  * @see cxMapRemoveAndGet()
949  * @see cxMapDetach()
950  */
951 #define cxMapRemove(map, key) _Generic((key), \
952     CxHashKey: cx_map_remove,                 \
953     cxstring: cx_map_remove_cxstr,            \
954     cxmutstr: cx_map_remove_mustr,            \
955     char*: cx_map_remove_str,                 \
956     char const*: cx_map_remove_str)           \
957     (map, key)
958
959 /**
960  * Detaches a key/value-pair from the map by using the key
961  * without invoking the destructor.
962  *
963  * @param map the map
964  * @param key the key
965  */
966 __attribute__((__nonnull__))
967 static inline void cx_map_detach(
968         CxMap *map,
969         CxHashKey key
970 ) {
971     (void) map->cl->remove(map, key, false);
972 }
973
974 /**
975  * Detaches a key/value-pair from the map by using the key
976  * without invoking the destructor.
977  *
978  * @param map the map
979  * @param key the key
980  */
981 __attribute__((__nonnull__))
982 static inline void cx_map_detach_cxstr(
983         CxMap *map,
984         cxstring key
985 ) {
986     (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
987 }
988
989 /**
990  * Detaches a key/value-pair from the map by using the key
991  * without invoking the destructor.
992  *
993  * @param map the map
994  * @param key the key
995  */
996 __attribute__((__nonnull__))
997 static inline void cx_map_detach_mustr(
998         CxMap *map,
999         cxmutstr key
1000 ) {
1001     (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
1002 }
1003
1004 /**
1005  * Detaches a key/value-pair from the map by using the key
1006  * without invoking the destructor.
1007  *
1008  * @param map the map
1009  * @param key the key
1010  */
1011 __attribute__((__nonnull__))
1012 static inline void cx_map_detach_str(
1013         CxMap *map,
1014         char const *key
1015 ) {
1016     (void) map->cl->remove(map, cx_hash_key_str(key), false);
1017 }
1018
1019 /**
1020  * Detaches a key/value-pair from the map by using the key
1021  * without invoking the destructor.
1022  *
1023  * In general, you should only use this function if the map does not own
1024  * the data and there is a valid reference to the data somewhere else
1025  * in the program. In all other cases it is preferable to use
1026  * cxMapRemove() or cxMapRemoveAndGet().
1027  *
1028  * @param map the map
1029  * @param key the key
1030  * @see cxMapRemove()
1031  * @see cxMapRemoveAndGet()
1032  */
1033 #define cxMapDetach(map, key) _Generic((key), \
1034     CxHashKey: cx_map_detach,                 \
1035     cxstring: cx_map_detach_cxstr,            \
1036     cxmutstr: cx_map_detach_mustr,            \
1037     char*: cx_map_detach_str,                 \
1038     char const*: cx_map_detach_str)           \
1039     (map, key)
1040
1041 /**
1042  * Removes a key/value-pair from the map by using the key.
1043  *
1044  * @param map the map
1045  * @param key the key
1046  * @return the stored pointer or \c NULL if either the key is not present
1047  * in the map or the map is not storing pointers
1048  */
1049 __attribute__((__nonnull__, __warn_unused_result__))
1050 static inline void *cx_map_remove_and_get(
1051         CxMap *map,
1052         CxHashKey key
1053 ) {
1054     return map->cl->remove(map, key, !map->store_pointer);
1055 }
1056
1057 /**
1058  * Removes a key/value-pair from the map by using the key.
1059  *
1060  * @param map the map
1061  * @param key the key
1062  * @return the stored pointer or \c NULL if either the key is not present
1063  * in the map or the map is not storing pointers
1064  */
1065 __attribute__((__nonnull__, __warn_unused_result__))
1066 static inline void *cx_map_remove_and_get_cxstr(
1067         CxMap *map,
1068         cxstring key
1069 ) {
1070     return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
1071 }
1072
1073 /**
1074  * Removes a key/value-pair from the map by using the key.
1075  *
1076  * @param map the map
1077  * @param key the key
1078  * @return the stored pointer or \c NULL if either the key is not present
1079  * in the map or the map is not storing pointers
1080  */
1081 __attribute__((__nonnull__, __warn_unused_result__))
1082 static inline void *cx_map_remove_and_get_mustr(
1083         CxMap *map,
1084         cxmutstr key
1085 ) {
1086     return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
1087 }
1088
1089 /**
1090  * Removes a key/value-pair from the map by using the key.
1091  *
1092  * @param map the map
1093  * @param key the key
1094  * @return the stored pointer or \c NULL if either the key is not present
1095  * in the map or the map is not storing pointers
1096  */
1097 __attribute__((__nonnull__, __warn_unused_result__))
1098 static inline void *cx_map_remove_and_get_str(
1099         CxMap *map,
1100         char const *key
1101 ) {
1102     return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
1103 }
1104
1105 /**
1106  * Removes a key/value-pair from the map by using the key.
1107  *
1108  * This function can be used when the map is storing pointers,
1109  * in order to retrieve the pointer from the map without invoking
1110  * any destructor function. Sometimes you do not want the pointer
1111  * to be returned - in that case (instead of suppressing the "unused
1112  * result" warning) you can use cxMapDetach().
1113  *
1114  * If this map is not storing pointers, this function behaves like
1115  * cxMapRemove() and returns \c NULL.
1116  *
1117  * @param map the map
1118  * @param key the key
1119  * @return the stored pointer or \c NULL if either the key is not present
1120  * in the map or the map is not storing pointers
1121  * @see cxMapStorePointers()
1122  * @see cxMapDetach()
1123  */
1124 #define cxMapRemoveAndGet(map, key) _Generic((key), \
1125     CxHashKey: cx_map_remove_and_get,               \
1126     cxstring: cx_map_remove_and_get_cxstr,          \
1127     cxmutstr: cx_map_remove_and_get_mustr,          \
1128     char*: cx_map_remove_and_get_str,               \
1129     char const*: cx_map_remove_and_get_str)         \
1130     (map, key)
1131
1132 #endif // __cplusplus
1133
1134 #endif // UCX_MAP_H