Mstdlib-1.24.0
m_hash_strvp.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
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 shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_HASH_STRVP_H__
25#define __M_HASH_STRVP_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31
32/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
33
34__BEGIN_DECLS
35
36/*! \addtogroup m_hash_strvp Hashtable - String/Void Pointer
37 * \ingroup m_hashtable
38 *
39 * Hashtable, meant for storing string keys and void pointer values.
40 *
41 * References to the data will always be read-only.
42 * All keys will be duplicated by the hashtable.
43 * Values will not be duplicated.
44 *
45 * @{
46 */
47
48struct M_hash_strvp;
49/* Currently a direct map to M_hashtable private opaque type,
50 * simply using casting to prevent the 'wrap' overhead of mallocing when it
51 * is not necessary.
52 */
53typedef struct M_hash_strvp M_hash_strvp_t;
54
55struct M_hash_strvp_enum;
56/* Used for enumerating a M_hash_strvp. */
57typedef struct M_hash_strvp_enum M_hash_strvp_enum_t;
58
59
60/*! Flags for controlling the behavior of the hashtable. */
61typedef enum {
62 M_HASH_STRVP_NONE = 0, /*!< Case sensitive single value (new values replace). */
63 M_HASH_STRVP_CASECMP = 1 << 0, /*!< Key compare is case insensitive. */
64 M_HASH_STRVP_KEYS_UPPER = 1 << 1, /*!< Keys will be upper cased before being inserted. Should be used
65 in conjunction with M_HASH_STRVP_CASECMP. */
66 M_HASH_STRVP_KEYS_LOWER = 1 << 2, /*!< Keys will be lower cased before being inserted. Should be used
67 in conjunction with M_HASH_STRVP_CASECMP. */
68 M_HASH_STRVP_KEYS_ORDERED = 1 << 3, /*!< Keys should be ordered. Default is insertion order unless the
69 sorted option is specified. */
70 M_HASH_STRVP_KEYS_SORTASC = 1 << 4, /*!< When the keys are ordered sort them using the key_equality function. */
71 M_HASH_STRVP_KEYS_SORTDESC = 1 << 5, /*!< When the keys are ordered sort them using the key_equality function. */
72 M_HASH_STRVP_MULTI_VALUE = 1 << 6, /*!< Allow keys to contain multiple values.
73 Sorted in insertion order another sorting is specified. */
74 M_HASH_STRVP_MULTI_GETLAST = 1 << 7, /*!< When using get and get_direct function get the last value from the list
75 when allowing multiple values. The default is to get the first value. */
76 M_HASH_STRVP_STATIC_SEED = 1 << 8 /*!< Use a static seed for hash function initialization. This greatly reduces
77 the security of the hashtable and removes collision attack protections.
78 This should only be used as a performance optimization when creating
79 millions of hashtables with static data specifically for quick look up.
80 DO _NOT_ use this flag with any hashtable that could store user
81 generated data! Be very careful about duplicating a hashtable that
82 was created with this flag. All duplicates will use the static seed. */
84
85
86/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
87
88/*! Create a new hashtable.
89 *
90 * The hashtable will pre-allocate an array of buckets based on the rounded up size specified. Any hash collisions
91 * will result in those collisions being chained together via a linked list. The hashtable will auto-expand by a
92 * power of 2 when the fill percentage specified is reached. All key entries are compared in a case-insensitive
93 * fashion, and are duplicated internally. Values are duplicated. Case is preserved for both keys and values.
94 *
95 * \param[in] size Size of the hash table. If not specified as a power of 2, will
96 * be rounded up to the nearest power of 2.
97 * \param[in] fillpct The maximum fill percentage before the hash table is expanded. If
98 * 0 is specified, the hashtable will never expand, otherwise the
99 * value must be between 1 and 99 (recommended: 75).
100 * \param[in] flags M_hash_strvp_flags_t flags for modifying behavior.
101 * \param[in] destroy_func The function to be called to destroy value when the hashtable
102 * itself is destroyed. Can be NULL.
103 *
104 * \return Allocated hashtable.
105 *
106 * \see M_hash_strvp_destroy
107 */
108M_API M_hash_strvp_t *M_hash_strvp_create(size_t size, M_uint8 fillpct, M_uint32 flags, void (*destroy_func)(void *)) M_MALLOC_ALIASED;
109
110
111/*! Destroy the hashtable.
112 *
113 * \param[in] h Hashtable to destroy
114 * \param[in] destroy_vals M_TRUE if the values held by the hashtable should be destroyed.
115 * This will almost always be M_TRUE. This should only be set to M_FALSE
116 * when all values held by the hashtable are being managed externally.
117 */
118M_API void M_hash_strvp_destroy(M_hash_strvp_t *h, M_bool destroy_vals) M_FREE(1);
119
120
121/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
122
123/*! Insert an entry into the hashtable.
124 *
125 * \param[in,out] h Hashtable being referenced.
126 * \param[in] key Key to insert.
127 * A NULL or empty string is explicity disallowed.
128 * \param[in] value Value to insert into hashtable. Value will not be duplicated.
129 * The hashtable will take ownership of the value. Maybe NULL.
130 *
131 * \return M_TRUE on success, or M_FALSE on failure.
132 */
133M_API M_bool M_hash_strvp_insert(M_hash_strvp_t *h, const char *key, void *value);
134
135
136/*! Remove an entry from the hashtable.
137 *
138 * \param[in,out] h Hashtable being referenced.
139 * \param[in] key Key to remove from the hashtable.
140 * A NULL or empty string is explicitly disallowed.
141 * \param[in] destroy_vals M_TRUE if the value held by the hashtable should be destroyed.
142 * This will almost always be M_TRUE. This should only be set to M_FALSE
143 * when the value held by the hashtable is being managed externally.
144 *
145 * \return M_TRUE on success, or M_FALSE if key does not exist.
146 */
147M_API M_bool M_hash_strvp_remove(M_hash_strvp_t *h, const char *key, M_bool destroy_vals);
148
149
150/*! Retrieve the value for a key from the hashtable.
151 *
152 * \param[in] h Hashtable being referenced.
153 * \param[in] key Key for value.
154 * A NULL or empty string is explicitly disallowed.
155 * \param[out] value Pointer to value stored in the hashtable. Optional, pass NULL if not needed.
156 *
157 * \return M_TRUE if value retrieved, M_FALSE if key does not exist.
158 */
159M_API M_bool M_hash_strvp_get(const M_hash_strvp_t *h, const char *key, void **value);
160
161
162/*! Retrieve the value for a key from the hashtable, and return it directly as the return value.
163 *
164 * This cannot be used if you need to differentiate between a key that doesn't exist vs a key with a NULL value.
165 *
166 * \param[in] h Hashtable being referenced.
167 * \param[in] key Key for value to retrieve from the hashtable.
168 * A NULL or empty string is explicitly disallowed.
169 *
170 * \return NULL if key doesn't exist or NULL value on file, otherwise the value.
171 */
172M_API void *M_hash_strvp_get_direct(const M_hash_strvp_t *h, const char *key);
173
174
175/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
176
177/*! Wether the hashtable a multi value table.
178 *
179 * \param[in] h Hashtable being referenced.
180 *
181 * \return M_TRUE if a multi value hashtable.
182 */
184
185
186/*! Get the number of values for a given key.
187 *
188 * \param[in] h Hashtable being referenced.
189 * \param[in] key Key for value to retrieve.
190 * \param[out] len The number of values.
191 *
192 * \return M_TRUE if length is retrieved, M_FALSE if key does not exist.
193 */
194M_API M_bool M_hash_strvp_multi_len(const M_hash_strvp_t *h, const char *key, size_t *len);
195
196
197/*! Retrieve the value for a key from the given index when supporting muli-values.
198 *
199 * \param[in] h Hashtable being referenced.
200 * \param[in] key Key for value to retrieve.
201 * \param[in] idx The index the value resides at.
202 * \param[out] value Pointer to value stored. Optional, pass NULL if not needed.
203 *
204 * \return M_TRUE if value retrieved, M_FALSE if key does not exist
205 */
206M_API M_bool M_hash_strvp_multi_get(const M_hash_strvp_t *h, const char *key, size_t idx, void **value);
207
208
209/*! Retrieve the value for a key from the given index when supporting muli-values.
210 *
211 * \param[in] h Hashtable being referenced.
212 * \param[in] key Key for value to retrieve.
213 * \param[in] idx The index the value resides at.
214 *
215 * \return M_TRUE if value retrieved, M_FALSE if key does not exist.
216 */
217M_API void *M_hash_strvp_multi_get_direct(const M_hash_strvp_t *h, const char *key, size_t idx);
218
219
220/*! Remove a value from the hashtable when supporting muli-values.
221 *
222 * If all values have been removed then the key will be removed.
223 *
224 * \param[in,out] h Hashtable being referenced
225 * \param[in] key Key for value to retrieve.
226 * \param[in] idx The index the value resides at.
227 * \param[in] destroy_vals M_TRUE if the value held by the hashtable should be destroyed.
228 * This will almost always be M_TRUE. This should only be set to M_FALSE
229 * when the value held by the hashtable is being managed externally.
230 *
231 * \return M_TRUE if the value was removed, M_FALSE if key does not exist.
232 */
233M_API M_bool M_hash_strvp_multi_remove(M_hash_strvp_t *h, const char *key, size_t idx, M_bool destroy_vals);
234
235
236/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
237
238/*! Retrieve the current size (number of buckets/slots, not necessarily used).
239 *
240 * \param[in] h Hashtable being referenced.
241 *
242 * \return Size of the hashtable
243 */
244M_API M_uint32 M_hash_strvp_size(const M_hash_strvp_t *h);
245
246
247/*! Retrieve the number of collisions for hashtable entries that has occurred since creation.
248 *
249 * \param[in] h Hashtable being referenced.
250 *
251 * \return Number of collisions.
252 */
254
255
256/*! Retrieve the number of expansions/rehashes since creation.
257 *
258 * \param[in] h Hashtable being referenced.
259 *
260 * \return number of expansions/rehashes.
261 */
263
264
265/*! Retrieve the number of entries in the hashtable.
266 *
267 * This is the number of keys stored.
268 *
269 * \param[in] h Hashtable being referenced.
270 *
271 * \return number of entries in the hashtable.
272 */
274
275
276/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
277
278/*! Start an enumeration of the keys within a hashtable.
279 *
280 * \param[in] h Hashtable being referenced.
281 * \param[out] hashenum Outputs an initialized state variable for starting an enumeration.
282 *
283 * \return Number of items in the hashtable
284 *
285 * \see M_hash_strvp_enumerate_free
286 */
288
289
290/*! Retrieve the next item from a hashtable enumeration.
291 *
292 * If multi-value, keys will appear multiple times as each value will be
293 * retrieved individually.
294 *
295 * \param[in] h Hashtable being referenced.
296 * \param[in,out] hashenum State variable for tracking the enumeration process.
297 * \param[out] key Value of next enumerated key. Optional, pass NULL if not needed.
298 * \param[out] value Value of next enumerated value. Optional, pass NULL if not needed.
299 *
300 * \return M_TRUE if enumeration succeeded, M_FALSE if no more keys.
301 */
302M_API M_bool M_hash_strvp_enumerate_next(const M_hash_strvp_t *h, M_hash_strvp_enum_t *hashenum, const char **key, void **value);
303
304
305/*! Destroy an enumeration state.
306 *
307 * \param[in] hashenum Enumeration to destroy.
308 */
310
311
312/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
313
314/*! Merge two hashtables together.
315 *
316 * The second (src) hashtable will be destroyed automatically upon completion of this function. Any key/value
317 * pointers for the hashtable will be directly copied over to the destination hashtable, they will not be
318 * duplicated. Any keys which exist in 'dest' that also exist in 'src' will be overwritten by the 'src' value.
319 *
320 * If dest and src are multi-value, all values from src will be copied into dest and the values from
321 * dest will not be removed. If dest is not multi-value and src is, then only the last value in src will
322 * be present in dest. If dest is multi-value and src is not, then the value from src will be added to dest.
323 *
324 * \param[in,out] dest Pointer by reference to the hashtable receiving the key/value pairs.
325 * if dest is NULL, the src address will simply be copied to dest.
326 * \param[in,out] src Pointer to the hashtable giving up its key/value pairs.
327 */
328M_API void M_hash_strvp_merge(M_hash_strvp_t **dest, M_hash_strvp_t *src) M_FREE(2);
329
330/*! @} */
331
332__END_DECLS
333
334#endif /* __M_HASH_STRVP_H__ */
size_t M_hash_strvp_num_expansions(const M_hash_strvp_t *h)
void M_hash_strvp_enumerate_free(M_hash_strvp_enum_t *hashenum)
void M_hash_strvp_merge(M_hash_strvp_t **dest, M_hash_strvp_t *src) M_FREE(2)
M_hash_strvp_t * M_hash_strvp_create(size_t size, M_uint8 fillpct, M_uint32 flags, void(*destroy_func)(void *)) M_MALLOC_ALIASED
void * M_hash_strvp_multi_get_direct(const M_hash_strvp_t *h, const char *key, size_t idx)
void M_hash_strvp_destroy(M_hash_strvp_t *h, M_bool destroy_vals) M_FREE(1)
M_uint32 M_hash_strvp_size(const M_hash_strvp_t *h)
M_bool M_hash_strvp_multi_get(const M_hash_strvp_t *h, const char *key, size_t idx, void **value)
M_bool M_hash_strvp_remove(M_hash_strvp_t *h, const char *key, M_bool destroy_vals)
M_bool M_hash_strvp_get(const M_hash_strvp_t *h, const char *key, void **value)
void * M_hash_strvp_get_direct(const M_hash_strvp_t *h, const char *key)
M_bool M_hash_strvp_insert(M_hash_strvp_t *h, const char *key, void *value)
size_t M_hash_strvp_enumerate(const M_hash_strvp_t *h, M_hash_strvp_enum_t **hashenum)
struct M_hash_strvp_enum M_hash_strvp_enum_t
Definition: m_hash_strvp.h:57
M_bool M_hash_strvp_multi_len(const M_hash_strvp_t *h, const char *key, size_t *len)
M_bool M_hash_strvp_multi_remove(M_hash_strvp_t *h, const char *key, size_t idx, M_bool destroy_vals)
size_t M_hash_strvp_num_keys(const M_hash_strvp_t *h)
struct M_hash_strvp M_hash_strvp_t
Definition: m_hash_strvp.h:53
M_bool M_hash_strvp_enumerate_next(const M_hash_strvp_t *h, M_hash_strvp_enum_t *hashenum, const char **key, void **value)
M_bool M_hash_strvp_is_multi(const M_hash_strvp_t *h)
M_hash_strvp_flags_t
Definition: m_hash_strvp.h:61
size_t M_hash_strvp_num_collisions(const M_hash_strvp_t *h)
@ M_HASH_STRVP_CASECMP
Definition: m_hash_strvp.h:63
@ M_HASH_STRVP_MULTI_GETLAST
Definition: m_hash_strvp.h:74
@ M_HASH_STRVP_KEYS_LOWER
Definition: m_hash_strvp.h:66
@ M_HASH_STRVP_NONE
Definition: m_hash_strvp.h:62
@ M_HASH_STRVP_KEYS_SORTDESC
Definition: m_hash_strvp.h:71
@ M_HASH_STRVP_KEYS_UPPER
Definition: m_hash_strvp.h:64
@ M_HASH_STRVP_MULTI_VALUE
Definition: m_hash_strvp.h:72
@ M_HASH_STRVP_KEYS_ORDERED
Definition: m_hash_strvp.h:68
@ M_HASH_STRVP_STATIC_SEED
Definition: m_hash_strvp.h:76
@ M_HASH_STRVP_KEYS_SORTASC
Definition: m_hash_strvp.h:70