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 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#ifndef NILOREA_HASH_HEADER_GUARD
28#define NILOREA_HASH_HEADER_GUARD
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
39#if defined(__linux__) || defined(_AIX) || defined(__sun)
40#include <arpa/inet.h>
41#include <string.h>
42#else
43#include <string.h>
44#endif
45
46#include <stdint.h>
47
48#include "n_common.h"
49#include "n_list.h"
50
51// #if defined(_MSC_VER)
52// #include <stdlib.h>
54// #define ROTL32(x,y) _rotl(x,y)
56// #define ROTL64(x,y) _rotl64(x,y)
58// #define BIG_CONSTANT(x) (x)
59// #else
61// #define ROTL32(x,y) rotl32(x,y)
63// #define ROTL64(x,y) rotl64(x,y)
65// #define BIG_CONSTANT(x) (x##LLU)
66// #endif /* if defined MSVC ... */
67
69#define HASH_INT 1
71#define HASH_DOUBLE 2
73#define HASH_STRING 4
75#define HASH_PTR 8
77#define HASH_UNKNOWN 16
79#define HASH_CLASSIC 128
81#define HASH_TRIE 256
82
83#ifdef ENV_32BITS
85#define MurmurHash(__key, __len, __seed, __out) MurmurHash3_x86_128(__key, __len, __seed, __out)
87#define HASH_INT_TYPE int32_t
88#else
90#define MurmurHash(__key, __len, __seed, __out) MurmurHash3_x64_128(__key, __len, __seed, __out)
92#define HASH_INT_TYPE int64_t
93#endif
94
96typedef size_t HASH_VALUE;
97
99union HASH_DATA {
103 double fval;
105 void* ptr;
107 char* string;
108};
109
111typedef struct HASH_NODE {
113 char* key;
115 char key_id;
119 int type;
123 void (*destroy_func)(void* ptr);
125 void* (*duplicate_func)(void* ptr);
134} HASH_NODE;
135
137typedef struct HASH_TABLE {
139 size_t size;
141 size_t nb_keys;
143 size_t seed;
153 unsigned int mode;
155 HASH_NODE* (*ht_get_node)(struct HASH_TABLE* table, const char* key);
157 int (*ht_put_int)(struct HASH_TABLE* table, const char* key, HASH_INT_TYPE val);
159 int (*ht_put_double)(struct HASH_TABLE* table, const char* key, double val);
161 int (*ht_put_ptr)(struct HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
163 int (*ht_put_string)(struct HASH_TABLE* table, const char* key, char* val);
165 int (*ht_put_string_ptr)(struct HASH_TABLE* table, const char* key, char* val);
167 int (*ht_get_int)(struct HASH_TABLE* table, const char* key, HASH_INT_TYPE* val);
169 int (*ht_get_double)(struct HASH_TABLE* table, const char* key, double* val);
171 int (*ht_get_ptr)(struct HASH_TABLE* table, const char* key, void** val);
173 int (*ht_get_string)(struct HASH_TABLE* table, const char* key, char** val);
175 int (*ht_remove)(struct HASH_TABLE* table, const char* key);
177 LIST* (*ht_search)(struct HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node));
179 int (*empty_ht)(struct HASH_TABLE* table);
181 int (*destroy_ht)(struct HASH_TABLE** table);
183 void (*ht_print)(struct HASH_TABLE* table);
184} HASH_TABLE;
185
187#define hash_val(node, type) \
188 ((node && node->ptr) ? ((type*)(((HASH_NODE*)node->ptr)->data.ptr)) : NULL)
189
191#define ht_foreach(__ITEM_, __HASH_) \
192 if (!__HASH_) { \
193 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
194 } else if (__HASH_->mode != HASH_CLASSIC) { \
195 n_log(LOG_ERR, "Error in ht_foreach( %s , %s ) unsupportted mode %d", #__ITEM_, #__HASH_, __HASH_->mode); \
196 } else \
197 for (size_t __hash_it = 0; __hash_it < __HASH_->size; __hash_it++) \
198 for (LIST_NODE* __ITEM_ = __HASH_->hash_table[__hash_it]->start; __ITEM_ != NULL; __ITEM_ = __ITEM_->next)
199
201#define ht_foreach_r(__ITEM_, __HASH_, __ITERATOR_) \
202 if (!__HASH_) { \
203 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
204 } else if (__HASH_->mode != HASH_CLASSIC) { \
205 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
206 } else \
207 for (size_t __ITERATOR_ = 0; __ITERATOR_ < __HASH_->size; __ITERATOR_++) \
208 for (LIST_NODE* __ITEM_ = __HASH_->hash_table[__ITERATOR_]->start; __ITEM_ != NULL; __ITEM_ = __ITEM_->next)
209
211#define HASH_VAL(node, type) \
212 ((node && node->data.ptr) ? ((type*)node->data.ptr) : NULL)
213
215#define HT_FOREACH(__ITEM_, __HASH_, ...) \
216 { \
217 do { \
218 if (!__HASH_) { \
219 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
220 } else { \
221 if (__HASH_->mode == HASH_CLASSIC) { \
222 int CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
223 for (size_t __hash_it = 0; __hash_it < __HASH_->size; __hash_it++) { \
224 for (LIST_NODE* __ht_list_node = __HASH_->hash_table[__hash_it]->start; __ht_list_node != NULL; __ht_list_node = __ht_list_node->next) { \
225 HASH_NODE* __ITEM_ = (HASH_NODE*)__ht_list_node->ptr; \
226 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 1; \
227 __VA_ARGS__ \
228 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
229 } \
230 if (CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) == 1) \
231 break; \
232 } \
233 } else if (__HASH_->mode == HASH_TRIE) { \
234 int CONCAT(__ht_node_trie_func_macro, __LINE__)(HASH_NODE * __ITEM_) { \
235 if (!__ITEM_) return TRUE; \
236 int CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 1; \
237 if (__ITEM_->is_leaf) { \
238 do { \
239 __VA_ARGS__ \
240 CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 0; \
241 } while (0); \
242 } \
243 if (CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) == 1) return FALSE; \
244 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__)++) { \
245 if (CONCAT(__ht_node_trie_func_macro, __LINE__)(__ITEM_->children[CONCAT(__ht_node_trie_func_it, __LINE__)]) == FALSE) \
246 return FALSE; \
247 } \
248 return TRUE; \
249 } \
250 CONCAT(__ht_node_trie_func_macro, __LINE__) \
251 (__HASH_->root); \
252 } else { \
253 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
254 break; \
255 } \
256 } \
257 } while (0); \
258 }
259
261#define HT_FOREACH_R(__ITEM_, __HASH_, __ITERATOR, ...) \
262 { \
263 do { \
264 if (!__HASH_) { \
265 n_log(LOG_ERR, "Error in ht_foreach, %s is NULL", #__HASH_); \
266 } else { \
267 if (__HASH_->mode == HASH_CLASSIC) { \
268 int CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
269 LIST_NODE* CONCAT(__ht_list_node_r, __LINE__) = NULL; \
270 for (size_t __ITERATOR = 0; __ITERATOR < __HASH_->size; __ITERATOR++) { \
271 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) { \
272 HASH_NODE* __ITEM_ = (HASH_NODE*)CONCAT(__ht_list_node_r, __LINE__)->ptr; \
273 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 1; \
274 __VA_ARGS__ \
275 CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) = 0; \
276 } \
277 if (CONCAT(__ht_node_trie_func_macro_break_flag_classic, __LINE__) == 1) \
278 break; \
279 } \
280 } else if (__HASH_->mode == HASH_TRIE) { \
281 int CONCAT(__ht_node_trie_func_macro, __LINE__)(HASH_NODE * __ITEM_) { \
282 if (!__ITEM_) return TRUE; \
283 int CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 1; \
284 if (__ITEM_->is_leaf) { \
285 do { \
286 __VA_ARGS__ \
287 CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) = 0; \
288 } while (0); \
289 } \
290 if (CONCAT(__ht_node_trie_func_macro_break_flag, __LINE__) == 1) return FALSE; \
291 for (size_t it = 0; it < __ITEM_->alphabet_length; it++) { \
292 if (CONCAT(__ht_node_trie_func_macro, __LINE__)(__ITEM_->children[it]) == FALSE) \
293 return FALSE; \
294 } \
295 return TRUE; \
296 } \
297 CONCAT(__ht_node_trie_func_macro, __LINE__) \
298 (__HASH_->root); \
299 } else { \
300 n_log(LOG_ERR, "Error in ht_foreach, %d is an unsupported mode", __HASH_->mode); \
301 break; \
302 } \
303 } \
304 } while (0); \
305 }
306
308void MurmurHash3_x86_32(const void* key, const size_t len, const uint32_t seed, void* out);
309// void MurmurHash3_x86_128(const void* key, int len, uint32_t seed, void* out);
311void MurmurHash3_x86_128(const void* key, const size_t len, const uint32_t seed, void* out);
313void MurmurHash3_x64_128(const void* key, const size_t len, const uint64_t seed, void* out);
314
316char* ht_node_type(const HASH_NODE* node);
318HASH_NODE* ht_get_node(HASH_TABLE* table, const char* key);
319
321HASH_TABLE* new_ht(size_t size);
323HASH_TABLE* new_ht_trie(size_t alphabet_size, size_t alphabet_offset);
324
326int ht_get_double(HASH_TABLE* table, const char* key, double* val);
328int ht_get_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE* val);
330int ht_get_ptr(HASH_TABLE* table, const char* key, void** val);
332int ht_get_string(HASH_TABLE* table, const char* key, char** val);
334int ht_put_double(HASH_TABLE* table, const char* key, double value);
336int ht_put_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE value);
338int ht_put_ptr(HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
340int ht_put_string(HASH_TABLE* table, const char* key, char* string);
342int ht_put_string_ptr(HASH_TABLE* table, const char* key, char* string);
344int ht_remove(HASH_TABLE* table, const char* key);
346void ht_print(HASH_TABLE* table);
348LIST* ht_search(HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node));
350int empty_ht(HASH_TABLE* table);
352int destroy_ht(HASH_TABLE** table);
353
355HASH_NODE* ht_get_node_ex(HASH_TABLE* table, HASH_VALUE hash_value);
357int ht_put_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void* val, void (*destructor)(void* ptr), void* (*duplicator)(void* ptr));
359int ht_get_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void** val);
361int ht_remove_ex(HASH_TABLE* table, HASH_VALUE hash_value);
362
364LIST* ht_get_completion_list(HASH_TABLE* table, const char* keybud, size_t max_results);
365
367int is_prime(size_t nb);
369size_t next_prime(size_t nb);
370
374size_t ht_get_optimal_size(HASH_TABLE* table);
376int ht_resize(HASH_TABLE** table, size_t size);
378int ht_optimize(HASH_TABLE** table);
381
386#ifdef __cplusplus
387}
388#endif
389
390#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:157
size_t alphabet_length
HASH_TRIE mode: size of alphabet and so size of children allocated array.
Definition n_hash.h:133
int need_rehash
flag to mark a node for rehash
Definition n_hash.h:129
char key_id
key id of the node if any
Definition n_hash.h:115
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:173
int(* ht_put_string)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string
Definition n_hash.h:163
char * key
string key of the node if any, else NULL
Definition n_hash.h:113
int64_t ival
integral type
Definition n_hash.h:101
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:161
int is_leaf
HASH_TRIE mode: does it have a value.
Definition n_hash.h:127
HASH_NODE * root
HASH_TRIE mode: Start of tree.
Definition n_hash.h:147
void * ptr
pointer type
Definition n_hash.h:105
union HASH_DATA data
data inside the node
Definition n_hash.h:121
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:171
int type
type of the node
Definition n_hash.h:119
int(* empty_ht)(struct HASH_TABLE *table)
empty a hash table.
Definition n_hash.h:179
LIST ** hash_table
HASH_CLASSIC mode: preallocated hash table.
Definition n_hash.h:145
size_t alphabet_offset
HASH_TRIE mode: offset to deduce to individual key digits.
Definition n_hash.h:151
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:169
size_t alphabet_length
HASH_TRIE mode: size of the alphabet.
Definition n_hash.h:149
unsigned int mode
hashing mode, murmurhash and classic HASH_MURMUR, or HASH_TRIE
Definition n_hash.h:153
size_t seed
table's seed
Definition n_hash.h:143
int(* destroy_ht)(struct HASH_TABLE **table)
destroy a hash table
Definition n_hash.h:181
int(* ht_put_string_ptr)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string pointer
Definition n_hash.h:165
int(* ht_remove)(struct HASH_TABLE *table, const char *key)
remove given's key node from the table
Definition n_hash.h:175
void(* ht_print)(struct HASH_TABLE *table)
print table
Definition n_hash.h:183
char * string
char *type
Definition n_hash.h:107
int(* ht_put_double)(struct HASH_TABLE *table, const char *key, double val)
put a double
Definition n_hash.h:159
struct HASH_NODE ** children
HASH_TRIE mode: pointers to children.
Definition n_hash.h:131
HASH_VALUE hash_value
numeric key of the node if any, else < 0
Definition n_hash.h:117
double fval
double type
Definition n_hash.h:103
size_t size
size of the hash table
Definition n_hash.h:139
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:167
size_t nb_keys
total number of used keys in the table
Definition n_hash.h:141
void(* destroy_func)(void *ptr)
destroy_func
Definition n_hash.h:123
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:2100
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:2214
HASH_TABLE * ht_duplicate(HASH_TABLE *table)
duplicate a hash table
Definition n_hash.c:2636
int destroy_ht(HASH_TABLE **table)
destroy a hash table and free all resources
Definition n_hash.c:2234
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:2297
int ht_remove(HASH_TABLE *table, const char *key)
remove a node from the hash table by key
Definition n_hash.c:2192
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:2245
HASH_TABLE * new_ht(size_t size)
create a new classic hash table of the given size
Definition n_hash.c:2001
int ht_get_table_collision_percentage(HASH_TABLE *table)
get the collision percentage of the hash table
Definition n_hash.c:2477
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:2074
int empty_ht(HASH_TABLE *table)
empty a hash table, freeing all nodes
Definition n_hash.c:2224
void ht_print(HASH_TABLE *table)
print the contents of a hash table
Definition n_hash.c:2202
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:2391
size_t HASH_VALUE
type of a HASH_VALUE
Definition n_hash.h:96
int ht_put_double(HASH_TABLE *table, const char *key, double value)
put a double value into the hash table
Definition n_hash.c:2126
size_t ht_get_optimal_size(HASH_TABLE *table)
compute the optimal size for the hash table
Definition n_hash.c:2501
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:2154
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:2113
int is_prime(size_t nb)
check if a number is prime
Definition n_hash.c:2438
#define HASH_INT_TYPE
type of a HASH_INT in 64 bits
Definition n_hash.h:92
size_t next_prime(size_t nb)
return the next prime number greater than or equal to nb
Definition n_hash.c:2460
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:2167
int ht_resize(HASH_TABLE **table, size_t size)
resize a hash table to the given size
Definition n_hash.c:2520
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:1026
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:1194
int ht_remove_ex(HASH_TABLE *table, HASH_VALUE hash_value)
remove a node by numeric hash value
Definition n_hash.c:2350
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:2087
HASH_NODE * ht_get_node(HASH_TABLE *table, const char *key)
get the HASH_NODE associated with the given key
Definition n_hash.c:2061
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:1955
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:2139
int ht_optimize(HASH_TABLE **table)
optimize a hash table by resizing to the optimal size
Definition n_hash.c:2602
char * ht_node_type(const HASH_NODE *node)
return the type of a hash node as a string
Definition n_hash.c:1316
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:968
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:2180
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:2270
structure of a hash table node
Definition n_hash.h:111
structure of a hash table
Definition n_hash.h:137
union of the possibles data values of a node
Definition n_hash.h:99
Structure of a generic LIST container.
Definition n_list.h:58
Common headers and low-level functions & define.
List structures and definitions.