universe@549: /* universe@549: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@549: * universe@549: * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. universe@549: * universe@549: * Redistribution and use in source and binary forms, with or without universe@549: * modification, are permitted provided that the following conditions are met: universe@549: * universe@549: * 1. Redistributions of source code must retain the above copyright universe@549: * notice, this list of conditions and the following disclaimer. universe@549: * universe@549: * 2. Redistributions in binary form must reproduce the above copyright universe@549: * notice, this list of conditions and the following disclaimer in the universe@549: * documentation and/or other materials provided with the distribution. universe@549: * universe@549: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@549: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@549: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@549: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@549: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@549: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@549: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@549: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@549: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@549: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@549: * POSSIBILITY OF SUCH DAMAGE. universe@549: */ universe@549: /** universe@549: * \file map.h universe@549: * \brief Interface for map implementations. universe@549: * \author Mike Becker universe@549: * \author Olaf Wintermann universe@549: * \version 3.0 universe@549: * \copyright 2-Clause BSD License universe@549: */ universe@549: universe@549: #ifndef UCX_MAP_H universe@549: #define UCX_MAP_H universe@549: universe@681: #include "common.h" universe@677: #include "collection.h" universe@563: #include "hash_key.h" universe@549: universe@549: #ifdef __cplusplus universe@549: extern "C" { universe@549: #endif universe@549: universe@549: /** Type for the UCX map. */ universe@549: typedef struct cx_map_s CxMap; universe@549: universe@549: /** Type for a map entry. */ universe@549: typedef struct cx_map_entry_s CxMapEntry; universe@549: universe@549: /** Type for map class definitions. */ universe@549: typedef struct cx_map_class_s cx_map_class; universe@549: universe@549: /** Structure for the UCX map. */ universe@549: struct cx_map_s { universe@549: /** The map class definition. */ universe@549: cx_map_class *cl; universe@549: /** An allocator that is used for the map elements. */ universe@549: CxAllocator *allocator; universe@549: /** The number of elements currently stored. */ universe@549: size_t size; universe@658: /** universe@658: * The size of an element. universe@658: */ universe@677: size_t item_size; universe@658: /** universe@658: * True, if this map shall store pointers instead universe@658: * of copies of objects. universe@658: */ universe@658: bool store_pointers; universe@549: }; universe@549: universe@549: /** universe@549: * The class definition for arbitrary maps. universe@549: */ universe@549: struct cx_map_class_s { universe@549: /** universe@549: * Deallocates the entire memory. universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: void (*destructor)(struct cx_map_s *map); universe@549: universe@549: /** universe@549: * Removes all elements. universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: void (*clear)(struct cx_map_s *map); universe@549: universe@549: /** universe@549: * Add or overwrite an element. universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: int (*put)( universe@549: CxMap *map, universe@563: CxHashKey key, universe@550: void *value universe@549: ); universe@549: universe@549: /** universe@549: * Returns an element. universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@549: void *(*get)( universe@549: CxMap const *map, universe@563: CxHashKey key universe@549: ); universe@549: universe@549: /** universe@549: * Removes an element. universe@549: */ universe@659: __attribute__((__nonnull__)) universe@549: void *(*remove)( universe@550: CxMap *map, universe@563: CxHashKey key universe@549: ); universe@549: universe@549: /** universe@549: * Iterator over the key/value pairs. universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxIterator (*iterator)(CxMap const *map); universe@549: universe@549: /** universe@549: * Iterator over the keys. universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxIterator (*iterator_keys)(CxMap const *map); universe@549: universe@549: /** universe@549: * Iterator over the values. universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxIterator (*iterator_values)(CxMap const *map); universe@630: universe@630: /** universe@630: * Mutating iterator over the key/value pairs. universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxMutIterator (*mut_iterator)(CxMap *map); universe@630: universe@630: /** universe@630: * Mutating iterator over the keys. universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxMutIterator (*mut_iterator_keys)(CxMap *map); universe@630: universe@630: /** universe@630: * Mutating iterator over the values. universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: CxMutIterator (*mut_iterator_values)(CxMap *map); universe@549: }; universe@549: universe@549: /** universe@549: * A map entry. universe@549: */ universe@549: struct cx_map_entry_s { universe@549: /** universe@551: * A pointer to the key. universe@549: */ universe@563: CxHashKey const *key; universe@549: /** universe@551: * A pointer to the value. universe@549: */ universe@551: void *value; universe@549: }; universe@549: universe@658: /** universe@658: * Advises the map to store copies of the objects (default mode of operation). universe@658: * universe@658: * Retrieving objects from this map will yield pointers to the copies stored universe@658: * within this list. universe@658: * universe@658: * @param map the map universe@658: * @see cxMapStorePointers() universe@658: */ universe@658: __attribute__((__nonnull__)) universe@658: static inline void cxMapStoreObjects(CxMap *map) { universe@658: map->store_pointers = false; universe@658: } universe@658: universe@658: /** universe@658: * Advises the map to only store pointers to the objects. universe@658: * universe@658: * Retrieving objects from this list will yield the original pointers stored. universe@658: * universe@658: * @note This function forcibly sets the element size to the size of a pointer. universe@658: * Invoking this function on a non-empty map that already stores copies of universe@658: * objects is undefined. universe@658: * universe@658: * @param map the map universe@658: * @see cxMapStoreObjects() universe@658: */ universe@658: __attribute__((__nonnull__)) universe@658: static inline void cxMapStorePointers(CxMap *map) { universe@658: map->store_pointers = true; universe@677: map->item_size = sizeof(void *); universe@658: } universe@658: universe@549: universe@549: /** universe@549: * Deallocates the memory of the specified map. universe@549: * universe@549: * @param map the map to be destroyed universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: static inline void cxMapDestroy(CxMap *map) { universe@549: // TODO: likely to add auto-free feature for contents in the future universe@549: map->cl->destructor(map); universe@549: } universe@549: universe@549: universe@549: /** universe@549: * Clears a map by removing all elements. universe@549: * universe@549: * @param map the map to be cleared universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: static inline void cxMapClear(CxMap *map) { universe@549: map->cl->clear(map); universe@549: } universe@549: universe@549: /** universe@549: * Puts a key/value-pair into the map. universe@549: * universe@549: * @param map the map universe@549: * @param key the key universe@549: * @param value the value universe@549: * @return 0 on success, non-zero value on failure universe@549: */ universe@549: __attribute__((__nonnull__)) universe@549: static inline int cxMapPut( universe@549: CxMap *map, universe@563: CxHashKey key, universe@550: void *value universe@549: ) { universe@549: return map->cl->put(map, key, value); universe@549: } universe@549: universe@549: /** universe@549: * Retrieves a value by using a key. universe@549: * universe@549: * @param map the map universe@549: * @param key the key universe@549: * @return the value universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@553: static inline void *cxMapGet( universe@549: CxMap const *map, universe@563: CxHashKey key universe@549: ) { universe@549: return map->cl->get(map, key); universe@549: } universe@549: universe@549: /** universe@549: * Removes a key/value-pair from the map by using the key. universe@549: * universe@659: * If this map is storing pointers, you should make sure that the map universe@659: * is not the last location where this pointer is stored. universe@659: * Otherwise, use cxMapRemoveAndGet() to retrieve the pointer while universe@659: * removing it from the map. universe@659: * universe@549: * @param map the map universe@549: * @param key the key universe@659: * @see cxMapRemoveAndGet() universe@659: */ universe@659: __attribute__((__nonnull__)) universe@659: static inline void cxMapRemove( universe@659: CxMap *map, universe@659: CxHashKey key universe@659: ) { universe@659: (void) map->cl->remove(map, key); universe@659: } universe@659: universe@659: /** universe@659: * Removes a key/value-pair from the map by using the key. universe@659: * universe@659: * This function should only be used when the map is storing pointers, universe@659: * in order to retrieve the pointer you are about to remove. universe@659: * In any other case, cxMapRemove() is sufficient. universe@659: * universe@659: * @param map the map universe@659: * @param key the key universe@659: * @return the stored pointer or \c NULL if either the key is not present universe@659: * in the map or the map is not storing pointers universe@658: * @see cxMapStorePointers() universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@659: static inline void *cxMapRemoveAndGet( universe@549: CxMap *map, universe@563: CxHashKey key universe@549: ) { universe@549: return map->cl->remove(map, key); universe@549: } universe@549: universe@549: // TODO: set-like map operations (union, intersect, difference) universe@549: universe@549: /** universe@549: * Creates a value iterator for a map. universe@549: * universe@549: * \note An iterator iterates over all elements successively. Therefore the order universe@549: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@549: * universe@549: * @param map the map to create the iterator for universe@549: * @return an iterator for the currently stored values universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@551: static inline CxIterator cxMapIteratorValues(CxMap *map) { universe@549: return map->cl->iterator_values(map); universe@549: } universe@549: universe@549: /** universe@549: * Creates a key iterator for a map. universe@549: * universe@564: * The elements of the iterator are keys of type CxHashKey. universe@555: * universe@549: * \note An iterator iterates over all elements successively. Therefore the order universe@549: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@549: * universe@549: * @param map the map to create the iterator for universe@549: * @return an iterator for the currently stored keys universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@551: static inline CxIterator cxMapIteratorKeys(CxMap *map) { universe@549: return map->cl->iterator_keys(map); universe@549: } universe@549: universe@549: /** universe@549: * Creates an iterator for a map. universe@549: * universe@555: * The elements of the iterator are key/value pairs of type CxMapEntry. universe@549: * universe@549: * \note An iterator iterates over all elements successively. Therefore the order universe@549: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@549: * universe@549: * @param map the map to create the iterator for universe@555: * @return an iterator for the currently stored entries universe@549: * @see cxMapIteratorKeys() universe@549: * @see cxMapIteratorValues() universe@549: */ universe@549: __attribute__((__nonnull__, __warn_unused_result__)) universe@551: static inline CxIterator cxMapIterator(CxMap *map) { universe@549: return map->cl->iterator(map); universe@549: } universe@549: universe@630: universe@630: /** universe@630: * Creates a mutating iterator over the values of a map. universe@630: * universe@630: * \note An iterator iterates over all elements successively. Therefore the order universe@630: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@630: * universe@630: * @param map the map to create the iterator for universe@630: * @return an iterator for the currently stored values universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: static inline CxMutIterator cxMapMutIteratorValues(CxMap *map) { universe@630: return map->cl->mut_iterator_values(map); universe@630: } universe@630: universe@630: /** universe@630: * Creates a mutating iterator over the keys of a map. universe@630: * universe@630: * The elements of the iterator are keys of type CxHashKey. universe@630: * universe@630: * \note An iterator iterates over all elements successively. Therefore the order universe@630: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@630: * universe@630: * @param map the map to create the iterator for universe@630: * @return an iterator for the currently stored keys universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: static inline CxMutIterator cxMapMutIteratorKeys(CxMap *map) { universe@630: return map->cl->mut_iterator_keys(map); universe@630: } universe@630: universe@630: /** universe@630: * Creates a mutating iterator for a map. universe@630: * universe@630: * The elements of the iterator are key/value pairs of type CxMapEntry. universe@630: * universe@630: * \note An iterator iterates over all elements successively. Therefore the order universe@630: * highly depends on the map implementation and may change arbitrarily when the contents change. universe@630: * universe@630: * @param map the map to create the iterator for universe@630: * @return an iterator for the currently stored entries universe@630: * @see cxMapMutIteratorKeys() universe@630: * @see cxMapMutIteratorValues() universe@630: */ universe@630: __attribute__((__nonnull__, __warn_unused_result__)) universe@630: static inline CxMutIterator cxMapMutIterator(CxMap *map) { universe@630: return map->cl->mut_iterator(map); universe@630: } universe@630: universe@549: #ifdef __cplusplus universe@549: } universe@549: #endif universe@549: universe@549: #endif // UCX_MAP_H