| /* |
| Copyright: Boaz Segev, 2017-2018 |
| License: MIT |
| */ |
| #ifndef H_FIOBJ_HASH_H |
| /** |
| * The facil.io Hash object is an ordered Hash Table implementation. |
| * |
| * By compromising some of the HashMap's collision resistance (comparing only |
| * the Hash values rather than comparing key data), memory comparison can be |
| * avoided and performance increased. |
| * |
| * By being ordered it's possible to iterate over key-value pairs in the order |
| * in which they were added to the Hash table, making it possible to output JSON |
| * in a controlled manner. |
| */ |
| #define H_FIOBJ_HASH_H |
| |
| #include <fiobject.h> |
| |
| #include <fio_siphash.h> |
| #include <fiobj_str.h> |
| |
| #include <errno.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* MUST be a power of 2 */ |
| #define HASH_INITIAL_CAPACITY 16 |
| |
| /** attempts to rehash the hashmap. */ |
| void fiobj_hash_rehash(FIOBJ h); |
| |
| /* ***************************************************************************** |
| Hash Creation |
| ***************************************************************************** */ |
| |
| /** |
| * Creates a mutable empty Hash object. Use `fiobj_free` when done. |
| * |
| * Notice that these Hash objects are optimized for smaller collections and |
| * retain order of object insertion. |
| */ |
| FIOBJ fiobj_hash_new(void); |
| |
| /** |
| * Creates a mutable empty Hash object with an initial capacity of `capa`. Use |
| * `fiobj_free` when done. |
| * |
| * This allows optimizations for larger (or smaller) collections. |
| */ |
| FIOBJ fiobj_hash_new2(size_t capa); |
| |
| /* ***************************************************************************** |
| Hash properties and state |
| ***************************************************************************** */ |
| |
| /** |
| * Returns a temporary theoretical Hash map capacity. |
| * This could be used for testing performance and memory consumption. |
| */ |
| size_t fiobj_hash_capa(const FIOBJ hash); |
| |
| /** Returns the number of elements in the Hash. */ |
| size_t fiobj_hash_count(const FIOBJ hash); |
| |
| /** Returns the key for the object in the current `fiobj_each` loop (if any). */ |
| FIOBJ fiobj_hash_key_in_loop(void); |
| |
| /* ***************************************************************************** |
| Populating the Hash |
| ***************************************************************************** */ |
| |
| /** |
| * Sets a key-value pair in the Hash, duplicating the Symbol and **moving** |
| * the ownership of the object to the Hash. |
| * |
| * Returns -1 on error. |
| */ |
| int fiobj_hash_set(FIOBJ hash, FIOBJ key, FIOBJ obj); |
| |
| /** |
| * Allows the Hash to be used as a stack. |
| * |
| * If a pointer `key` is provided, it will receive ownership of the key |
| * (remember to free). |
| * |
| * Returns FIOBJ_INVALID on error. |
| * |
| * Returns and object if successful (remember to free). |
| */ |
| FIOBJ fiobj_hash_pop(FIOBJ hash, FIOBJ *key); |
| |
| /** |
| * Replaces the value in a key-value pair, returning the old value (and it's |
| * ownership) to the caller. |
| * |
| * A return value of FIOBJ_INVALID indicates that no previous object existed |
| * (but a new key-value pair was created. |
| * |
| * Errors are silently ignored. |
| * |
| * Remember to free the returned object. |
| */ |
| FIOBJ fiobj_hash_replace(FIOBJ hash, FIOBJ key, FIOBJ obj); |
| |
| /** |
| * Removes a key-value pair from the Hash, if it exists, returning the old |
| * object (instead of freeing it). |
| */ |
| FIOBJ fiobj_hash_remove(FIOBJ hash, FIOBJ key); |
| |
| /** |
| * Removes a key-value pair from the Hash, if it exists, returning the old |
| * object (instead of freeing it). |
| */ |
| FIOBJ fiobj_hash_remove2(FIOBJ hash, uint64_t key_hash); |
| |
| /** |
| * Deletes a key-value pair from the Hash, if it exists, freeing the |
| * associated object. |
| * |
| * Returns -1 on type error or if the object never existed. |
| */ |
| int fiobj_hash_delete(FIOBJ hash, FIOBJ key); |
| |
| /** |
| * Deletes a key-value pair from the Hash, if it exists, freeing the |
| * associated object. |
| * |
| * This function takes a `uint64_t` Hash value (see `fio_siphash`) to |
| * perform a lookup in the HashMap, which is slightly faster than the other |
| * variations. |
| * |
| * Returns -1 on type error or if the object never existed. |
| */ |
| int fiobj_hash_delete2(FIOBJ hash, uint64_t key_hash); |
| |
| /** |
| * Returns a temporary handle to the object associated with the Symbol, |
| * FIOBJ_INVALID if none. |
| */ |
| FIOBJ fiobj_hash_get(const FIOBJ hash, FIOBJ key); |
| |
| /** |
| * Returns a temporary handle to the object associated hashed key value. |
| * |
| * This function takes a `uint64_t` Hash value (see `fio_siphash`) to |
| * perform a lookup in the HashMap, which is slightly faster than the other |
| * variations. |
| * |
| * Returns FIOBJ_INVALID if no object is associated with this hashed key value. |
| */ |
| FIOBJ fiobj_hash_get2(const FIOBJ hash, uint64_t key_hash); |
| |
| /** |
| * Returns 1 if the key (Symbol) exists in the Hash, even if it's value is NULL. |
| */ |
| int fiobj_hash_haskey(const FIOBJ hash, FIOBJ key); |
| |
| /** |
| * Empties the Hash. |
| */ |
| void fiobj_hash_clear(const FIOBJ hash); |
| |
| #if DEBUG |
| void fiobj_test_hash(void); |
| #endif |
| |
| #ifdef __cplusplus |
| } /* extern "C" */ |
| #endif |
| |
| #endif |