Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_hash.h
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#ifndef NILOREA_HASH_HEADER_GUARD
29#define NILOREA_HASH_HEADER_GUARD
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
40#if defined(__linux__) || defined(_AIX) || defined(__sun)
41#include <arpa/inet.h>
42#include <string.h>
43#else
44#include <string.h>
45#endif
46
47#include <stdint.h>
48
49#include "n_common.h"
50#include "n_list.h"
51
52// #if defined(_MSC_VER)
53// #include <stdlib.h>
55// #define ROTL32(x,y) _rotl(x,y)
57// #define ROTL64(x,y) _rotl64(x,y)
59// #define BIG_CONSTANT(x) (x)
60// #else
62// #define ROTL32(x,y) rotl32(x,y)
64// #define ROTL64(x,y) rotl64(x,y)
66// #define BIG_CONSTANT(x) (x##LLU)
67// #endif /* if defined MSVC ... */
68
70#define HASH_INT 1
72#define HASH_DOUBLE 2
74#define HASH_STRING 4
76#define HASH_PTR 8
78#define HASH_UNKNOWN 16
80#define HASH_CLASSIC 128
82#define HASH_TRIE 256
83
84#ifdef ENV_32BITS
86#define MurmurHash(__key, __len, __seed, __out) MurmurHash3_x86_128(__key, __len, __seed, __out)
88#define HASH_INT_TYPE int32_t
89#else
91#define MurmurHash(__key, __len, __seed, __out) MurmurHash3_x64_128(__key, __len, __seed, __out)
93#define HASH_INT_TYPE int64_t
94#endif
95
97typedef size_t HASH_VALUE;
98
104 double fval;
106 void* ptr;
108 char* string;
109};
110
112typedef struct HASH_NODE {
114 char* key;
116 char key_id;
120 int type;
124 void (*destroy_func)(void* ptr);
126 void* (*duplicate_func)(void* ptr);
135} HASH_NODE;
136
138typedef struct HASH_TABLE {
140 size_t size;
142 size_t nb_keys;
144 size_t seed;
154 unsigned int mode;
156 HASH_NODE* (*ht_get_node)(struct HASH_TABLE* table, const char* key);
158 int (*ht_put_int)(struct HASH_TABLE* table, const char* key, HASH_INT_TYPE val);
160 int (*ht_put_double)(struct HASH_TABLE* table, const char* key, double val);
162 int (*ht_put_ptr)(struct HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
164 int (*ht_put_string)(struct HASH_TABLE* table, const char* key, char* val);
166 int (*ht_put_string_ptr)(struct HASH_TABLE* table, const char* key, char* val);
168 int (*ht_get_int)(struct HASH_TABLE* table, const char* key, HASH_INT_TYPE* val);
170 int (*ht_get_double)(struct HASH_TABLE* table, const char* key, double* val);
172 int (*ht_get_ptr)(struct HASH_TABLE* table, const char* key, void** val);
174 int (*ht_get_string)(struct HASH_TABLE* table, const char* key, char** val);
176 int (*ht_remove)(struct HASH_TABLE* table, const char* key);
178 LIST* (*ht_search)(struct HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node));
180 int (*empty_ht)(struct HASH_TABLE* table);
182 int (*destroy_ht)(struct HASH_TABLE** table);
184 void (*ht_print)(struct HASH_TABLE* table);
185} HASH_TABLE;
186
188#define hash_val(node, type) \
189 ((node && node->ptr) ? ((type*)(((HASH_NODE*)node->ptr)->data.ptr)) : NULL)
190
192#define ht_foreach(__ITEM_, __HASH_) \
193 if (!__HASH_) { \
194 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
195 } else if (__HASH_->mode != HASH_CLASSIC) { \
196 n_log(LOG_ERR, "Error in ht_foreach( %s , %s ) unsupportted mode %d", #__ITEM_, #__HASH_, __HASH_->mode); \
197 } else \
198 for (size_t __hash_it = 0; __hash_it < __HASH_->size; __hash_it++) \
199 for (LIST_NODE* __ITEM_ = __HASH_->hash_table[__hash_it]->start; __ITEM_ != NULL; __ITEM_ = __ITEM_->next)
200
202#define ht_foreach_r(__ITEM_, __HASH_, __ITERATOR_) \
203 if (!__HASH_) { \
204 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
205 } else if (__HASH_->mode != HASH_CLASSIC) { \
206 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
207 } else \
208 for (size_t __ITERATOR_ = 0; __ITERATOR_ < __HASH_->size; __ITERATOR_++) \
209 for (LIST_NODE* __ITEM_ = __HASH_->hash_table[__ITERATOR_]->start; __ITEM_ != NULL; __ITEM_ = __ITEM_->next)
210
212#define HASH_VAL(node, type) \
213 ((node && node->data.ptr) ? ((type*)node->data.ptr) : NULL)
214
216#define HT_FOREACH(__ITEM_, __HASH_, ...) \
217 { \
218 do { \
219 if (!__HASH_) { \
220 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
221 } else { \
222 if (__HASH_->mode == HASH_CLASSIC) { \
223 int CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
224 for (size_t __hash_it = 0; __hash_it < __HASH_->size; __hash_it++) { \
225 for (LIST_NODE* __ht_list_node = __HASH_->hash_table[__hash_it]->start; __ht_list_node != NULL; __ht_list_node = __ht_list_node->next) { \
226 HASH_NODE* __ITEM_ = (HASH_NODE*)__ht_list_node->ptr; \
227 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 1; \
228 __VA_ARGS__ \
229 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
230 } \
231 if (CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) == 1) \
232 break; \
233 } \
234 } else if (__HASH_->mode == HASH_TRIE) { \
235 int CONCAT(__ht_node_trie_func_macro, __LINE__)(HASH_NODE * __ITEM_) { \
236 if (!__ITEM_) return TRUE; \
237 int CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 1; \
238 if (__ITEM_->is_leaf) { \
239 do { \
240 __VA_ARGS__ \
241 CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 0; \
242 } while (0); \
243 } \
244 if (CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) == 1) return FALSE; \
245 for (size_t CONCAT(__ht_node_trie_func_it, __LINE__) = 0; CONCAT(__ht_node_trie_func_it, __LINE__) < __ITEM_->alphabet_length; CONCAT(__ht_node_trie_func_it, __LINE__)++) { \
246 if (CONCAT(__ht_node_trie_func_macro, __LINE__)(__ITEM_->children[CONCAT(__ht_node_trie_func_it, __LINE__)]) == FALSE) \
247 return FALSE; \
248 } \
249 return TRUE; \
250 } \
251 CONCAT(__ht_node_trie_func_macro, __LINE__) \
252 (__HASH_->root); \
253 } else { \
254 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
255 break; \
256 } \
257 } \
258 } while (0); \
259 }
260
262#define HT_FOREACH_R(__ITEM_, __HASH_, __ITERATOR, ...) \
263 { \
264 do { \
265 if (!__HASH_) { \
266 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
267 } else { \
268 if (__HASH_->mode == HASH_CLASSIC) { \
269 int CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
270 LIST_NODE* CONCAT(__ht_list_node_r, __LINE__) = NULL; \
271 for (size_t __ITERATOR = 0; __ITERATOR < __HASH_->size; __ITERATOR++) { \
272 for (CONCAT(__ht_list_node_r, __LINE__) = __HASH_->hash_table[__ITERATOR]->start; CONCAT(__ht_list_node_r, __LINE__) != NULL; CONCAT(__ht_list_node_r, __LINE__) = CONCAT(__ht_list_node_r, __LINE__)->next) { \
273 HASH_NODE* __ITEM_ = (HASH_NODE*)CONCAT(__ht_list_node_r, __LINE__)->ptr; \
274 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 1; \
275 __VA_ARGS__ \
276 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
277 } \
278 if (CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) == 1) \
279 break; \
280 } \
281 } else if (__HASH_->mode == HASH_TRIE) { \
282 int CONCAT(__ht_node_trie_func_macro, __LINE__)(HASH_NODE * __ITEM_) { \
283 if (!__ITEM_) return TRUE; \
284 int CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 1; \
285 if (__ITEM_->is_leaf) { \
286 do { \
287 __VA_ARGS__ \
288 CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 0; \
289 } while (0); \
290 } \
291 if (CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) == 1) return FALSE; \
292 for (size_t it = 0; it < __ITEM_->alphabet_length; it++) { \
293 if (CONCAT(__ht_node_trie_func_macro, __LINE__)(__ITEM_->children[it]) == FALSE) \
294 return FALSE; \
295 } \
296 return TRUE; \
297 } \
298 CONCAT(__ht_node_trie_func_macro, __LINE__) \
299 (__HASH_->root); \
300 } else { \
301 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
302 break; \
303 } \
304 } \
305 } while (0); \
306 }
307
309void MurmurHash3_x86_32(const void* key, const size_t len, const uint32_t seed, void* out);
310// void MurmurHash3_x86_128(const void* key, int len, uint32_t seed, void* out);
312void MurmurHash3_x86_128(const void* key, const size_t len, const uint32_t seed, void* out);
314void MurmurHash3_x64_128(const void* key, const size_t len, const uint64_t seed, void* out);
315
317char* ht_node_type(const HASH_NODE* node);
319HASH_NODE* ht_get_node(HASH_TABLE* table, const char* key);
320
322HASH_TABLE* new_ht(size_t size);
324HASH_TABLE* new_ht_trie(size_t alphabet_size, size_t alphabet_offset);
325
327int ht_get_double(HASH_TABLE* table, const char* key, double* val);
329int ht_get_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE* val);
331int ht_get_ptr(HASH_TABLE* table, const char* key, void** val);
333int ht_get_string(HASH_TABLE* table, const char* key, char** val);
335int ht_put_double(HASH_TABLE* table, const char* key, double value);
337int ht_put_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE value);
339int ht_put_ptr(HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
341int ht_put_string(HASH_TABLE* table, const char* key, char* string);
343int ht_put_string_ptr(HASH_TABLE* table, const char* key, char* string);
345int ht_remove(HASH_TABLE* table, const char* key);
347void ht_print(HASH_TABLE* table);
349LIST* ht_search(HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node));
351int empty_ht(HASH_TABLE* table);
353int destroy_ht(HASH_TABLE** table);
354
356HASH_NODE* ht_get_node_ex(HASH_TABLE* table, HASH_VALUE hash_value);
358int ht_put_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void* val, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
360int ht_get_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void** val);
362int ht_remove_ex(HASH_TABLE* table, HASH_VALUE hash_value);
363
365LIST* ht_get_completion_list(HASH_TABLE* table, const char* keybud, size_t max_results);
366
368int is_prime(size_t nb);
370size_t next_prime(size_t nb);
371
375size_t ht_get_optimal_size(HASH_TABLE* table);
377int ht_resize(HASH_TABLE** table, size_t size);
379int ht_optimize(HASH_TABLE** table);
382
387#ifdef __cplusplus
388}
389#endif
390
391#endif // header guard
static size_t max_results
char * key
int(* ht_put_int)(struct HASH_TABLE *table, const char *key, int64_t val)
put an integer
Definition n_hash.h:158
size_t alphabet_length
HASH_TRIE mode: size of alphabet and so size of children allocated array.
Definition n_hash.h:134
int need_rehash
flag to mark a node for rehash
Definition n_hash.h:130
char key_id
key id of the node if any
Definition n_hash.h:116
int(* ht_get_string)(struct HASH_TABLE *table, const char *key, char **val)
get a char *string from a key's node
Definition n_hash.h:174
int(* ht_put_string)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string
Definition n_hash.h:164
char * key
string key of the node if any, else NULL
Definition n_hash.h:114
int64_t ival
integral type
Definition n_hash.h:102
int(* ht_put_ptr)(struct HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr), void *(*duplicator)(void *ptr))
put a a pointer
Definition n_hash.h:162
int is_leaf
HASH_TRIE mode: does it have a value.
Definition n_hash.h:128
HASH_NODE * root
HASH_TRIE mode: Start of tree.
Definition n_hash.h:148
void * ptr
pointer type
Definition n_hash.h:106
union HASH_DATA data
data inside the node
Definition n_hash.h:122
int(* ht_get_ptr)(struct HASH_TABLE *table, const char *key, void **val)
get a pointer from a key's node
Definition n_hash.h:172
int type
type of the node
Definition n_hash.h:120
int(* empty_ht)(struct HASH_TABLE *table)
empty a hash table.
Definition n_hash.h:180
LIST ** hash_table
HASH_CLASSIC mode: preallocated hash table.
Definition n_hash.h:146
size_t alphabet_offset
HASH_TRIE mode: offset to deduce to individual key digits.
Definition n_hash.h:152
int(* ht_get_double)(struct HASH_TABLE *table, const char *key, double *val)
get a double from a key's node
Definition n_hash.h:170
size_t alphabet_length
HASH_TRIE mode: size of the alphabet.
Definition n_hash.h:150
unsigned int mode
hashing mode, murmurhash and classic HASH_MURMUR, or HASH_TRIE
Definition n_hash.h:154
size_t seed
table's seed
Definition n_hash.h:144
int(* destroy_ht)(struct HASH_TABLE **table)
destroy a hash table
Definition n_hash.h:182
int(* ht_put_string_ptr)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string pointer
Definition n_hash.h:166
int(* ht_remove)(struct HASH_TABLE *table, const char *key)
remove given's key node from the table
Definition n_hash.h:176
void(* ht_print)(struct HASH_TABLE *table)
print table
Definition n_hash.h:184
char * string
char *type
Definition n_hash.h:108
int(* ht_put_double)(struct HASH_TABLE *table, const char *key, double val)
put a double
Definition n_hash.h:160
struct HASH_NODE ** children
HASH_TRIE mode: pointers to children.
Definition n_hash.h:132
HASH_VALUE hash_value
numeric key of the node if any, else < 0
Definition n_hash.h:118
double fval
double type
Definition n_hash.h:104
size_t size
size of the hash table
Definition n_hash.h:140
int(* ht_get_int)(struct HASH_TABLE *table, const char *key, int64_t *val)
get an int from a key's node
Definition n_hash.h:168
size_t nb_keys
total number of used keys in the table
Definition n_hash.h:142
void(* destroy_func)(void *ptr)
destroy_func
Definition n_hash.h:124
int ht_get_ptr(HASH_TABLE *table, const char *key, void **val)
get a pointer value from the hash table by key
Definition n_hash.c:2110
LIST * ht_search(HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
search the hash table for nodes matching a predicate
Definition n_hash.c:2224
HASH_TABLE * ht_duplicate(HASH_TABLE *table)
duplicate a hash table
Definition n_hash.c:2652
int destroy_ht(HASH_TABLE **table)
destroy a hash table and free all resources
Definition n_hash.c:2244
int ht_put_ptr_ex(HASH_TABLE *table, HASH_VALUE hash_value, void *val, void(*destructor)(void *ptr), void *(*duplicator)(void *ptr))
put a pointer value by numeric hash value
Definition n_hash.c:2307
int ht_remove(HASH_TABLE *table, const char *key)
remove a node from the hash table by key
Definition n_hash.c:2202
HASH_NODE * ht_get_node_ex(HASH_TABLE *table, HASH_VALUE hash_value)
get a HASH_NODE by numeric hash value
Definition n_hash.c:2255
HASH_TABLE * new_ht(size_t size)
create a new classic hash table of the given size
Definition n_hash.c:2011
int ht_get_table_collision_percentage(HASH_TABLE *table)
get the collision percentage of the hash table
Definition n_hash.c:2487
int ht_get_double(HASH_TABLE *table, const char *key, double *val)
get a double value from the hash table by key
Definition n_hash.c:2084
int empty_ht(HASH_TABLE *table)
empty a hash table, freeing all nodes
Definition n_hash.c:2234
void ht_print(HASH_TABLE *table)
print the contents of a hash table
Definition n_hash.c:2212
LIST * ht_get_completion_list(HASH_TABLE *table, const char *keybud, size_t max_results)
get a list of key completions matching the given prefix
Definition n_hash.c:2401
size_t HASH_VALUE
type of a HASH_VALUE
Definition n_hash.h:97
int ht_put_double(HASH_TABLE *table, const char *key, double value)
put a double value into the hash table
Definition n_hash.c:2136
size_t ht_get_optimal_size(HASH_TABLE *table)
compute the optimal size for the hash table
Definition n_hash.c:2511
int ht_put_ptr(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr), void *(*duplicator)(void *ptr))
put a pointer value into the hash table with destructor and duplicator
Definition n_hash.c:2164
int ht_get_string(HASH_TABLE *table, const char *key, char **val)
get a string value from the hash table by key
Definition n_hash.c:2123
int is_prime(size_t nb)
check if a number is prime
Definition n_hash.c:2448
#define HASH_INT_TYPE
type of a HASH_INT in 64 bits
Definition n_hash.h:93
size_t next_prime(size_t nb)
return the next prime number greater than or equal to nb
Definition n_hash.c:2470
int ht_put_string(HASH_TABLE *table, const char *key, char *string)
put a string value (duplicated) into the hash table
Definition n_hash.c:2177
int ht_resize(HASH_TABLE **table, size_t size)
resize a hash table to the given size
Definition n_hash.c:2530
void MurmurHash3_x86_128(const void *key, const size_t len, const uint32_t seed, void *out)
compute a 128-bit MurmurHash3 hash for x86
Definition n_hash.c:1036
void MurmurHash3_x64_128(const void *key, const size_t len, const uint64_t seed, void *out)
compute a 128-bit MurmurHash3 hash for x64
Definition n_hash.c:1204
int ht_remove_ex(HASH_TABLE *table, HASH_VALUE hash_value)
remove a node by numeric hash value
Definition n_hash.c:2360
int ht_get_int(HASH_TABLE *table, const char *key, int64_t *val)
get an integer value from the hash table by key
Definition n_hash.c:2097
HASH_NODE * ht_get_node(HASH_TABLE *table, const char *key)
get the HASH_NODE associated with the given key
Definition n_hash.c:2071
HASH_TABLE * new_ht_trie(size_t alphabet_size, size_t alphabet_offset)
create a new trie hash table with the given alphabet size and offset
Definition n_hash.c:1965
int ht_put_int(HASH_TABLE *table, const char *key, int64_t value)
put an integer value into the hash table
Definition n_hash.c:2149
int ht_optimize(HASH_TABLE **table)
optimize a hash table by resizing to the optimal size
Definition n_hash.c:2618
char * ht_node_type(const HASH_NODE *node)
return the type of a hash node as a string
Definition n_hash.c:1326
void MurmurHash3_x86_32(const void *key, const size_t len, const uint32_t seed, void *out)
compute a 32-bit MurmurHash3 hash
Definition n_hash.c:978
int ht_put_string_ptr(HASH_TABLE *table, const char *key, char *string)
put a string pointer into the hash table without copying
Definition n_hash.c:2190
int ht_get_ptr_ex(HASH_TABLE *table, HASH_VALUE hash_value, void **val)
get a pointer value by numeric hash value
Definition n_hash.c:2280
structure of a hash table node
Definition n_hash.h:112
structure of a hash table
Definition n_hash.h:138
union of the possibles data values of a node
Definition n_hash.h:100
Structure of a generic LIST container.
Definition n_list.h:59
Common headers and low-level functions & define.
List structures and definitions.