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