quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_htable.h (6517B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2023 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #ifndef __ARES__HTABLE_H
     27 #define __ARES__HTABLE_H
     28 
     29 
     30 /*! \addtogroup ares_htable Base HashTable Data Structure
     31  *
     32  * This is a basic hashtable data structure that is meant to be wrapped
     33  * by a higher level implementation.  This data structure is designed to
     34  * be callback-based in order to facilitate wrapping without needing to
     35  * worry about any underlying complexities of the hashtable implementation.
     36  *
     37  * This implementation supports automatic growing by powers of 2 when reaching
     38  * 75% capacity.  A rehash will be performed on the expanded bucket list.
     39  *
     40  * Average time complexity:
     41  *  - Insert: O(1)
     42  *  - Search: O(1)
     43  *  - Delete: O(1)
     44  *
     45  * @{
     46  */
     47 
     48 struct ares_htable;
     49 
     50 /*! Opaque data type for generic hash table implementation */
     51 typedef struct ares_htable ares_htable_t;
     52 
     53 /*! Callback for generating a hash of the key.
     54  *
     55  *  \param[in] key   pointer to key to be hashed
     56  *  \param[in] seed  randomly generated seed used by hash function.
     57  *                   value is specific to the hashtable instance
     58  *                   but otherwise will not change between calls.
     59  *  \return hash
     60  */
     61 typedef unsigned int (*ares_htable_hashfunc_t)(const void  *key,
     62                                                unsigned int seed);
     63 
     64 /*! Callback to free the bucket
     65  *
     66  *  \param[in] bucket  user provided bucket
     67  */
     68 typedef void (*ares_htable_bucket_free_t)(void *bucket);
     69 
     70 /*! Callback to extract the key from the user-provided bucket
     71  *
     72  *  \param[in] bucket  user provided bucket
     73  *  \return pointer to key held in bucket
     74  */
     75 typedef const void *(*ares_htable_bucket_key_t)(const void *bucket);
     76 
     77 /*! Callback to compare two keys for equality
     78  *
     79  *  \param[in] key1  first key
     80  *  \param[in] key2  second key
     81  *  \return ARES_TRUE if equal, ARES_FALSE if not
     82  */
     83 typedef ares_bool_t (*ares_htable_key_eq_t)(const void *key1, const void *key2);
     84 
     85 
     86 /*! Destroy the initialized hashtable
     87  *
     88  *  \param[in] htable initialized hashtable
     89  */
     90 void           ares_htable_destroy(ares_htable_t *htable);
     91 
     92 /*! Create a new hashtable
     93  *
     94  *  \param[in] hash_func   Required. Callback for Hash function.
     95  *  \param[in] bucket_key  Required. Callback to extract key from bucket.
     96  *  \param[in] bucket_free Required. Callback to free bucket.
     97  *  \param[in] key_eq      Required. Callback to check for key equality.
     98  *  \return initialized hashtable.  NULL if out of memory or misuse.
     99  */
    100 ares_htable_t *ares_htable_create(ares_htable_hashfunc_t    hash_func,
    101                                   ares_htable_bucket_key_t  bucket_key,
    102                                   ares_htable_bucket_free_t bucket_free,
    103                                   ares_htable_key_eq_t      key_eq);
    104 
    105 /*! Count of keys from initialized hashtable
    106  *
    107  *  \param[in] htable  Initialized hashtable.
    108  *  \return count of keys
    109  */
    110 size_t         ares_htable_num_keys(const ares_htable_t *htable);
    111 
    112 /*! Retrieve an array of buckets from the hashtable.  This is mainly used as
    113  *  a helper for retrieving an array of keys.
    114  *
    115  *  \param[in]  htable   Initialized hashtable
    116  *  \param[out] num      Count of returned buckets
    117  *  \return Array of pointers to the buckets.  These are internal pointers
    118  *          to data within the hashtable, so if the key is removed, there
    119  *          will be a dangling pointer.  It is expected wrappers will make
    120  *          such values safe by duplicating them.
    121  */
    122 const void **ares_htable_all_buckets(const ares_htable_t *htable, size_t *num);
    123 
    124 /*! Insert bucket into hashtable
    125  *
    126  *  \param[in] htable  Initialized hashtable.
    127  *  \param[in] bucket  User-provided bucket to insert. Takes "ownership". Not
    128  *                     allowed to be NULL.
    129  *  \return ARES_TRUE on success, ARES_FALSE if out of memory
    130  */
    131 ares_bool_t  ares_htable_insert(ares_htable_t *htable, void *bucket);
    132 
    133 /*! Retrieve bucket from hashtable based on key.
    134  *
    135  *  \param[in] htable  Initialized hashtable
    136  *  \param[in] key     Pointer to key to use for comparison.
    137  *  \return matching bucket, or NULL if not found.
    138  */
    139 void        *ares_htable_get(const ares_htable_t *htable, const void *key);
    140 
    141 /*! Remove bucket from hashtable by key
    142  *
    143  *  \param[in] htable  Initialized hashtable
    144  *  \param[in] key     Pointer to key to use for comparison
    145  *  \return ARES_TRUE if found, ARES_FALSE if not found
    146  */
    147 ares_bool_t  ares_htable_remove(ares_htable_t *htable, const void *key);
    148 
    149 /*! FNV1a hash algorithm.  Can be used as underlying primitive for building
    150  *  a wrapper hashtable.
    151  *
    152  *  \param[in] key      pointer to key
    153  *  \param[in] key_len  Length of key
    154  *  \param[in] seed     Seed for generating hash
    155  *  \return hash value
    156  */
    157 unsigned int ares_htable_hash_FNV1a(const unsigned char *key, size_t key_len,
    158                                     unsigned int seed);
    159 
    160 /*! FNV1a hash algorithm, but converts all characters to lowercase before
    161  *  hashing to make the hash case-insensitive. Can be used as underlying
    162  *  primitive for building a wrapper hashtable.  Used on string-based keys.
    163  *
    164  *  \param[in] key      pointer to key
    165  *  \param[in] key_len  Length of key
    166  *  \param[in] seed     Seed for generating hash
    167  *  \return hash value
    168  */
    169 unsigned int ares_htable_hash_FNV1a_casecmp(const unsigned char *key,
    170                                             size_t key_len, unsigned int seed);
    171 
    172 /*! @} */
    173 
    174 #endif /* __ARES__HTABLE_H */