• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
175