Mstdlib-1.24.0
m_hash_stridx.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_STRIDX_H__
25#define __M_HASH_STRIDX_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_stridx Hashtable - String/Index
37 * \ingroup m_hashtable
38 *
39 * Hashtable, meant for storing string keys and index values.
40 * This is primarily used for something like dereferencing a CSV column name to its position.
41 *
42 * References to the data will always be read-only.
43 * All keys and values will be duplicated by the hashtable.
44 *
45 * @{
46 */
47
48struct M_hash_stridx;
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 */
52typedef struct M_hash_stridx M_hash_stridx_t;
53
54struct M_hash_stridx_enum;
55/* Used for enumerating a M_hash_stridx. */
56typedef struct M_hash_stridx_enum M_hash_stridx_enum_t;
57
58
59/*! Flags for controlling the behavior of the hashtable. */
60typedef enum {
61 M_HASH_STRIDX_NONE = 0, /*!< Case sensitive single value (new values replace). */
62 M_HASH_STRIDX_CASECMP = 1 << 0, /*!< Key compare is case insensitive. */
63 M_HASH_STRIDX_KEYS_UPPER = 1 << 1, /*!< Keys will be upper cased before being inserted. Should be used
64 in conjunction with M_HASH_STRIDX_CASECMP. */
65 M_HASH_STRIDX_KEYS_LOWER = 1 << 2, /*!< Keys will be lower cased before being inserted. Should be used
66 in conjunction with M_HASH_STRIDX_CASECMP. */
67 M_HASH_STRIDX_KEYS_ORDERED = 1 << 3, /*!< Keys should be ordered. Default is insertion order unless the
68 sorted option is specified. */
69 M_HASH_STRIDX_KEYS_SORTASC = 1 << 4, /*!< When the keys are ordered sort them using the key_equality function. */
70 M_HASH_STRIDX_KEYS_SORTDESC = 1 << 5, /*!< When the keys are ordered sort them using the key_equality function. */
71 M_HASH_STRIDX_MULTI_VALUE = 1 << 6, /*!< Allow keys to contain multiple values.
72 Sorted in insertion order another sorting is specified. */
73 M_HASH_STRIDX_MULTI_GETLAST = 1 << 7, /*!< When using get and get_direct function get the last value from the list
74 when allowing multiple values. The default is to get the first value. */
75 M_HASH_STRIDX_STATIC_SEED = 1 << 8 /*!< Use a static seed for hash function initialization. This greatly reduces
76 the security of the hashtable and removes collision attack protections.
77 This should only be used as a performance optimization when creating
78 millions of hashtables with static data specifically for quick look up.
79 DO _NOT_ use this flag with any hashtable that could store user
80 generated data! Be very careful about duplicating a hashtable that
81 was created with this flag. All duplicates will use the static seed. */
83
84
85/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
86
87/*! Create a new hashtable.
88 *
89 * The hashtable will pre-allocate an array of buckets based on the rounded up size specified. Any hash collisions
90 * will result in those collisions being chained together via a linked list. The hashtable will auto-expand by a
91 * power of 2 when the fill percentage specified is reached. All key entries are compared in a case-insensitive
92 * fashion, and are duplicated internally. Values are duplicated. Case is preserved for both keys and values.
93 *
94 * \param[in] size Size of the hash table. If not specified as a power of 2, will
95 * be rounded up to the nearest power of 2.
96 * \param[in] fillpct The maximum fill percentage before the hash table is expanded. If
97 * 0 is specified, the hashtable will never expand, otherwise the
98 * value must be between 1 and 99 (recommended: 75).
99 * \param[in] flags M_hash_stridx_flags_t flags for modifying behavior.
100 *
101 * \return Allocated hashtable.
102 *
103 * \see M_hash_stridx_destroy
104 */
105M_API M_hash_stridx_t *M_hash_stridx_create(size_t size, M_uint8 fillpct, M_uint32 flags) M_MALLOC;
106
107
108/*! Destroy the hashtable.
109 *
110 * \param[in] h Hashtable to destroy
111 */
112M_API void M_hash_stridx_destroy(M_hash_stridx_t *h) M_FREE(1);
113
114
115/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
116
117/*! Insert an entry into the hashtable.
118 *
119 * \param[in,out] h Hashtable being referenced.
120 * \param[in] key Key to insert.
121 * A NULL or empty string is explicity disallowed.
122 * \param[in] value Value to insert into hashtable.
123 *
124 * \return M_TRUE on success, or M_FALSE on failure.
125 */
126M_API M_bool M_hash_stridx_insert(M_hash_stridx_t *h, const char *key, size_t value);
127
128
129/*! Remove an entry from the hashtable.
130 *
131 * \param[in,out] h Hashtable being referenced.
132 * \param[in] key Key to remove from the hashtable.
133 * A NULL or empty string is explicitly disallowed.
134 *
135 * \return M_TRUE on success, or M_FALSE if key does not exist.
136 */
137M_API M_bool M_hash_stridx_remove(M_hash_stridx_t *h, const char *key);
138
139
140/*! Retrieve the value for a key from the hashtable.
141 *
142 * \param[in] h Hashtable being referenced.
143 * \param[in] key Key for value.
144 * A NULL or empty string is explicitly disallowed.
145 * \param[out] value Pointer to value stored in the hashtable. Optional, pass NULL if not needed.
146 *
147 * \return M_TRUE if value retrieved, M_FALSE if key does not exist.
148 */
149M_API M_bool M_hash_stridx_get(const M_hash_stridx_t *h, const char *key, size_t *value);
150
151
152/*! Retrieve the value for a key from the hashtable, and return it directly as the return value.
153 *
154 * This cannot be used if you need to differentiate between a key that doesn't exist vs a key with a 0 value.
155 *
156 * \param[in] h Hashtable being referenced.
157 * \param[in] key Key for value to retrieve from the hashtable.
158 * A NULL or empty string is explicitly disallowed.
159 *
160 * \return NULL if key doesn't exist or NULL value on file, otherwise the value.
161 */
162M_API size_t M_hash_stridx_get_direct(const M_hash_stridx_t *h, const char *key);
163
164
165/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
166
167/*! Wether the hashtable a multi value table.
168 *
169 * \param[in] h Hashtable being referenced.
170 *
171 * \return M_TRUE if a multi value hashtable.
172 */
174
175
176/*! Get the number of values for a given key.
177 *
178 * \param[in] h Hashtable being referenced.
179 * \param[in] key Key for value to retrieve.
180 * \param[out] len The number of values.
181 *
182 * \return M_TRUE if length is retrieved, M_FALSE if key does not exist.
183 */
184M_API M_bool M_hash_stridx_multi_len(const M_hash_stridx_t *h, const char *key, size_t *len);
185
186
187/*! Retrieve the value for a key from the given index when supporting muli-values.
188 *
189 * \param[in] h Hashtable being referenced.
190 * \param[in] key Key for value to retrieve.
191 * \param[in] idx The index the value resides at.
192 * \param[out] value Pointer to value stored. Optional, pass NULL if not needed.
193 *
194 * \return M_TRUE if value retrieved, M_FALSE if key does not exist
195 */
196M_API M_bool M_hash_stridx_multi_get(const M_hash_stridx_t *h, const char *key, size_t idx, size_t *value);
197
198
199/*! Retrieve the value for a key from the given index when supporting muli-values.
200 *
201 * \param[in] h Hashtable being referenced.
202 * \param[in] key Key for value to retrieve.
203 * \param[in] idx The index the value resides at.
204 *
205 * \return M_TRUE if value retrieved, M_FALSE if key does not exist.
206 */
207M_API size_t M_hash_stridx_multi_get_direct(const M_hash_stridx_t *h, const char *key, size_t idx);
208
209
210/*! Remove a value from the hashtable when supporting muli-values.
211 *
212 * If all values have been removed then the key will be removed.
213 *
214 * \param[in,out] h Hashtable being referenced
215 * \param[in] key Key for value to retrieve.
216 * \param[in] idx The index the value resides at.
217 *
218 * \return M_TRUE if the value was removed, M_FALSE if key does not exist.
219 */
220M_API M_bool M_hash_stridx_multi_remove(M_hash_stridx_t *h, const char *key, size_t idx);
221
222
223/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
224
225/*! Retrieve the current size (number of buckets/slots, not necessarily used).
226 *
227 * \param[in] h Hashtable being referenced.
228 *
229 * \return Size of the hashtable
230 */
231M_API M_uint32 M_hash_stridx_size(const M_hash_stridx_t *h);
232
233
234/*! Retrieve the number of collisions for hashtable entries that has occurred since creation.
235 *
236 * \param[in] h Hashtable being referenced.
237 *
238 * \return Number of collisions.
239 */
241
242
243/*! Retrieve the number of expansions/rehashes since creation.
244 *
245 * \param[in] h Hashtable being referenced.
246 *
247 * \return number of expansions/rehashes.
248 */
250
251
252/*! Retrieve the number of entries in the hashtable.
253 *
254 * This is the number of keys stored.
255 *
256 * \param[in] h Hashtable being referenced.
257 *
258 * \return number of entries in the hashtable.
259 */
261
262
263/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
264
265/*! Start an enumeration of the keys within a hashtable.
266 *
267 * \param[in] h Hashtable being referenced.
268 * \param[out] hashenum Outputs an initialized state variable for starting an enumeration.
269 *
270 * \return Number of items in the hashtable
271 *
272 * \see M_hash_stridx_enumerate_free
273 */
275
276
277/*! Retrieve the next item from a hashtable enumeration.
278 *
279 * If multi-value, keys will appear multiple times as each value will be
280 * retrieved individually.
281 *
282 * \param[in] h Hashtable being referenced.
283 * \param[in,out] hashenum State variable for tracking the enumeration process.
284 * \param[out] key Value of next enumerated key. Optional, pass NULL if not needed.
285 * \param[out] value Value of next enumerated value. Optional, pass NULL if not needed.
286 *
287 * \return M_TRUE if enumeration succeeded, M_FALSE if no more keys.
288 */
289M_API M_bool M_hash_stridx_enumerate_next(const M_hash_stridx_t *h, M_hash_stridx_enum_t *hashenum, const char **key, size_t *value);
290
291
292/*! Destroy an enumeration state.
293 *
294 * \param[in] hashenum Enumeration to destroy.
295 */
297
298
299/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
300
301/*! Merge two hashtables together.
302 *
303 * The second (src) hashtable will be destroyed automatically upon completion of this function. Any key/value
304 * pointers for the hashtable will be directly copied over to the destination hashtable, they will not be
305 * duplicated. Any keys which exist in 'dest' that also exist in 'src' will be overwritten by the 'src' value.
306 *
307 * If dest and src are multi-value, all values from src will be copied into dest and the values from
308 * dest will not be removed. If dest is not multi-value and src is, then only the last value in src will
309 * be present in dest. If dest is multi-value and src is not, then the value from src will be added to dest.
310 *
311 * \param[in,out] dest Pointer by reference to the hashtable receiving the key/value pairs.
312 * if dest is NULL, the src address will simply be copied to dest.
313 * \param[in,out] src Pointer to the hashtable giving up its key/value pairs.
314 */
315M_API void M_hash_stridx_merge(M_hash_stridx_t **dest, M_hash_stridx_t *src) M_FREE(2);
316
317/*! Duplicate an existing hashtable.
318 *
319 * Copying all keys and values.
320 *
321 * \param[in] h Hashtable to be copied.
322 *
323 * \return Duplicated hashtable.
324 */
326
327/*! @} */
328
329__END_DECLS
330
331#endif /* __M_HASH_STRIDX_H__ */
size_t M_hash_stridx_num_collisions(const M_hash_stridx_t *h)
M_bool M_hash_stridx_remove(M_hash_stridx_t *h, const char *key)
M_bool M_hash_stridx_multi_get(const M_hash_stridx_t *h, const char *key, size_t idx, size_t *value)
struct M_hash_stridx M_hash_stridx_t
Definition: m_hash_stridx.h:52
size_t M_hash_stridx_multi_get_direct(const M_hash_stridx_t *h, const char *key, size_t idx)
void M_hash_stridx_merge(M_hash_stridx_t **dest, M_hash_stridx_t *src) M_FREE(2)
size_t M_hash_stridx_num_keys(const M_hash_stridx_t *h)
M_hash_stridx_flags_t
Definition: m_hash_stridx.h:60
void M_hash_stridx_enumerate_free(M_hash_stridx_enum_t *hashenum)
size_t M_hash_stridx_get_direct(const M_hash_stridx_t *h, const char *key)
M_uint32 M_hash_stridx_size(const M_hash_stridx_t *h)
size_t M_hash_stridx_enumerate(const M_hash_stridx_t *h, M_hash_stridx_enum_t **hashenum)
M_bool M_hash_stridx_enumerate_next(const M_hash_stridx_t *h, M_hash_stridx_enum_t *hashenum, const char **key, size_t *value)
M_bool M_hash_stridx_insert(M_hash_stridx_t *h, const char *key, size_t value)
M_hash_stridx_t * M_hash_stridx_duplicate(const M_hash_stridx_t *h) M_MALLOC
void M_hash_stridx_destroy(M_hash_stridx_t *h) M_FREE(1)
M_bool M_hash_stridx_multi_remove(M_hash_stridx_t *h, const char *key, size_t idx)
M_hash_stridx_t * M_hash_stridx_create(size_t size, M_uint8 fillpct, M_uint32 flags) M_MALLOC
size_t M_hash_stridx_num_expansions(const M_hash_stridx_t *h)
M_bool M_hash_stridx_multi_len(const M_hash_stridx_t *h, const char *key, size_t *len)
M_bool M_hash_stridx_get(const M_hash_stridx_t *h, const char *key, size_t *value)
M_bool M_hash_stridx_is_multi(const M_hash_stridx_t *h)
struct M_hash_stridx_enum M_hash_stridx_enum_t
Definition: m_hash_stridx.h:56
@ M_HASH_STRIDX_STATIC_SEED
Definition: m_hash_stridx.h:75
@ M_HASH_STRIDX_NONE
Definition: m_hash_stridx.h:61
@ M_HASH_STRIDX_KEYS_UPPER
Definition: m_hash_stridx.h:63
@ M_HASH_STRIDX_MULTI_GETLAST
Definition: m_hash_stridx.h:73
@ M_HASH_STRIDX_KEYS_SORTASC
Definition: m_hash_stridx.h:69
@ M_HASH_STRIDX_KEYS_SORTDESC
Definition: m_hash_stridx.h:70
@ M_HASH_STRIDX_KEYS_LOWER
Definition: m_hash_stridx.h:65
@ M_HASH_STRIDX_CASECMP
Definition: m_hash_stridx.h:62
@ M_HASH_STRIDX_MULTI_VALUE
Definition: m_hash_stridx.h:71
@ M_HASH_STRIDX_KEYS_ORDERED
Definition: m_hash_stridx.h:67