--- a/ucx/cx/map.h Sat Feb 22 18:10:36 2025 +0100 +++ b/ucx/cx/map.h Sun Feb 23 14:28:47 2025 +0100 @@ -51,6 +51,9 @@ /** Type for a map entry. */ typedef struct cx_map_entry_s CxMapEntry; +/** Type for a map iterator. */ +typedef struct cx_map_iterator_s CxMapIterator; + /** Type for map class definitions. */ typedef struct cx_map_class_s cx_map_class; @@ -65,6 +68,20 @@ }; /** + * A map entry. + */ +struct cx_map_entry_s { + /** + * A pointer to the key. + */ + const CxHashKey *key; + /** + * A pointer to the value. + */ + void *value; +}; + +/** * The type of iterator for a map. */ enum cx_map_iterator_type { @@ -83,6 +100,76 @@ }; /** + * Internal iterator struct - use CxMapIterator. + */ +struct cx_map_iterator_s { + /** + * Inherited common data for all iterators. + */ + CX_ITERATOR_BASE; + + /** + * Handle for the source map. + */ + union { + /** + * Access for mutating iterators. + */ + CxMap *m; + /** + * Access for normal iterators. + */ + const CxMap *c; + } map; + + /** + * Handle for the current element. + * + * @attention Depends on the map implementation, do not assume a type (better: do not use!). + */ + void *elem; + + /** + * Reserved memory for a map entry. + * + * If a map implementation uses an incompatible layout, the iterator needs something + * to point to during iteration which @em is compatible. + */ + CxMapEntry entry; + + /** + * Field for storing the current slot number. + * + * (Used internally) + */ + size_t slot; + + /** + * Counts the elements successfully. + * It usually does not denote a stable index within the map as it would be for arrays. + */ + size_t index; + + /** + * The size of a value stored in this map. + */ + size_t elem_size; + + /** + * May contain the total number of elements, if known. + * Set to @c SIZE_MAX when the total number is unknown during iteration. + * + * @remark The UCX implementations of #CxMap always know the number of elements they store. + */ + size_t elem_count; + + /** + * The type of this iterator. + */ + enum cx_map_iterator_type type; +}; + +/** * The class definition for arbitrary maps. */ struct cx_map_class_s { @@ -132,21 +219,7 @@ /** * Creates an iterator for this map. */ - CxIterator (*iterator)(const CxMap *map, enum cx_map_iterator_type type); -}; - -/** - * A map entry. - */ -struct cx_map_entry_s { - /** - * A pointer to the key. - */ - const CxHashKey *key; - /** - * A pointer to the value. - */ - void *value; + CxMapIterator (*iterator)(const CxMap *map, enum cx_map_iterator_type type); }; /** @@ -157,59 +230,17 @@ * You can use this is a placeholder for initializing CxMap pointers * for which you do not want to reserve memory right from the beginning. */ +cx_attr_export extern CxMap *const cxEmptyMap; /** - * Advises the map to store copies of the objects (default mode of operation). - * - * Retrieving objects from this map will yield pointers to the copies stored - * within this list. - * - * @param map the map - * @see cxMapStorePointers() - */ -cx_attr_nonnull -static inline void cxMapStoreObjects(CxMap *map) { - map->collection.store_pointer = false; -} - -/** - * Advises the map to only store pointers to the objects. - * - * Retrieving objects from this list will yield the original pointers stored. - * - * @note This function forcibly sets the element size to the size of a pointer. - * Invoking this function on a non-empty map that already stores copies of - * objects is undefined. - * - * @param map the map - * @see cxMapStoreObjects() - */ -cx_attr_nonnull -static inline void cxMapStorePointers(CxMap *map) { - map->collection.store_pointer = true; - map->collection.elem_size = sizeof(void *); -} - -/** - * Returns true, if this map is storing pointers instead of the actual data. - * - * @param map - * @return true, if this map is storing pointers - * @see cxMapStorePointers() - */ -cx_attr_nonnull -static inline bool cxMapIsStoringPointers(const CxMap *map) { - return map->collection.store_pointer; -} - -/** * Deallocates the memory of the specified map. * * Also calls the content destructor functions for each element, if specified. * * @param map the map to be freed */ +cx_attr_export void cxMapFree(CxMap *map); @@ -239,6 +270,10 @@ /** * Creates a value iterator for a map. * + * When the map is storing pointers, those pointers are returned. + * Otherwise, the iterator iterates over pointers to the memory within the map where the + * respective elements are stored. + * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. * @@ -247,14 +282,15 @@ */ cx_attr_nonnull cx_attr_nodiscard -static inline CxIterator cxMapIteratorValues(const CxMap *map) { +static inline CxMapIterator cxMapIteratorValues(const CxMap *map) { return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); } /** * Creates a key iterator for a map. * - * The elements of the iterator are keys of type CxHashKey. + * The elements of the iterator are keys of type CxHashKey and the pointer returned + * during iterator shall be treated as @c const @c CxHashKey* . * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. @@ -264,14 +300,15 @@ */ cx_attr_nonnull cx_attr_nodiscard -static inline CxIterator cxMapIteratorKeys(const CxMap *map) { +static inline CxMapIterator cxMapIteratorKeys(const CxMap *map) { return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); } /** * Creates an iterator for a map. * - * The elements of the iterator are key/value pairs of type CxMapEntry. + * The elements of the iterator are key/value pairs of type CxMapEntry and the pointer returned + * during iterator shall be treated as @c const @c CxMapEntry* . * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. @@ -283,7 +320,7 @@ */ cx_attr_nonnull cx_attr_nodiscard -static inline CxIterator cxMapIterator(const CxMap *map) { +static inline CxMapIterator cxMapIterator(const CxMap *map) { return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); } @@ -291,6 +328,10 @@ /** * Creates a mutating iterator over the values of a map. * + * When the map is storing pointers, those pointers are returned. + * Otherwise, the iterator iterates over pointers to the memory within the map where the + * respective elements are stored. + * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. * @@ -299,12 +340,14 @@ */ cx_attr_nonnull cx_attr_nodiscard -CxIterator cxMapMutIteratorValues(CxMap *map); +cx_attr_export +CxMapIterator cxMapMutIteratorValues(CxMap *map); /** * Creates a mutating iterator over the keys of a map. * - * The elements of the iterator are keys of type CxHashKey. + * The elements of the iterator are keys of type CxHashKey and the pointer returned + * during iterator shall be treated as @c const @c CxHashKey* . * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. @@ -314,12 +357,14 @@ */ cx_attr_nonnull cx_attr_nodiscard -CxIterator cxMapMutIteratorKeys(CxMap *map); +cx_attr_export +CxMapIterator cxMapMutIteratorKeys(CxMap *map); /** * Creates a mutating iterator for a map. * - * The elements of the iterator are key/value pairs of type CxMapEntry. + * The elements of the iterator are key/value pairs of type CxMapEntry and the pointer returned + * during iterator shall be treated as @c const @c CxMapEntry* . * * @note An iterator iterates over all elements successively. Therefore, the order * highly depends on the map implementation and may change arbitrarily when the contents change. @@ -331,7 +376,8 @@ */ cx_attr_nonnull cx_attr_nodiscard -CxIterator cxMapMutIterator(CxMap *map); +cx_attr_export +CxMapIterator cxMapMutIterator(CxMap *map); #ifdef __cplusplus } // end the extern "C" block here, because we want to start overloading @@ -538,6 +584,8 @@ * Puts a key/value-pair into the map. * * A possible existing value will be overwritten. + * If destructor functions are specified, they are called for + * the overwritten element. * * If this map is storing pointers, the @p value pointer is written * to the map. Otherwise, the memory is copied from @p value with @@ -749,7 +797,7 @@ * Removes a key/value-pair from the map by using the key. * * This function will copy the contents of the removed element - * to the target buffer must be guaranteed to be large enough + * to the target buffer, which must be guaranteed to be large enough * to hold the element (the map's element size). * The destructor functions, if any, will @em not be called. * @@ -761,8 +809,7 @@ * @param targetbuf (@c void*) the buffer where the element shall be copied to * @retval zero success * @retval non-zero the key was not found - * - * @see cxMapStorePointers() + * * @see cxMapRemove() */ #define cxMapRemoveAndGet(map, key, targetbuf) _Generic((key), \