ucx/cx/map.h

Sun, 17 Dec 2023 15:33:50 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 17 Dec 2023 15:33:50 +0100
changeset 800
30d484806c2b
parent 775
e5909dff0dbf
child 816
839fefbdedc7
permissions
-rw-r--r--

fix faulty string to int conversion utilities

Probably it was expected that errno is set to EINVAL when illegal characters are encountered. But this is not standard and does not happen on every system, allowing illegal strings to be parsed as valid integers.

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * \file map.h
 * \brief Interface for map implementations.
 * \author Mike Becker
 * \author Olaf Wintermann
 * \version 3.0
 * \copyright 2-Clause BSD License
 */

#ifndef UCX_MAP_H
#define UCX_MAP_H

#include "common.h"
#include "collection.h"
#include "string.h"
#include "hash_key.h"

#ifdef    __cplusplus
extern "C" {
#endif

/** Type for the UCX map. */
typedef struct cx_map_s CxMap;

/** Type for a map entry. */
typedef struct cx_map_entry_s CxMapEntry;

/** Type for map class definitions. */
typedef struct cx_map_class_s cx_map_class;

/** Structure for the UCX map. */
struct cx_map_s {
    CX_COLLECTION_MEMBERS
    /** The map class definition. */
    cx_map_class *cl;
};

/**
 * The type of iterator for a map.
 */
enum cx_map_iterator_type {
    /**
     * Iterates over key/value pairs.
     */
    CX_MAP_ITERATOR_PAIRS,
    /**
     * Iterates over keys only.
     */
    CX_MAP_ITERATOR_KEYS,
    /**
     * Iterates over values only.
     */
    CX_MAP_ITERATOR_VALUES
};

/**
 * The class definition for arbitrary maps.
 */
struct cx_map_class_s {
    /**
     * Deallocates the entire memory.
     */
    __attribute__((__nonnull__))
    void (*destructor)(struct cx_map_s *map);

    /**
     * Removes all elements.
     */
    __attribute__((__nonnull__))
    void (*clear)(struct cx_map_s *map);

    /**
     * Add or overwrite an element.
     */
    __attribute__((__nonnull__))
    int (*put)(
            CxMap *map,
            CxHashKey key,
            void *value
    );

    /**
     * Returns an element.
     */
    __attribute__((__nonnull__, __warn_unused_result__))
    void *(*get)(
            CxMap const *map,
            CxHashKey key
    );

    /**
     * Removes an element.
     */
    __attribute__((__nonnull__))
    void *(*remove)(
            CxMap *map,
            CxHashKey key,
            bool destroy
    );

    /**
     * Creates an iterator for this map.
     */
    __attribute__((__nonnull__, __warn_unused_result__))
    CxIterator (*iterator)(CxMap const *map, enum cx_map_iterator_type type);
};

/**
 * A map entry.
 */
struct cx_map_entry_s {
    /**
     * A pointer to the key.
     */
    CxHashKey const *key;
    /**
     * A pointer to the value.
     */
    void *value;
};

/**
 * A shared instance of an empty map.
 *
 * Writing to that map is undefined.
 */
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()
 */
__attribute__((__nonnull__))
static inline void cxMapStoreObjects(CxMap *map) {
    map->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()
 */
__attribute__((__nonnull__))
static inline void cxMapStorePointers(CxMap *map) {
    map->store_pointer = true;
    map->item_size = sizeof(void *);
}


/**
 * Deallocates the memory of the specified map.
 *
 * @param map the map to be destroyed
 */
__attribute__((__nonnull__))
static inline void cxMapDestroy(CxMap *map) {
    map->cl->destructor(map);
}


/**
 * Clears a map by removing all elements.
 *
 * @param map the map to be cleared
 */
__attribute__((__nonnull__))
static inline void cxMapClear(CxMap *map) {
    map->cl->clear(map);
}


// TODO: set-like map operations (union, intersect, difference)

/**
 * Creates a value iterator for a map.
 *
 * \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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored values
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxIterator cxMapIteratorValues(CxMap const *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.
 *
 * \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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored keys
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxIterator cxMapIteratorKeys(CxMap const *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.
 *
 * \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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored entries
 * @see cxMapIteratorKeys()
 * @see cxMapIteratorValues()
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline CxIterator cxMapIterator(CxMap const *map) {
    return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS);
}


/**
 * Creates a mutating iterator over the values of a map.
 *
 * \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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored values
 */
__attribute__((__nonnull__, __warn_unused_result__))
CxMutIterator cxMapMutIteratorValues(CxMap *map);

/**
 * Creates a mutating iterator over the keys of a map.
 *
 * The elements of the iterator are keys of type 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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored keys
 */
__attribute__((__nonnull__, __warn_unused_result__))
CxMutIterator cxMapMutIteratorKeys(CxMap *map);

/**
 * Creates a mutating iterator for a map.
 *
 * The elements of the iterator are key/value pairs of type 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.
 *
 * @param map the map to create the iterator for
 * @return an iterator for the currently stored entries
 * @see cxMapMutIteratorKeys()
 * @see cxMapMutIteratorValues()
 */
__attribute__((__nonnull__, __warn_unused_result__))
CxMutIterator cxMapMutIterator(CxMap *map);

#ifdef __cplusplus
} // end the extern "C" block here, because we want to start overloading

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cxMapPut(
        CxMap *map,
        CxHashKey const &key,
        void *value
) {
    return map->cl->put(map, key, value);
}


/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cxMapPut(
        CxMap *map,
        cxstring const &key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_cxstr(key), value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cxMapPut(
        CxMap *map,
        cxmutstr const &key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_cxstr(key), value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cxMapPut(
        CxMap *map,
        char const *key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_str(key), value);
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapGet(
        CxMap const *map,
        CxHashKey const &key
) {
    return map->cl->get(map, key);
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapGet(
        CxMap const *map,
        cxstring const &key
) {
    return map->cl->get(map, cx_hash_key_cxstr(key));
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapGet(
        CxMap const *map,
        cxmutstr const &key
) {
    return map->cl->get(map, cx_hash_key_cxstr(key));
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapGet(
        CxMap const *map,
        char const *key
) {
    return map->cl->get(map, cx_hash_key_str(key));
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * Always invokes the destructor function, if any, on the removed element.
 * If this map is storing pointers and you just want to retrieve the pointer
 * without invoking the destructor, use cxMapRemoveAndGet().
 * If you just want to detach the element from the map without invoking the
 * destructor or returning the element, use cxMapDetach().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemoveAndGet()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__))
static inline void cxMapRemove(
        CxMap *map,
        CxHashKey const &key
) {
    (void) map->cl->remove(map, key, true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * Always invokes the destructor function, if any, on the removed element.
 * If this map is storing pointers and you just want to retrieve the pointer
 * without invoking the destructor, use cxMapRemoveAndGet().
 * If you just want to detach the element from the map without invoking the
 * destructor or returning the element, use cxMapDetach().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemoveAndGet()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__))
static inline void cxMapRemove(
        CxMap *map,
        cxstring const &key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * Always invokes the destructor function, if any, on the removed element.
 * If this map is storing pointers and you just want to retrieve the pointer
 * without invoking the destructor, use cxMapRemoveAndGet().
 * If you just want to detach the element from the map without invoking the
 * destructor or returning the element, use cxMapDetach().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemoveAndGet()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__))
static inline void cxMapRemove(
        CxMap *map,
        cxmutstr const &key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * Always invokes the destructor function, if any, on the removed element.
 * If this map is storing pointers and you just want to retrieve the pointer
 * without invoking the destructor, use cxMapRemoveAndGet().
 * If you just want to detach the element from the map without invoking the
 * destructor or returning the element, use cxMapDetach().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemoveAndGet()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__))
static inline void cxMapRemove(
        CxMap *map,
        char const *key
) {
    (void) map->cl->remove(map, cx_hash_key_str(key), true);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * In general, you should only use this function if the map does not own
 * the data and there is a valid reference to the data somewhere else
 * in the program. In all other cases it is preferable to use
 * cxMapRemove() or cxMapRemoveAndGet().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemove()
 * @see cxMapRemoveAndGet()
 */
__attribute__((__nonnull__))
static inline void cxMapDetach(
        CxMap *map,
        CxHashKey const &key
) {
    (void) map->cl->remove(map, key, false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * In general, you should only use this function if the map does not own
 * the data and there is a valid reference to the data somewhere else
 * in the program. In all other cases it is preferable to use
 * cxMapRemove() or cxMapRemoveAndGet().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemove()
 * @see cxMapRemoveAndGet()
 */
__attribute__((__nonnull__))
static inline void cxMapDetach(
        CxMap *map,
        cxstring const &key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * In general, you should only use this function if the map does not own
 * the data and there is a valid reference to the data somewhere else
 * in the program. In all other cases it is preferable to use
 * cxMapRemove() or cxMapRemoveAndGet().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemove()
 * @see cxMapRemoveAndGet()
 */
__attribute__((__nonnull__))
static inline void cxMapDetach(
        CxMap *map,
        cxmutstr const &key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * In general, you should only use this function if the map does not own
 * the data and there is a valid reference to the data somewhere else
 * in the program. In all other cases it is preferable to use
 * cxMapRemove() or cxMapRemoveAndGet().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemove()
 * @see cxMapRemoveAndGet()
 */
__attribute__((__nonnull__))
static inline void cxMapDetach(
        CxMap *map,
        char const *key
) {
    (void) map->cl->remove(map, cx_hash_key_str(key), false);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * This function can be used when the map is storing pointers,
 * in order to retrieve the pointer from the map without invoking
 * any destructor function. Sometimes you do not want the pointer
 * to be returned - in that case (instead of suppressing the "unused
 * result" warning) you can use cxMapDetach().
 *
 * If this map is not storing pointers, this function behaves like
 * cxMapRemove() and returns \c NULL.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 * @see cxMapStorePointers()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapRemoveAndGet(
        CxMap *map,
        CxHashKey key
) {
    return map->cl->remove(map, key, !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * This function can be used when the map is storing pointers,
 * in order to retrieve the pointer from the map without invoking
 * any destructor function. Sometimes you do not want the pointer
 * to be returned - in that case (instead of suppressing the "unused
 * result" warning) you can use cxMapDetach().
 *
 * If this map is not storing pointers, this function behaves like
 * cxMapRemove() and returns \c NULL.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 * @see cxMapStorePointers()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapRemoveAndGet(
        CxMap *map,
        cxstring key
) {
    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * This function can be used when the map is storing pointers,
 * in order to retrieve the pointer from the map without invoking
 * any destructor function. Sometimes you do not want the pointer
 * to be returned - in that case (instead of suppressing the "unused
 * result" warning) you can use cxMapDetach().
 *
 * If this map is not storing pointers, this function behaves like
 * cxMapRemove() and returns \c NULL.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 * @see cxMapStorePointers()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapRemoveAndGet(
        CxMap *map,
        cxmutstr key
) {
    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * This function can be used when the map is storing pointers,
 * in order to retrieve the pointer from the map without invoking
 * any destructor function. Sometimes you do not want the pointer
 * to be returned - in that case (instead of suppressing the "unused
 * result" warning) you can use cxMapDetach().
 *
 * If this map is not storing pointers, this function behaves like
 * cxMapRemove() and returns \c NULL.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 * @see cxMapStorePointers()
 * @see cxMapDetach()
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cxMapRemoveAndGet(
        CxMap *map,
        char const *key
) {
    return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
}

#else // __cplusplus

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cx_map_put(
        CxMap *map,
        CxHashKey key,
        void *value
) {
    return map->cl->put(map, key, value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cx_map_put_cxstr(
        CxMap *map,
        cxstring key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_cxstr(key), value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cx_map_put_mustr(
        CxMap *map,
        cxmutstr key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_cxstr(key), value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
__attribute__((__nonnull__))
static inline int cx_map_put_str(
        CxMap *map,
        char const *key,
        void *value
) {
    return map->cl->put(map, cx_hash_key_str(key), value);
}

/**
 * Puts a key/value-pair into the map.
 *
 * @param map the map
 * @param key the key
 * @param value the value
 * @return 0 on success, non-zero value on failure
 */
#define cxMapPut(map, key, value) _Generic((key), \
    CxHashKey: cx_map_put,                        \
    cxstring: cx_map_put_cxstr,                   \
    cxmutstr: cx_map_put_mustr,                   \
    char*: cx_map_put_str,                        \
    char const*: cx_map_put_str)                  \
    (map, key, value)

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_get(
        CxMap const *map,
        CxHashKey key
) {
    return map->cl->get(map, key);
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_get_cxstr(
        CxMap const *map,
        cxstring key
) {
    return map->cl->get(map, cx_hash_key_cxstr(key));
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_get_mustr(
        CxMap const *map,
        cxmutstr key
) {
    return map->cl->get(map, cx_hash_key_cxstr(key));
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_get_str(
        CxMap const *map,
        char const *key
) {
    return map->cl->get(map, cx_hash_key_str(key));
}

/**
 * Retrieves a value by using a key.
 *
 * @param map the map
 * @param key the key
 * @return the value
 */
#define cxMapGet(map, key) _Generic((key), \
    CxHashKey: cx_map_get,                 \
    cxstring: cx_map_get_cxstr,            \
    cxmutstr: cx_map_get_mustr,            \
    char*: cx_map_get_str,                 \
    char const*: cx_map_get_str)           \
    (map, key)

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_remove(
        CxMap *map,
        CxHashKey key
) {
    (void) map->cl->remove(map, key, true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_remove_cxstr(
        CxMap *map,
        cxstring key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_remove_mustr(
        CxMap *map,
        cxmutstr key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_remove_str(
        CxMap *map,
        char const *key
) {
    (void) map->cl->remove(map, cx_hash_key_str(key), true);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * Always invokes the destructor function, if any, on the removed element.
 * If this map is storing pointers and you just want to retrieve the pointer
 * without invoking the destructor, use cxMapRemoveAndGet().
 * If you just want to detach the element from the map without invoking the
 * destructor or returning the element, use cxMapDetach().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemoveAndGet()
 * @see cxMapDetach()
 */
#define cxMapRemove(map, key) _Generic((key), \
    CxHashKey: cx_map_remove,                 \
    cxstring: cx_map_remove_cxstr,            \
    cxmutstr: cx_map_remove_mustr,            \
    char*: cx_map_remove_str,                 \
    char const*: cx_map_remove_str)           \
    (map, key)

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_detach(
        CxMap *map,
        CxHashKey key
) {
    (void) map->cl->remove(map, key, false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_detach_cxstr(
        CxMap *map,
        cxstring key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_detach_mustr(
        CxMap *map,
        cxmutstr key
) {
    (void) map->cl->remove(map, cx_hash_key_cxstr(key), false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * @param map the map
 * @param key the key
 */
__attribute__((__nonnull__))
static inline void cx_map_detach_str(
        CxMap *map,
        char const *key
) {
    (void) map->cl->remove(map, cx_hash_key_str(key), false);
}

/**
 * Detaches a key/value-pair from the map by using the key
 * without invoking the destructor.
 *
 * In general, you should only use this function if the map does not own
 * the data and there is a valid reference to the data somewhere else
 * in the program. In all other cases it is preferable to use
 * cxMapRemove() or cxMapRemoveAndGet().
 *
 * @param map the map
 * @param key the key
 * @see cxMapRemove()
 * @see cxMapRemoveAndGet()
 */
#define cxMapDetach(map, key) _Generic((key), \
    CxHashKey: cx_map_detach,                 \
    cxstring: cx_map_detach_cxstr,            \
    cxmutstr: cx_map_detach_mustr,            \
    char*: cx_map_detach_str,                 \
    char const*: cx_map_detach_str)           \
    (map, key)

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_remove_and_get(
        CxMap *map,
        CxHashKey key
) {
    return map->cl->remove(map, key, !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_remove_and_get_cxstr(
        CxMap *map,
        cxstring key
) {
    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_remove_and_get_mustr(
        CxMap *map,
        cxmutstr key
) {
    return map->cl->remove(map, cx_hash_key_cxstr(key), !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 */
__attribute__((__nonnull__, __warn_unused_result__))
static inline void *cx_map_remove_and_get_str(
        CxMap *map,
        char const *key
) {
    return map->cl->remove(map, cx_hash_key_str(key), !map->store_pointer);
}

/**
 * Removes a key/value-pair from the map by using the key.
 *
 * This function can be used when the map is storing pointers,
 * in order to retrieve the pointer from the map without invoking
 * any destructor function. Sometimes you do not want the pointer
 * to be returned - in that case (instead of suppressing the "unused
 * result" warning) you can use cxMapDetach().
 *
 * If this map is not storing pointers, this function behaves like
 * cxMapRemove() and returns \c NULL.
 *
 * @param map the map
 * @param key the key
 * @return the stored pointer or \c NULL if either the key is not present
 * in the map or the map is not storing pointers
 * @see cxMapStorePointers()
 * @see cxMapDetach()
 */
#define cxMapRemoveAndGet(map, key) _Generic((key), \
    CxHashKey: cx_map_remove_and_get,               \
    cxstring: cx_map_remove_and_get_cxstr,          \
    cxmutstr: cx_map_remove_and_get_mustr,          \
    char*: cx_map_remove_and_get_str,               \
    char const*: cx_map_remove_and_get_str)         \
    (map, key)

#endif // __cplusplus

#endif // UCX_MAP_H

mercurial