Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_hash.c
Go to the documentation of this file.
1
8#include "nilorea/n_common.h"
9#include "nilorea/n_log.h"
10#include "nilorea/n_hash.h"
11#include "nilorea/n_str.h"
12
13#include <pthread.h>
14#include <string.h>
15#include <strings.h>
16
17#ifdef __windows__
18#include <winsock.h>
19#else
20#include <arpa/inet.h>
21#endif
22
23/************ TRIE TREE TABLES ************/
24
32HASH_NODE* _ht_new_node_trie(HASH_TABLE* table, const char key) {
33 __n_assert(table, return NULL);
34
35 HASH_NODE* new_hash_node = NULL;
36 Malloc(new_hash_node, HASH_NODE, 1);
37 __n_assert(new_hash_node, n_log(LOG_ERR, "Could not allocate new_hash_node"); return NULL);
38 new_hash_node->key = NULL;
39 new_hash_node->hash_value = 0;
40 new_hash_node->data.ptr = NULL;
41 new_hash_node->destroy_func = NULL;
42 new_hash_node->children = NULL;
43 new_hash_node->is_leaf = 0;
44 new_hash_node->need_rehash = 0;
45 new_hash_node->alphabet_length = table->alphabet_length;
46
47 Malloc(new_hash_node->children, HASH_NODE*, table->alphabet_length);
48 __n_assert(new_hash_node->children, n_log(LOG_ERR, "Could not allocate new_hash_node"); Free(new_hash_node); return NULL);
49
50 /* n_log( LOG_DEBUG , "node: %d %c table: alpha: %d / offset %d" , key , key , table -> alphabet_length , table -> alphabet_offset ); */
51
52 for (size_t it = 0; it < table->alphabet_length; it++) {
53 new_hash_node->children[it] = NULL;
54 }
55 new_hash_node->is_leaf = 0;
56 new_hash_node->key_id = key;
57 return new_hash_node;
58} /* _ht_new_node_trie(...) */
59
66int _ht_is_leaf_node_trie(HASH_TABLE* table, const char* key) {
67 __n_assert(table, return -1);
68
69 /* checks if the prefix match of key and root is a leaf node */
70 HASH_NODE* node = table->root;
71 for (size_t it = 0; key[it]; it++) {
72 size_t index = (size_t)key[it] - table->alphabet_offset;
73 if (index >= table->alphabet_length) {
74 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
75 index = 0;
76 }
77 if (node->children[index]) {
78 node = node->children[index];
79 }
80 }
81 return node->is_leaf;
82} /* _ht_is_leaf_node_trie(...) */
83
88void _ht_node_destroy(void* node) {
89 HASH_NODE* node_ptr = (HASH_NODE*)node;
90 __n_assert(node_ptr, return);
91 if (node_ptr->type == HASH_STRING) {
92 Free(node_ptr->data.string);
93 }
94 if (node_ptr->type == HASH_PTR) {
95 if (node_ptr->destroy_func && node_ptr->data.ptr) {
96 node_ptr->destroy_func(node_ptr->data.ptr);
97 }
98 /* No free by default. must be passed as a destroy_func
99 else
100 {
101 Free( node_ptr -> data . ptr );
102 }
103 */
104 }
105 FreeNoLog(node_ptr->key);
106 if (node_ptr->alphabet_length > 0) {
107 for (size_t it = 0; it < node_ptr->alphabet_length; it++) {
108 if (node_ptr->children[it]) {
109 _ht_node_destroy(node_ptr->children[it]);
110 }
111 }
112 Free(node_ptr->children);
113 }
114 Free(node_ptr)
115} /* _ht_node_destroy */
116
123size_t _ht_check_trie_divergence(HASH_TABLE* table, const char* key) {
124 __n_assert(table, return SIZE_MAX);
125 __n_assert(key, return SIZE_MAX);
126
127 HASH_NODE* node = table->root;
128
129 size_t last_index = 0;
130 for (size_t it = 0; key[it] != '\0'; it++) {
131 size_t index = (size_t)key[it] - table->alphabet_offset;
132 if (index >= table->alphabet_length) {
133 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
134 index = 0;
135 }
136 if (node->children[index]) {
137 /* child check */
138 for (size_t it2 = 0; it2 < table->alphabet_length; it2++) {
139 if (it2 != (unsigned)index && node->children[it2]) {
140 /* child found, update branch index */
141 last_index = it + 1;
142 break;
143 }
144 }
145 /* Go to the next child in the sequence */
146 node = node->children[index];
147 }
148 }
149 return last_index;
150} /* _ht_check_trie_divergence(...) */
151
158char* _ht_find_longest_prefix_trie(HASH_TABLE* table, const char* key) {
159 __n_assert(table, return NULL);
160 __n_assert(key, return NULL);
161
162 size_t len = strlen(key);
163
164 /* start with full key and backtrack to search for divergences */
165 char* longest_prefix = NULL;
166 Malloc(longest_prefix, char, len + 1);
167 __n_assert(longest_prefix, return NULL);
168 memcpy(longest_prefix, key, len);
169
170 /* check branching from the root */
171 size_t branch_index = _ht_check_trie_divergence(table, longest_prefix);
172 if (branch_index > 0 && branch_index != SIZE_MAX) {
173 /* there is branching, update the position to the longest match and update the longest prefix by the branch index length */
174 longest_prefix[branch_index - 1] = '\0';
175 Realloc(longest_prefix, char, (branch_index + 1));
176 if (!longest_prefix) {
177 n_log(LOG_ERR, "reallocation error, stopping find longest prefix");
178 return NULL;
179 }
180 __n_assert(longest_prefix, return NULL);
181 }
182 return longest_prefix;
183} /* _ht_find_longest_prefix_trie(...) */
184
191int _ht_remove_trie(HASH_TABLE* table, const char* key) {
192 __n_assert(table, return FALSE);
193 __n_assert(table->root, return FALSE);
194 __n_assert(key, return FALSE);
195
196 /* stop if matching node not a leaf node */
197 if (!_ht_is_leaf_node_trie(table, key)) {
198 return FALSE;
199 }
200
201 HASH_NODE* node = table->root;
202 /* find the longest prefix string that is not the current key */
203 char* longest_prefix = _ht_find_longest_prefix_trie(table, key);
204 if (longest_prefix && longest_prefix[0] == '\0') {
205 Free(longest_prefix);
206 return FALSE;
207 }
208 /* keep track of position in the tree */
209 size_t it = 0;
210 for (it = 0; longest_prefix[it] != '\0'; it++) {
211 size_t index = (size_t)longest_prefix[it] - table->alphabet_offset;
212 if (index >= table->alphabet_length) {
213 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
214 index = 0;
215 }
216 if (node->children[index] != NULL) {
217 /* common prefix, keep moving */
218 node = node->children[index];
219 } else {
220 /* not found */
221 Free(longest_prefix);
222 return FALSE;
223 }
224 }
225 /* deepest common node between the two strings */
226 /* deleting the sequence corresponding to key */
227 for (; key[it] != '\0'; it++) {
228 size_t index = (size_t)key[it] - table->alphabet_offset;
229 if (index >= table->alphabet_length) {
230 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
231 index = 0;
232 }
233 if (node->children[index]) {
234 /* delete the remaining sequence */
235 HASH_NODE* node_to_kill = node->children[index];
236 node->children[index] = NULL;
237 _ht_node_destroy(node_to_kill);
238 }
239 }
240 Free(longest_prefix);
241
242 table->nb_keys--;
243
244 return TRUE;
245} /* _ht_remove_trie(...) */
246
256int _ht_put_int_trie(HASH_TABLE* table, const char* key, HASH_INT_TYPE value) {
257 __n_assert(table, return FALSE);
258 __n_assert(key, return FALSE);
259
260 HASH_NODE* node = table->root;
261
262 for (size_t it = 0; key[it] != '\0'; it++) {
263 size_t index = (size_t)key[it] - table->alphabet_offset;
264 if (index >= table->alphabet_length) {
265 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
266 index = 0;
267 }
268 /* n_log( LOG_DEBUG , "index:%d" , index ); */
269 if (node->children[index] == NULL) {
270 /* create a node */
271 node->children[index] = _ht_new_node_trie(table, key[it]);
272 __n_assert(node->children[index], return FALSE);
273 } else {
274 /* nothing to do since node is existing */
275 }
276 /* go down a level, to the child referenced by index */
277 node = node->children[index];
278 }
279 /* At the end of the key, mark this node as the leaf node */
280 node->is_leaf = 1;
281 /* Put the key */
282 node->key = strdup(key);
283 if (!node->key) {
284 n_log(LOG_ERR, "strdup failure for key [%s]", key);
285 table->nb_keys++; /* compensate for upcoming remove */
286 _ht_remove_trie(table, key);
287 return FALSE;
288 }
289 /* Put the value */
290 node->data.ival = value;
291 node->type = HASH_INT;
292
293 table->nb_keys++;
294
295 return TRUE;
296} /* _ht_put_int_trie(...) */
297
307int _ht_put_double_trie(HASH_TABLE* table, const char* key, double value) {
308 __n_assert(table, return FALSE);
309 __n_assert(key, return FALSE);
310
311 HASH_NODE* node = table->root;
312
313 for (size_t it = 0; key[it] != '\0'; it++) {
314 size_t index = (size_t)key[it] - table->alphabet_offset;
315 if (index >= table->alphabet_length) {
316 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
317 index = 0;
318 }
319 if (node->children[index] == NULL) {
320 /* create a node */
321 node->children[index] = _ht_new_node_trie(table, key[it]);
322 __n_assert(node->children[index], return FALSE);
323 } else {
324 /* nothing to do since node is existing */
325 }
326 /* go down a level, to the child referenced by index */
327 node = node->children[index];
328 }
329 /* At the end of the key, mark this node as the leaf node */
330 node->is_leaf = 1;
331 /* Put the key */
332 node->key = strdup(key);
333 if (!node->key) {
334 n_log(LOG_ERR, "strdup failure for key [%s]", key);
335 table->nb_keys++; /* compensate for upcoming remove */
336 _ht_remove_trie(table, key);
337 return FALSE;
338 }
339 /* Put the value */
340 node->data.fval = value;
341 node->type = HASH_DOUBLE;
342
343 table->nb_keys++;
344
345 return TRUE;
346} /* _ht_put_double_trie(...) */
347
357int _ht_put_string_trie(HASH_TABLE* table, const char* key, char* string) {
358 __n_assert(table, return FALSE);
359 __n_assert(key, return FALSE);
360
361 HASH_NODE* node = table->root;
362
363 for (size_t it = 0; key[it] != '\0'; it++) {
364 size_t index = (size_t)key[it] - table->alphabet_offset;
365 if (index >= table->alphabet_length) {
366 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
367 index = 0;
368 }
369 if (node->children[index] == NULL) {
370 /* create a node */
371 node->children[index] = _ht_new_node_trie(table, key[it]);
372 __n_assert(node->children[index], return FALSE);
373 } else {
374 /* nothing to do since node is existing */
375 }
376 /* go down a level, to the child referenced by index */
377 node = node->children[index];
378 }
379 /* At the end of the key, mark this node as the leaf node */
380 node->is_leaf = 1;
381 /* Put the key */
382 node->key = strdup(key);
383 if (!node->key) {
384 n_log(LOG_ERR, "strdup failure for key [%s]", key);
385 table->nb_keys++; /* compensate for upcoming remove */
386 _ht_remove_trie(table, key);
387 return FALSE;
388 }
389 /* Put the value */
390 if (string) {
391 node->data.string = strdup(string);
392 if (!node->data.string) {
393 n_log(LOG_ERR, "strdup failure for value at key [%s]", key);
394 Free(node->key);
395 table->nb_keys++; /* compensate for upcoming remove */
396 _ht_remove_trie(table, key);
397 return FALSE;
398 }
399 } else {
400 node->data.string = NULL;
401 }
402
403 node->type = HASH_STRING;
404
405 table->nb_keys++;
406
407 return TRUE;
408} /* _ht_put_string_trie(...) */
409
419int _ht_put_string_ptr_trie(HASH_TABLE* table, const char* key, char* string) {
420 __n_assert(table, return FALSE);
421 __n_assert(key, return FALSE);
422
423 HASH_NODE* node = table->root;
424
425 for (size_t it = 0; key[it] != '\0'; it++) {
426 size_t index = (size_t)key[it] - table->alphabet_offset;
427 if (index >= table->alphabet_length) {
428 n_log(LOG_ERR, "Invalid value %d for charater at position %d of %s, set to 0", index, it, key);
429 index = 0;
430 }
431 if (node->children[index] == NULL) {
432 /* create a node */
433 node->children[index] = _ht_new_node_trie(table, key[it]);
434 __n_assert(node->children[index], return FALSE);
435 } else {
436 /* nothing to do since node is existing */
437 }
438 /* go down a level, to the child referenced by index */
439 node = node->children[index];
440 }
441 /* At the end of the key, mark this node as the leaf node */
442 node->is_leaf = 1;
443 /* Put the key */
444 node->key = strdup(key);
445 if (!node->key) {
446 n_log(LOG_ERR, "strdup failure for key [%s]", key);
447 table->nb_keys++; /* compensate for upcoming remove */
448 _ht_remove_trie(table, key);
449 return FALSE;
450 }
451 /* Put the string */
452 node->data.string = string;
453 node->type = HASH_STRING;
454
455 table->nb_keys++;
456
457 return TRUE;
458} /* _ht_put_string_ptr_trie(...) */
459
470int _ht_put_ptr_trie(HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr)) {
471 __n_assert(table, return FALSE);
472 __n_assert(key, return FALSE);
473
474 HASH_NODE* node = table->root;
475
476 for (size_t it = 0; key[it] != '\0'; it++) {
477 size_t index = ((size_t)key[it] - table->alphabet_offset) % table->alphabet_length;
478 if (index >= table->alphabet_length) {
479 n_log(LOG_ERR, "Invalid value %u for charater at position %d of %s, set to 0", index, it, key);
480 index = 0;
481 }
482 if (node->children[index] == NULL) {
483 /* create a node */
484 node->children[index] = _ht_new_node_trie(table, key[it]);
485 __n_assert(node->children[index], return FALSE);
486 } else {
487 /* nothing to do since node is existing */
488 }
489 /* go down a level, to the child referenced by index */
490 node = node->children[index];
491 }
492 /* At the end of the key, mark this node as the leaf node */
493 node->is_leaf = 1;
494 /* Put the key */
495 node->key = strdup(key);
496 /* Put the value */
497 node->data.ptr = ptr;
498 if (destructor)
499 node->destroy_func = destructor;
500 node->type = HASH_PTR;
501
502 table->nb_keys++;
503
504 return TRUE;
505} /* _ht_put_ptr_trie(...) */
506
515HASH_NODE* _ht_get_node_trie(HASH_TABLE* table, const char* key) {
516 __n_assert(table, return NULL);
517 __n_assert(key, return NULL);
518
519 HASH_NODE* node = NULL;
520
521 if (key[0] != '\0') {
522 node = table->root;
523 for (size_t it = 0; key[it] != '\0'; it++) {
524 size_t index = (size_t)key[it] - table->alphabet_offset;
525 if (index >= table->alphabet_length) {
526 n_log(LOG_DEBUG, "Invalid value %d for charater at index %d of %s, set to 0", index, it, key);
527 return NULL;
528 }
529 if (node->children[index] == NULL) {
530 /* not found */
531 return NULL;
532 }
533 node = node->children[index];
534 }
535 } else {
536 node = NULL;
537 }
538 return node;
539} /* _ht_get_node_trie(...) */
540
548int _ht_get_int_trie(HASH_TABLE* table, const char* key, HASH_INT_TYPE* val) {
549 __n_assert(table, return FALSE);
550 __n_assert(key, return FALSE);
551 if (strlen(key) == 0)
552 return FALSE;
553
554 HASH_NODE* node = _ht_get_node_trie(table, key);
555
556 if (!node || !node->is_leaf)
557 return FALSE;
558
559 if (node->type != HASH_INT) {
560 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_INT, key is type %s", key, ht_node_type(node));
561 return FALSE;
562 }
563
564 (*val) = node->data.ival;
565
566 return TRUE;
567} /* _ht_get_int_trie() */
568
576int _ht_get_double_trie(HASH_TABLE* table, const char* key, double* val) {
577 __n_assert(table, return FALSE);
578 __n_assert(key, return FALSE);
579 if (strlen(key) == 0)
580 return FALSE;
581
582 HASH_NODE* node = _ht_get_node_trie(table, key);
583
584 if (!node || !node->is_leaf)
585 return FALSE;
586
587 if (node->type != HASH_DOUBLE) {
588 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_INT, key is type %s", key, ht_node_type(node));
589 return FALSE;
590 }
591
592 (*val) = node->data.fval;
593
594 return TRUE;
595} /* _ht_get_double_trie() */
596
604int _ht_get_string_trie(HASH_TABLE* table, const char* key, char** val) {
605 __n_assert(table, return FALSE);
606 __n_assert(key, return FALSE);
607 if (strlen(key) == 0)
608 return FALSE;
609
610 HASH_NODE* node = _ht_get_node_trie(table, key);
611
612 if (!node || !node->is_leaf)
613 return FALSE;
614
615 if (node->type != HASH_STRING) {
616 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_INT, key is type %s", key, ht_node_type(node));
617 return FALSE;
618 }
619
620 (*val) = node->data.string;
621
622 return TRUE;
623} /* _ht_get_string_trie() */
624
632int _ht_get_ptr_trie(HASH_TABLE* table, const char* key, void** val) {
633 __n_assert(table, return FALSE);
634 __n_assert(key, return FALSE);
635 if (strlen(key) == 0)
636 return FALSE;
637
638 HASH_NODE* node = _ht_get_node_trie(table, key);
639
640 if (!node || !node->is_leaf)
641 return FALSE;
642
643 if (node->type != HASH_PTR) {
644 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_PTR , key is type %s", key, ht_node_type(node));
645 return FALSE;
646 }
647
648 (*val) = node->data.ptr;
649
650 return TRUE;
651} /* _ht_get_ptr_trie() */
652
659 __n_assert(table, return FALSE);
660
661 _ht_node_destroy(table->root);
662
663 table->root = _ht_new_node_trie(table, '\0');
664
665 table->nb_keys = 0;
666 return TRUE;
667} /* _empty_ht_trie */
668
677 __n_assert(table && (*table), n_log(LOG_ERR, "Can't destroy table: already NULL"); return FALSE);
678
679 _ht_node_destroy((*table)->root);
680
681 Free((*table));
682
683 return TRUE;
684} /* _destroy_ht_trie */
685
694 if (!node)
695 return;
696
697 if (node->is_leaf) {
698 printf("key: %s, val: ", node->key);
699 switch (node->type) {
700 case HASH_INT:
701 printf("int: %ld", (long)node->data.ival);
702 break;
703 case HASH_DOUBLE:
704 printf("double: %f", node->data.fval);
705 break;
706 case HASH_PTR:
707 printf("ptr: %p", node->data.ptr);
708 break;
709 case HASH_STRING:
710 printf("%s", node->data.string);
711 break;
712 default:
713 printf("unknwow type %d", node->type);
714 break;
715 }
716 printf("\n");
717 }
718 for (size_t it = 0; it < table->alphabet_length; it++) {
719 _ht_print_trie_helper(table, node->children[it]);
720 }
721} /* _ht_print_trie_helper(...) */
722
728 __n_assert(table, return);
729 __n_assert(table->root, return);
730
731 HASH_NODE* node = table->root;
732
733 _ht_print_trie_helper(table, node);
734
735 return;
736} /* _ht_print_trie(...) */
737
746void _ht_search_trie_helper(LIST* results, HASH_NODE* node, int (*node_is_matching)(HASH_NODE* node)) {
747 if (!node)
748 return;
749
750 if (node->is_leaf) {
751 if (node_is_matching(node) == TRUE) {
752 list_push(results, strdup(node->key), &free);
753 }
754 }
755 for (size_t it = 0; it < node->alphabet_length; it++) {
756 _ht_search_trie_helper(results, node->children[it], node_is_matching);
757 }
758}
759
768LIST* _ht_search_trie(HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node)) {
769 __n_assert(table, return NULL);
770
771 LIST* results = new_generic_list(MAX_LIST_ITEMS);
772 __n_assert(results, return NULL);
773
774 _ht_search_trie_helper(results, table->root, node_is_matching);
775
776 if (results->nb_items < 1)
777 list_destroy(&results);
778
779 return results;
780} /* _ht_search_trie(...) */
781
791 __n_assert(results, return FALSE);
792
793 if (!node)
794 return FALSE;
795
796 for (size_t it = 0; it < node->alphabet_length; it++) {
797 _ht_depth_first_search(node->children[it], results);
798 }
799 if (node->is_leaf) {
800 if (results->nb_items < results->nb_max_items) {
801 return list_push(results, strdup(node->key), &free);
802 }
803 return TRUE;
804 }
805 return TRUE;
806} /* _ht_depth_first_search(...) */
807
808/************ CLASSIC HASH TABLE ************/
810#define ROTL64(x, r) (((x) << (r)) | ((x) >> (64 - (r))))
812#define ROTL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
814#define BIG_CONSTANT(x) (x##LLU)
815
816/* NO-OP for little-endian platforms */
817#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
818#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
819#define BYTESWAP32(x) (x)
820#define BYTESWAP64(x) (x)
821#endif
822/* if __BYTE_ORDER__ is not predefined (like FreeBSD), use arch */
823#elif defined(__i386) || defined(__x86_64) || defined(__alpha) || defined(__vax)
824
825#define BYTESWAP32(x) (x)
826#define BYTESWAP64(x) (x)
827/* use __builtin_bswap32 if available */
828#elif defined(__GNUC__) || defined(__clang__)
829#ifdef __has_builtin
830#if __has_builtin(__builtin_bswap32)
831#define BYTESWAP32(x) __builtin_bswap32(x)
832#endif // __has_builtin(__builtin_bswap32)
833#if __has_builtin(__builtin_bswap64)
834#define BYTESWAP64(x) __builtin_bswap64(x)
835#endif // __has_builtin(__builtin_bswap64)
836#endif // __has_builtin
837#endif // defined(__GNUC__) || defined(__clang__)
838/* last resort (big-endian w/o __builtin_bswap) */
839#ifndef BYTESWAP32
841#define BYTESWAP32(x) ((((x) & 0xFF) << 24) | (((x) >> 24) & 0xFF) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8))
842#endif
843#ifndef BYTESWAP64
845#define BYTESWAP64(x) \
846 (((uint64_t)(x) << 56) | \
847 (((uint64_t)(x) << 40) & 0X00FF000000000000ULL) | \
848 (((uint64_t)(x) << 24) & 0X0000FF0000000000ULL) | \
849 (((uint64_t)(x) << 8) & 0X000000FF00000000ULL) | \
850 (((uint64_t)(x) >> 8) & 0X00000000FF000000ULL) | \
851 (((uint64_t)(x) >> 24) & 0X0000000000FF0000ULL) | \
852 (((uint64_t)(x) >> 40) & 0X000000000000FF00ULL) | \
853 ((uint64_t)(x) >> 56))
854#endif
855
862FORCE_INLINE uint32_t getblock32(const uint32_t* p, const size_t i) {
863 uint32_t result;
864 memcpy(&result, (const uint8_t*)p + i * 4, sizeof(result));
865 return BYTESWAP32(result);
866}
867
874FORCE_INLINE uint64_t getblock64(const uint64_t* p, const size_t i) {
875 uint64_t result;
876 memcpy(&result, (const uint8_t*)p + i * 8, sizeof(result));
877 return BYTESWAP64(result);
878}
879
885FORCE_INLINE uint32_t fmix32(uint32_t h) {
886 h ^= h >> 16;
887 h *= 0x85ebca6b;
888 h ^= h >> 13;
889 h *= 0xc2b2ae35;
890 h ^= h >> 16;
891
892 return h;
893} /* fmix32(...) */
894
900FORCE_INLINE uint64_t fmix64(uint64_t k) {
901 k ^= k >> 33;
902 k *= BIG_CONSTANT(0xff51afd7ed558ccd);
903 k ^= k >> 33;
904 k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
905 k ^= k >> 33;
906
907 return k;
908}
909
922// Safe forward-indexing version
923void MurmurHash3_x86_32(const void* key, const size_t len, const uint32_t seed, void* out) {
924 const uint8_t* data = (const uint8_t*)key;
925 const size_t nblocks = len / 4;
926
927 uint32_t h1 = seed;
928 const uint32_t c1 = 0xcc9e2d51;
929 const uint32_t c2 = 0x1b873593;
930
931 const uint32_t* blocks = (const uint32_t*)data;
932
933 for (size_t i = 0; i < nblocks; i++) {
934 uint32_t k1 = getblock32(blocks, i);
935 k1 *= c1;
936 k1 = ROTL32(k1, 15);
937 k1 *= c2;
938
939 h1 ^= k1;
940 h1 = ROTL32(h1, 13);
941 h1 = h1 * 5 + 0xe6546b64;
942 }
943
944 const uint8_t* tail = data + nblocks * 4;
945 uint32_t k1 = 0;
946 switch (len & 3) {
947 case 3:
948 k1 ^= (uint32_t)tail[2] << 16; /* fall through */
950 case 2:
951 k1 ^= (uint32_t)tail[1] << 8; /* fall through */
953 case 1:
954 k1 ^= (uint32_t)tail[0];
955 k1 *= c1;
956 k1 = ROTL32(k1, 15);
957 k1 *= c2;
958 h1 ^= k1;
959 break;
960 default:
961 break;
962 }
963
964 h1 ^= (uint32_t)len;
965 h1 = fmix32(h1);
966 *(uint32_t*)out = h1;
967} /* MurmurHash3_x86_32 */
968
981void MurmurHash3_x86_128(const void* key, const size_t len, const uint32_t seed, void* out) {
982 const uint8_t* data = (const uint8_t*)key;
983 const size_t nblocks = len / 16;
984
985 uint32_t h1 = seed;
986 uint32_t h2 = seed;
987 uint32_t h3 = seed;
988 uint32_t h4 = seed;
989
990 const uint32_t c1 = 0x239b961b;
991 const uint32_t c2 = 0xab0e9789;
992 const uint32_t c3 = 0x38b34ae5;
993 const uint32_t c4 = 0xa1e38b93;
994
995 const uint32_t* blocks = (const uint32_t*)data;
996
997 for (size_t i = 0; i < nblocks; i++) {
998 uint32_t k1 = getblock32(blocks, i * 4 + 0);
999 uint32_t k2 = getblock32(blocks, i * 4 + 1);
1000 uint32_t k3 = getblock32(blocks, i * 4 + 2);
1001 uint32_t k4 = getblock32(blocks, i * 4 + 3);
1002
1003 k1 *= c1;
1004 k1 = ROTL32(k1, 15);
1005 k1 *= c2;
1006 h1 ^= k1;
1007 h1 = ROTL32(h1, 19);
1008 h1 += h2;
1009 h1 = h1 * 5 + 0x561ccd1b;
1010
1011 k2 *= c2;
1012 k2 = ROTL32(k2, 16);
1013 k2 *= c3;
1014 h2 ^= k2;
1015 h2 = ROTL32(h2, 17);
1016 h2 += h3;
1017 h2 = h2 * 5 + 0x0bcaa747;
1018
1019 k3 *= c3;
1020 k3 = ROTL32(k3, 17);
1021 k3 *= c4;
1022 h3 ^= k3;
1023 h3 = ROTL32(h3, 15);
1024 h3 += h4;
1025 h3 = h3 * 5 + 0x96cd1c35;
1026
1027 k4 *= c4;
1028 k4 = ROTL32(k4, 18);
1029 k4 *= c1;
1030 h4 ^= k4;
1031 h4 = ROTL32(h4, 13);
1032 h4 += h1;
1033 h4 = h4 * 5 + 0x32ac3b17;
1034 }
1035
1036 // tail
1037 const uint8_t* tail = data + nblocks * 16;
1038
1039 uint32_t k1 = 0, k2 = 0, k3 = 0, k4 = 0;
1040
1041 switch (len & 15) {
1042 case 15:
1043 k4 ^= (uint32_t)tail[14] << 16; /* fall through */
1045 case 14:
1046 k4 ^= (uint32_t)tail[13] << 8; /* fall through */
1048 case 13:
1049 k4 ^= (uint32_t)tail[12];
1050 k4 *= c4;
1051 k4 = ROTL32(k4, 18);
1052 k4 *= c1;
1053 h4 ^= k4;
1054 /* fall through */
1056 case 12:
1057 k3 ^= (uint32_t)tail[11] << 24; /* fall through */
1059 case 11:
1060 k3 ^= (uint32_t)tail[10] << 16; /* fall through */
1062 case 10:
1063 k3 ^= (uint32_t)tail[9] << 8; /* fall through */
1065 case 9:
1066 k3 ^= (uint32_t)tail[8];
1067 k3 *= c3;
1068 k3 = ROTL32(k3, 17);
1069 k3 *= c4;
1070 h3 ^= k3;
1071 /* fall through */
1073 case 8:
1074 k2 ^= (uint32_t)tail[7] << 24; /* fall through */
1076 case 7:
1077 k2 ^= (uint32_t)tail[6] << 16; /* fall through */
1079 case 6:
1080 k2 ^= (uint32_t)tail[5] << 8; /* fall through */
1082 case 5:
1083 k2 ^= (uint32_t)tail[4];
1084 k2 *= c2;
1085 k2 = ROTL32(k2, 16);
1086 k2 *= c3;
1087 h2 ^= k2;
1088 /* fall through */
1090 case 4:
1091 k1 ^= (uint32_t)tail[3] << 24; /* fall through */
1093 case 3:
1094 k1 ^= (uint32_t)tail[2] << 16; /* fall through */
1096 case 2:
1097 k1 ^= (uint32_t)tail[1] << 8; /* fall through */
1099 case 1:
1100 k1 ^= (uint32_t)tail[0];
1101 k1 *= c1;
1102 k1 = ROTL32(k1, 15);
1103 k1 *= c2;
1104 h1 ^= k1;
1105 break;
1106 default:
1107 break;
1108 }
1109
1110 // finalization
1111 h1 ^= (uint32_t)len;
1112 h2 ^= (uint32_t)len;
1113 h3 ^= (uint32_t)len;
1114 h4 ^= (uint32_t)len;
1115
1116 h1 += h2 + h3 + h4;
1117 h2 += h1;
1118 h3 += h1;
1119 h4 += h1;
1120
1121 h1 = fmix32(h1);
1122 h2 = fmix32(h2);
1123 h3 = fmix32(h3);
1124 h4 = fmix32(h4);
1125
1126 h1 += h2 + h3 + h4;
1127 h2 += h1;
1128 h3 += h1;
1129 h4 += h1;
1130
1131 ((uint32_t*)out)[0] = h1;
1132 ((uint32_t*)out)[1] = h2;
1133 ((uint32_t*)out)[2] = h3;
1134 ((uint32_t*)out)[3] = h4;
1135} /* MurmurHash3_x86_128(...) */
1136
1149void MurmurHash3_x64_128(const void* key, const size_t len, const uint64_t seed, void* out) {
1150 const uint8_t* data = (const uint8_t*)key;
1151 const size_t nblocks = len / 16;
1152
1153 uint64_t h1 = seed;
1154 uint64_t h2 = seed;
1155
1156 const uint64_t c1 = 0x87c37b91114253d5ULL;
1157 const uint64_t c2 = 0x4cf5ad432745937fULL;
1158
1159 // Body
1160 const uint64_t* blocks = (const uint64_t*)data;
1161 for (size_t i = 0; i < nblocks; i++) {
1162 uint64_t k1 = getblock64(blocks, i * 2 + 0);
1163 uint64_t k2 = getblock64(blocks, i * 2 + 1);
1164
1165 k1 *= c1;
1166 k1 = ROTL64(k1, 31);
1167 k1 *= c2;
1168 h1 ^= k1;
1169
1170 h1 = ROTL64(h1, 27);
1171 h1 += h2;
1172 h1 = h1 * 5 + 0x52dce729;
1173
1174 k2 *= c2;
1175 k2 = ROTL64(k2, 33);
1176 k2 *= c1;
1177 h2 ^= k2;
1178
1179 h2 = ROTL64(h2, 31);
1180 h2 += h1;
1181 h2 = h2 * 5 + 0x38495ab5;
1182 }
1183
1184 // Tail
1185 const uint8_t* tail = data + nblocks * 16;
1186
1187 uint64_t k1 = 0;
1188 uint64_t k2 = 0;
1189
1190 switch (len & 15) {
1191 case 15:
1192 k2 ^= ((uint64_t)tail[14]) << 48; /* fall through */
1194 case 14:
1195 k2 ^= ((uint64_t)tail[13]) << 40; /* fall through */
1197 case 13:
1198 k2 ^= ((uint64_t)tail[12]) << 32; /* fall through */
1200 case 12:
1201 k2 ^= ((uint64_t)tail[11]) << 24; /* fall through */
1203 case 11:
1204 k2 ^= ((uint64_t)tail[10]) << 16; /* fall through */
1206 case 10:
1207 k2 ^= ((uint64_t)tail[9]) << 8; /* fall through */
1209 case 9:
1210 k2 ^= ((uint64_t)tail[8]);
1211 k2 *= c2;
1212 k2 = ROTL64(k2, 33);
1213 k2 *= c1;
1214 h2 ^= k2;
1215 /* fall through */
1217 case 8:
1218 k1 ^= ((uint64_t)tail[7]) << 56; /* fall through */
1220 case 7:
1221 k1 ^= ((uint64_t)tail[6]) << 48; /* fall through */
1223 case 6:
1224 k1 ^= ((uint64_t)tail[5]) << 40; /* fall through */
1226 case 5:
1227 k1 ^= ((uint64_t)tail[4]) << 32; /* fall through */
1229 case 4:
1230 k1 ^= ((uint64_t)tail[3]) << 24; /* fall through */
1232 case 3:
1233 k1 ^= ((uint64_t)tail[2]) << 16; /* fall through */
1235 case 2:
1236 k1 ^= ((uint64_t)tail[1]) << 8; /* fall through */
1238 case 1:
1239 k1 ^= ((uint64_t)tail[0]);
1240 k1 *= c1;
1241 k1 = ROTL64(k1, 31);
1242 k1 *= c2;
1243 h1 ^= k1;
1244 break;
1245 default:
1246 break;
1247 }
1248
1249 // Finalization
1250 h1 ^= len;
1251 h2 ^= len;
1252
1253 h1 += h2;
1254 h2 += h1;
1255
1256 h1 = fmix64(h1);
1257 h2 = fmix64(h2);
1258
1259 h1 += h2;
1260 h2 += h1;
1261
1262 ((uint64_t*)out)[0] = h1;
1263 ((uint64_t*)out)[1] = h2;
1264} /* MurmurHash3_x64_128()*/
1265
1272 static char* HASH_TYPE_STR[5] = {"HASH_INT", "HASH_DOUBLE", "HASH_STRING", "HASH_PTR", "HASH_UNKNOWN"};
1273
1274 __n_assert(node, return NULL);
1275
1276 if (node->type >= 0 && node->type < HASH_UNKNOWN)
1277 return HASH_TYPE_STR[node->type];
1278
1279 return NULL;
1280} /* ht_node_type(...) */
1281
1288HASH_NODE* _ht_get_node(HASH_TABLE* table, const char* key) {
1289 HASH_VALUE hash_value[2] = {0, 0};
1290 size_t index = 0;
1291
1292 HASH_NODE* node_ptr = NULL;
1293
1294 __n_assert(table, return NULL);
1295 __n_assert(key, return NULL);
1296
1297 if (key[0] == '\0')
1298 return NULL;
1299
1300 MurmurHash(key, strlen(key), table->seed, &hash_value);
1301 index = (hash_value[0]) % (table->size);
1302
1303 if (!table->hash_table[index]->start)
1304 return NULL;
1305
1306 list_foreach(list_node, table->hash_table[index]) {
1307 node_ptr = (HASH_NODE*)list_node->ptr;
1308 if (!strcmp(key, node_ptr->key)) {
1309 return node_ptr;
1310 }
1311 }
1312 return NULL;
1313} /* _ht_get_node() */
1314
1321HASH_NODE* _ht_new_node(HASH_TABLE* table, const char* key) {
1322 __n_assert(table, return NULL);
1323 __n_assert(key, return NULL);
1324
1325 HASH_NODE* new_hash_node = NULL;
1326
1327 HASH_VALUE hash_value[2] = {0, 0};
1328
1329 if (strlen(key) == 0)
1330 return NULL;
1331
1332 MurmurHash(key, strlen(key), table->seed, &hash_value);
1333
1334 Malloc(new_hash_node, HASH_NODE, 1);
1335 __n_assert(new_hash_node, n_log(LOG_ERR, "Could not allocate new_hash_node"); return NULL);
1336 new_hash_node->key = strdup(key);
1337 new_hash_node->key_id = '\0';
1338 __n_assert(new_hash_node->key, n_log(LOG_ERR, "Could not allocate new_hash_node->key"); Free(new_hash_node); return NULL);
1339 new_hash_node->hash_value = hash_value[0];
1340 new_hash_node->data.ptr = NULL;
1341 new_hash_node->destroy_func = NULL;
1342 new_hash_node->children = NULL;
1343 new_hash_node->is_leaf = 0;
1344 new_hash_node->need_rehash = 0;
1345 new_hash_node->alphabet_length = 0;
1346
1347 return new_hash_node;
1348} /* _ht_new_node */
1349
1357HASH_NODE* _ht_new_int_node(HASH_TABLE* table, const char* key, HASH_INT_TYPE value) {
1358 __n_assert(table, return NULL);
1359 __n_assert(key, return NULL);
1360
1361 HASH_NODE* new_hash_node = NULL;
1362 new_hash_node = _ht_new_node(table, key);
1363 if (new_hash_node) {
1364 new_hash_node->data.ival = value;
1365 new_hash_node->type = HASH_INT;
1366 } else {
1367 n_log(LOG_ERR, "Could not get a new node in table %p with key %s", table, key);
1368 }
1369 return new_hash_node;
1370} /* _ht_new_int_node */
1371
1379HASH_NODE* _ht_new_double_node(HASH_TABLE* table, const char* key, double value) {
1380 __n_assert(table, return NULL);
1381 __n_assert(key, return NULL);
1382
1383 HASH_NODE* new_hash_node = NULL;
1384 new_hash_node = _ht_new_node(table, key);
1385 if (new_hash_node) {
1386 new_hash_node->data.fval = value;
1387 new_hash_node->type = HASH_DOUBLE;
1388 } else {
1389 n_log(LOG_ERR, "Could not get a new node in table %p with key %s", table, key);
1390 }
1391 return new_hash_node;
1392} /* _ht_new_double_node */
1393
1401HASH_NODE* _ht_new_string_node(HASH_TABLE* table, const char* key, char* value) {
1402 __n_assert(table, return NULL);
1403 __n_assert(key, return NULL);
1404
1405 HASH_NODE* new_hash_node = NULL;
1406 new_hash_node = _ht_new_node(table, key);
1407 if (new_hash_node) {
1408 if (value)
1409 new_hash_node->data.string = strdup(value);
1410 else
1411 new_hash_node->data.string = NULL;
1412 new_hash_node->type = HASH_STRING;
1413 } else {
1414 n_log(LOG_ERR, "Could not get a new node in table %p with key %s", table, key);
1415 }
1416 return new_hash_node;
1417}
1418
1426HASH_NODE* _ht_new_string_ptr_node(HASH_TABLE* table, const char* key, char* value) {
1427 __n_assert(table, return NULL);
1428 __n_assert(key, return NULL);
1429
1430 HASH_NODE* new_hash_node = NULL;
1431 new_hash_node = _ht_new_node(table, key);
1432 if (new_hash_node) {
1433 new_hash_node->data.string = value;
1434 new_hash_node->type = HASH_STRING;
1435 } else {
1436 n_log(LOG_ERR, "Could not get a new node in table %p with key %s", table, key);
1437 }
1438 return new_hash_node;
1439}
1440
1449HASH_NODE* _ht_new_ptr_node(HASH_TABLE* table, const char* key, void* value, void (*destructor)(void* ptr)) {
1450 __n_assert(table, return NULL);
1451 __n_assert(key, return NULL);
1452
1453 HASH_NODE* new_hash_node = NULL;
1454 new_hash_node = _ht_new_node(table, key);
1455 if (new_hash_node) {
1456 new_hash_node->data.ptr = value;
1457 new_hash_node->destroy_func = destructor;
1458 new_hash_node->type = HASH_PTR;
1459 } else {
1460 n_log(LOG_ERR, "Could not get a new node in table %p with key %s", table, key);
1461 }
1462 return new_hash_node;
1463}
1464
1474int _ht_put_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE value) {
1475 HASH_NODE* node_ptr = NULL;
1476
1477 __n_assert(table, return FALSE);
1478 __n_assert(key, return FALSE);
1479
1480 if ((node_ptr = _ht_get_node(table, key))) {
1481 if (node_ptr->type == HASH_INT) {
1482 node_ptr->data.ival = value;
1483 return TRUE;
1484 }
1485 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_INT, key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
1486 return FALSE; /* key registered with another data type */
1487 }
1488
1489 int retcode = FALSE;
1490 node_ptr = _ht_new_int_node(table, key, value);
1491 if (node_ptr) {
1492 size_t index = (node_ptr->hash_value) % (table->size);
1493 retcode = list_push(table->hash_table[index], node_ptr, &_ht_node_destroy);
1494 if (retcode == TRUE) {
1495 table->nb_keys++;
1496 }
1497 }
1498 return retcode;
1499} /*_ht_put_int() */
1500
1508int _ht_put_double(HASH_TABLE* table, const char* key, double value) {
1509 HASH_NODE* node_ptr = NULL;
1510
1511 __n_assert(table, return FALSE);
1512 __n_assert(key, return FALSE);
1513
1514 if ((node_ptr = _ht_get_node(table, key))) {
1515 if (node_ptr->type == HASH_DOUBLE) {
1516 node_ptr->data.fval = value;
1517 return TRUE;
1518 }
1519 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_DOUBLE, key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
1520 return FALSE; /* key registered with another data type */
1521 }
1522
1523 int retcode = FALSE;
1524 node_ptr = _ht_new_double_node(table, key, value);
1525 if (node_ptr) {
1526 HASH_VALUE index = (node_ptr->hash_value) % (table->size);
1527 retcode = list_push(table->hash_table[index], node_ptr, &_ht_node_destroy);
1528 if (retcode == TRUE) {
1529 table->nb_keys++;
1530 }
1531 }
1532 return retcode;
1533} /*_ht_put_double()*/
1534
1543int _ht_put_ptr(HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr)) {
1544 HASH_NODE* node_ptr = NULL;
1545
1546 __n_assert(table, return FALSE);
1547 __n_assert(key, return FALSE);
1548
1549 if ((node_ptr = _ht_get_node(table, key))) {
1550 /* let's check the key isn't already assigned with another data type */
1551 if (node_ptr->type == HASH_PTR) {
1552 if (node_ptr->destroy_func) {
1553 node_ptr->destroy_func(node_ptr->data.ptr);
1554 node_ptr->data.ptr = ptr;
1555 node_ptr->destroy_func = destructor;
1556 }
1557 return TRUE;
1558 }
1559 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_PTR , key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
1560 return FALSE; /* key registered with another data type */
1561 }
1562
1563 int retcode = FALSE;
1564 node_ptr = _ht_new_ptr_node(table, key, ptr, destructor);
1565 if (node_ptr) {
1566 HASH_VALUE index = (node_ptr->hash_value) % (table->size);
1567 retcode = list_push(table->hash_table[index], node_ptr, &_ht_node_destroy);
1568 if (retcode == TRUE) {
1569 table->nb_keys++;
1570 }
1571 }
1572 return retcode;
1573} /* _ht_put_ptr() */
1574
1582int _ht_put_string(HASH_TABLE* table, const char* key, char* string) {
1583 HASH_NODE* node_ptr = NULL;
1584
1585 __n_assert(table, return FALSE);
1586 __n_assert(key, return FALSE);
1587
1588 if ((node_ptr = _ht_get_node(table, key))) {
1589 /* let's check the key isn't already assigned with another data type */
1590 if (node_ptr->type == HASH_STRING) {
1591 Free(node_ptr->data.string);
1592 node_ptr->data.string = strdup(string);
1593 return TRUE;
1594 }
1595 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_PTR , key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
1596 return FALSE; /* key registered with another data type */
1597 }
1598
1599 int retcode = FALSE;
1600 node_ptr = _ht_new_string_node(table, key, string);
1601 if (node_ptr) {
1602 HASH_VALUE index = (node_ptr->hash_value) % (table->size);
1603 retcode = list_push(table->hash_table[index], node_ptr, &_ht_node_destroy);
1604 if (retcode == TRUE) {
1605 table->nb_keys++;
1606 }
1607 }
1608 return retcode;
1609} /*_ht_put_string */
1610
1618int _ht_put_string_ptr(HASH_TABLE* table, const char* key, char* string) {
1619 HASH_NODE* node_ptr = NULL;
1620
1621 __n_assert(table, return FALSE);
1622 __n_assert(key, return FALSE);
1623
1624 if ((node_ptr = _ht_get_node(table, key))) {
1625 /* let's check the key isn't already assigned with another data type */
1626 if (node_ptr->type == HASH_STRING) {
1627 Free(node_ptr->data.string);
1628 node_ptr->data.string = string;
1629 return TRUE;
1630 }
1631 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_PTR , key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
1632 return FALSE; /* key registered with another data type */
1633 }
1634
1635 int retcode = FALSE;
1636 node_ptr = _ht_new_string_node(table, key, string);
1637 if (node_ptr) {
1638 HASH_VALUE index = (node_ptr->hash_value) % (table->size);
1639 retcode = list_push(table->hash_table[index], node_ptr, &_ht_node_destroy);
1640 if (retcode == TRUE) {
1641 table->nb_keys++;
1642 }
1643 }
1644 return retcode;
1645} /*_ht_put_string_ptr */
1646
1654int _ht_get_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE* val) {
1655 __n_assert(table, return FALSE);
1656 __n_assert(key, return FALSE);
1657 if (strlen(key) == 0)
1658 return FALSE;
1659
1660 HASH_NODE* node = _ht_get_node(table, key);
1661
1662 if (!node)
1663 return FALSE;
1664
1665 if (node->type != HASH_INT) {
1666 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_INT, key is type %s", key, ht_node_type(node));
1667 return FALSE;
1668 }
1669
1670 (*val) = node->data.ival;
1671
1672 return TRUE;
1673} /* _ht_get_int() */
1674
1682int _ht_get_double(HASH_TABLE* table, const char* key, double* val) {
1683 __n_assert(table, return FALSE);
1684 __n_assert(key, return FALSE);
1685
1686 if (strlen(key) == 0)
1687 return FALSE;
1688
1689 HASH_NODE* node = _ht_get_node(table, key);
1690
1691 if (!node)
1692 return FALSE;
1693
1694 if (node->type != HASH_DOUBLE) {
1695 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_DOUBLE, key is type %s", key, ht_node_type(node));
1696 return FALSE;
1697 }
1698
1699 (*val) = node->data.fval;
1700
1701 return TRUE;
1702} /* _ht_get_double()*/
1703
1711int _ht_get_ptr(HASH_TABLE* table, const char* key, void** val) {
1712 __n_assert(table, return FALSE);
1713 __n_assert(key, return FALSE);
1714 if (strlen(key) == 0)
1715 return FALSE;
1716
1717 HASH_NODE* node = _ht_get_node(table, key);
1718 if (!node)
1719 return FALSE;
1720
1721 if (node->type != HASH_PTR) {
1722 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_PTR, key is type %s", key, ht_node_type(node));
1723 return FALSE;
1724 }
1725
1726 (*val) = node->data.ptr;
1727
1728 return TRUE;
1729} /* _ht_get_ptr() */
1730
1738int _ht_get_string(HASH_TABLE* table, const char* key, char** val) {
1739 __n_assert(table, return FALSE);
1740 __n_assert(key, return FALSE);
1741 if (strlen(key) == 0)
1742 return FALSE;
1743
1744 HASH_NODE* node = _ht_get_node(table, key);
1745 if (!node)
1746 return FALSE;
1747
1748 if (node->type != HASH_STRING) {
1749 n_log(LOG_ERR, "Can't get key[\"%s\"] of type HASH_STRING, key is type %s", key, ht_node_type(node));
1750 return FALSE;
1751 }
1752
1753 (*val) = node->data.string;
1754
1755 return TRUE;
1756} /* _ht_get_string() */
1757
1764int _ht_remove(HASH_TABLE* table, const char* key) {
1765 HASH_VALUE hash_value[2] = {0, 0};
1766 size_t index = 0;
1767
1768 HASH_NODE* node_ptr = NULL;
1769 LIST_NODE* node_to_kill = NULL;
1770
1771 __n_assert(table, return FALSE);
1772 __n_assert(key, return FALSE);
1773 if (strlen(key) == 0)
1774 return FALSE;
1775
1776 MurmurHash(key, strlen(key), table->seed, &hash_value);
1777 index = (hash_value[0]) % (table->size);
1778
1779 if (!table->hash_table[index]->start) {
1780 n_log(LOG_ERR, "Can't remove key[\"%s\"], table is empty", key);
1781 return FALSE;
1782 }
1783
1784 list_foreach(list_node, table->hash_table[index]) {
1785 node_ptr = (HASH_NODE*)list_node->ptr;
1786 /* if we found the same */
1787 if (!strcmp(key, node_ptr->key)) {
1788 node_to_kill = list_node;
1789 break;
1790 }
1791 }
1792 if (node_to_kill) {
1793 node_ptr = remove_list_node(table->hash_table[index], node_to_kill, HASH_NODE);
1794 _ht_node_destroy(node_ptr);
1795
1796 table->nb_keys--;
1797
1798 return TRUE;
1799 }
1800 n_log(LOG_ERR, "Can't delete key[\"%s\"]: inexisting key", key);
1801 return FALSE;
1802} /* ht_remove() */
1803
1812 HASH_NODE* hash_node = NULL;
1813
1814 __n_assert(table, return FALSE);
1815
1816 HASH_VALUE index = 0;
1817 for (index = 0; index < table->size; index++) {
1818 while (table->hash_table[index] && table->hash_table[index]->start) {
1819 hash_node = remove_list_node(table->hash_table[index], table->hash_table[index]->start, HASH_NODE);
1820 _ht_node_destroy(hash_node);
1821 }
1822 }
1823 table->nb_keys = 0;
1824 return TRUE;
1825} /* empty_ht */
1826
1835 __n_assert(table && (*table), n_log(LOG_ERR, "Can't destroy table: already NULL"); return FALSE);
1836
1837 if ((*table)->hash_table) {
1838 // empty_ht( (*table) );
1839
1840 HASH_VALUE it = 0;
1841 for (it = 0; it < (*table)->size; it++) {
1842 if ((*table)->hash_table[it])
1843 list_destroy(&(*table)->hash_table[it]);
1844 }
1845 Free((*table)->hash_table);
1846 }
1847 Free((*table));
1848 return TRUE;
1849} /* _destroy_ht */
1850
1857void _ht_print(HASH_TABLE* table) {
1858 __n_assert(table, return);
1859 __n_assert(table->hash_table, return);
1860 ht_foreach(node, table) {
1861 printf("key:%s node:%s\n", ((HASH_NODE*)node->ptr)->key, ((HASH_NODE*)node->ptr)->key);
1862 }
1863
1864 return;
1865} /* _ht_print(...) */
1866
1875LIST* _ht_search(HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node)) {
1876 __n_assert(table, return NULL);
1877
1878 LIST* results = new_generic_list(MAX_LIST_ITEMS);
1879 __n_assert(results, return NULL);
1880
1881 ht_foreach(node, table) {
1882 HASH_NODE* hnode = (HASH_NODE*)node->ptr;
1883 if (node_is_matching(hnode) == TRUE) {
1884 list_push(results, strdup(hnode->key), &free);
1885 }
1886 }
1887
1888 if (results->nb_items < 1)
1889 list_destroy(&results);
1890
1891 return results;
1892} /* _ht_search(...) */
1893
1894/************ HASH_TABLES FUNCTION POINTERS AND COMMON TABLE TYPE FUNCS ************/
1895
1902HASH_TABLE* new_ht_trie(size_t alphabet_length, size_t alphabet_offset) {
1903 HASH_TABLE* table = NULL;
1904
1905 Malloc(table, HASH_TABLE, 1);
1906 __n_assert(table, n_log(LOG_ERR, "Error allocating HASH_TABLE *table"); return NULL);
1907
1908 table->size = 0;
1909 table->seed = 0;
1910 table->nb_keys = 0;
1911 errno = 0;
1912 table->hash_table = NULL;
1913
1914 table->ht_put_int = _ht_put_int_trie;
1919 table->ht_get_int = _ht_get_int_trie;
1923 table->ht_remove = _ht_remove_trie;
1924 table->ht_search = _ht_search_trie;
1925 table->empty_ht = _empty_ht_trie;
1927 table->ht_print = _ht_print_trie;
1928
1929 table->alphabet_length = alphabet_length;
1930 table->alphabet_offset = alphabet_offset;
1931
1932 table->root = _ht_new_node_trie(table, '\0');
1933 if (!table->root) {
1934 n_log(LOG_ERR, "Couldn't allocate new_ht_trie with alphabet_length of %zu and alphabet offset of %d", alphabet_length, alphabet_offset);
1935 Free(table);
1936 return NULL;
1937 }
1938 table->mode = HASH_TRIE;
1939
1940 return table;
1941} /* new_ht_trie */
1942
1948HASH_TABLE* new_ht(size_t size) {
1949 HASH_TABLE* table = NULL;
1950
1951 if (size < 1) {
1952 n_log(LOG_ERR, "Invalide size %d for new_ht()", size);
1953 return NULL;
1954 }
1955 Malloc(table, HASH_TABLE, 1);
1956 __n_assert(table, n_log(LOG_ERR, "Error allocating HASH_TABLE *table"); return NULL);
1957
1958 table->size = size;
1959 table->seed = (uint32_t)rand() % 100000;
1960 table->nb_keys = 0;
1961 errno = 0;
1962 Malloc(table->hash_table, LIST*, size);
1963 // table -> hash_table = (LIST **)calloc( size, sizeof( LIST *) );
1964 __n_assert(table->hash_table, n_log(LOG_ERR, "Can't allocate table -> hash_table with size %d !", size); Free(table); return NULL);
1965
1966 size_t it = 0;
1967 for (it = 0; it < size; it++) {
1968 table->hash_table[it] = new_generic_list(MAX_LIST_ITEMS);
1969 // if no valid table then unroll previsouly created slots
1970 if (!table->hash_table[it]) {
1971 n_log(LOG_ERR, "Can't allocate table -> hash_table[ %d ] !", it);
1972 size_t it_delete = 0;
1973 for (it_delete = 0; it_delete < it; it_delete++) {
1974 list_destroy(&table->hash_table[it_delete]);
1975 }
1976 Free(table->hash_table);
1977 Free(table);
1978 return NULL;
1979 }
1980 }
1981 table->mode = HASH_CLASSIC;
1982
1983 table->ht_put_int = _ht_put_int;
1985 table->ht_put_ptr = _ht_put_ptr;
1988 table->ht_get_int = _ht_get_int;
1991 table->ht_get_ptr = _ht_get_ptr;
1992 table->ht_get_node = _ht_get_node;
1993 table->ht_remove = _ht_remove;
1994 table->ht_search = _ht_search;
1995 table->empty_ht = _empty_ht;
1996 table->destroy_ht = _destroy_ht;
1997 table->ht_print = _ht_print;
1998
1999 return table;
2000} /* new_ht(...) */
2001
2008HASH_NODE* ht_get_node(HASH_TABLE* table, const char* key) {
2009 __n_assert(table, return FALSE);
2010 __n_assert(key, return FALSE);
2011 return table->ht_get_node(table, key);
2012} /*ht_get_node(...) */
2013
2021int ht_get_double(HASH_TABLE* table, const char* key, double* val) {
2022 __n_assert(table, return FALSE);
2023 __n_assert(key, return FALSE);
2024 return table->ht_get_double(table, key, val);
2025} /* ht_get_double(...) */
2026
2034int ht_get_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE* val) {
2035 __n_assert(table, return FALSE);
2036 __n_assert(key, return FALSE);
2037 return table->ht_get_int(table, key, val);
2038} /* ht_get_int(...) */
2039
2047int ht_get_ptr(HASH_TABLE* table, const char* key, void** val) {
2048 __n_assert(table, return FALSE);
2049 __n_assert(key, return FALSE);
2050 return table->ht_get_ptr(table, key, &(*val));
2051} /* ht_get_ptr(...) */
2052
2060int ht_get_string(HASH_TABLE* table, const char* key, char** val) {
2061 __n_assert(table, return FALSE);
2062 __n_assert(key, return FALSE);
2063 return table->ht_get_string(table, key, val);
2064} /* ht_get_string(...) */
2065
2073int ht_put_double(HASH_TABLE* table, const char* key, double value) {
2074 __n_assert(table, return FALSE);
2075 __n_assert(key, return FALSE);
2076 return table->ht_put_double(table, key, value);
2077} /* ht_put_double(...) */
2078
2086int ht_put_int(HASH_TABLE* table, const char* key, HASH_INT_TYPE value) {
2087 __n_assert(table, return FALSE);
2088 __n_assert(key, return FALSE);
2089 return table->ht_put_int(table, key, value);
2090} /* ht_put_int(...) */
2091
2100int ht_put_ptr(HASH_TABLE* table, const char* key, void* ptr, void (*destructor)(void* ptr)) {
2101 __n_assert(table, return FALSE);
2102 __n_assert(key, return FALSE);
2103 return table->ht_put_ptr(table, key, ptr, destructor);
2104} /* ht_put_ptr(...) */
2105
2113int ht_put_string(HASH_TABLE* table, const char* key, char* string) {
2114 __n_assert(table, return FALSE);
2115 __n_assert(key, return FALSE);
2116 return table->ht_put_string(table, key, string);
2117} /* ht_put_string(...) */
2118
2126int ht_put_string_ptr(HASH_TABLE* table, const char* key, char* string) {
2127 __n_assert(table, return FALSE);
2128 __n_assert(key, return FALSE);
2129 return table->ht_put_string_ptr(table, key, string);
2130} /* ht_put_string_ptr(...) */
2131
2138int ht_remove(HASH_TABLE* table, const char* key) {
2139 __n_assert(table, return FALSE);
2140 __n_assert(key, return FALSE);
2141 return table->ht_remove(table, key);
2142} /* ht_remove(...) */
2143
2148void ht_print(HASH_TABLE* table) {
2149 __n_assert(table, return);
2150 table->ht_print(table);
2151 return;
2152} /* ht_print(...) */
2153
2160LIST* ht_search(HASH_TABLE* table, int (*node_is_matching)(HASH_NODE* node)) {
2161 __n_assert(table, return FALSE);
2162 return table->ht_search(table, node_is_matching);
2163} /* ht_search(...) */
2164
2171 __n_assert(table, return FALSE);
2172 return table->empty_ht(table);
2173} /* empty_ht(...) */
2174
2181 __n_assert((*table), return FALSE);
2182 return (*table)->destroy_ht(table);
2183} /* destroy_ht(...) */
2184
2192 __n_assert(table, return NULL);
2193 __n_assert(table->mode == HASH_CLASSIC, return NULL);
2194
2195 size_t index = 0;
2196 HASH_NODE* node_ptr = NULL;
2197
2198 index = (hash_value) % (table->size);
2199 if (!table->hash_table[index]->start) {
2200 return NULL;
2201 }
2202
2203 list_foreach(list_node, table->hash_table[index]) {
2204 node_ptr = (HASH_NODE*)list_node->ptr;
2205 if (hash_value == node_ptr->hash_value) {
2206 return node_ptr;
2207 }
2208 }
2209 return NULL;
2210} /* ht_get_node_ex() */
2211
2219int ht_get_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void** val) {
2220 __n_assert(table, return FALSE);
2221 __n_assert(table->mode == HASH_CLASSIC, return FALSE);
2222
2223 HASH_NODE* node = ht_get_node_ex(table, hash_value);
2224 if (!node)
2225 return FALSE;
2226
2227 if (node->type != HASH_PTR) {
2228 n_log(LOG_ERR, "Can't get key[\"%lld\"] of type HASH_PTR, key is type %s", hash_value, ht_node_type(node));
2229 return FALSE;
2230 }
2231
2232 (*val) = node->data.ptr;
2233
2234 return TRUE;
2235} /* ht_get_ptr_ex() */
2236
2245int ht_put_ptr_ex(HASH_TABLE* table, HASH_VALUE hash_value, void* val, void (*destructor)(void* ptr)) {
2246 __n_assert(table, return FALSE);
2247 __n_assert(table->mode == HASH_CLASSIC, return FALSE);
2248
2249 size_t index = 0;
2250 HASH_NODE* new_hash_node = NULL;
2251 HASH_NODE* node_ptr = NULL;
2252
2253 index = (hash_value) % (table->size);
2254
2255 /* we have some nodes here. Let's check if the key already exists */
2256 list_foreach(list_node, table->hash_table[index]) {
2257 node_ptr = (HASH_NODE*)list_node->ptr;
2258 /* if we found the same key we just replace the value and return */
2259 if (hash_value == node_ptr->hash_value) {
2260 /* let's check the key isn't already assigned with another data type */
2261 if (node_ptr->type == HASH_PTR) {
2262 if (list_node->destroy_func) {
2263 list_node->destroy_func(node_ptr->data.ptr);
2264 node_ptr->data.ptr = val;
2265 list_node->destroy_func = destructor;
2266 }
2267 return TRUE;
2268 }
2269 n_log(LOG_ERR, "Can't add key[\"%s\"] with type HASH_PTR , key already exist with type %s", node_ptr->key, ht_node_type(node_ptr));
2270 return FALSE; /* key registered with another data type */
2271 }
2272 }
2273
2274 Malloc(new_hash_node, HASH_NODE, 1);
2275 __n_assert(new_hash_node, n_log(LOG_ERR, "Could not allocate new_hash_node"); return FALSE);
2276
2277 new_hash_node->key = NULL;
2278 new_hash_node->hash_value = hash_value;
2279 new_hash_node->data.ptr = val;
2280 new_hash_node->type = HASH_PTR;
2281 new_hash_node->destroy_func = destructor;
2282
2283 table->nb_keys++;
2284
2285 return list_push(table->hash_table[index], new_hash_node, &_ht_node_destroy);
2286} /* ht_put_ptr_ex() */
2287
2294int ht_remove_ex(HASH_TABLE* table, HASH_VALUE hash_value) {
2295 __n_assert(table, return FALSE);
2296 __n_assert(table->mode == HASH_CLASSIC, return FALSE);
2297
2298 size_t index = 0;
2299 HASH_NODE* node_ptr = NULL;
2300 LIST_NODE* node_to_kill = NULL;
2301
2302 index = (hash_value) % (table->size);
2303 if (!table->hash_table[index]->start) {
2304 n_log(LOG_ERR, "Can't remove key[\"%d\"], table is empty", hash_value);
2305 return FALSE;
2306 }
2307
2308 list_foreach(list_node, table->hash_table[index]) {
2309 node_ptr = (HASH_NODE*)list_node->ptr;
2310 /* if we found the same */
2311 if (hash_value == node_ptr->hash_value) {
2312 node_to_kill = list_node;
2313 break;
2314 }
2315 }
2316 if (node_to_kill) {
2317 node_ptr = remove_list_node(table->hash_table[index], node_to_kill, HASH_NODE);
2318 _ht_node_destroy(node_ptr);
2319
2320 table->nb_keys--;
2321
2322 return TRUE;
2323 }
2324 n_log(LOG_ERR, "Can't delete key[\"%d\"]: inexisting key", hash_value);
2325 return FALSE;
2326} /* ht_remove_ex() */
2327
2335LIST* ht_get_completion_list(HASH_TABLE* table, const char* keybud, size_t max_results) {
2336 __n_assert(table, return NULL);
2337 __n_assert(keybud, return NULL);
2338
2339 LIST* results = new_generic_list(max_results);
2340 if (table->mode == HASH_TRIE) {
2341 HASH_NODE* node = _ht_get_node_trie(table, keybud);
2342 if (node) {
2343 if (list_push(results, strdup(keybud), &free) == TRUE) {
2344 _ht_depth_first_search(node, results);
2345 }
2346 } else {
2347 node = table->root;
2348 for (size_t it = 0; it < table->alphabet_length; it++) {
2349 if (node->children[it]) {
2350 char new_keybud[3] = "";
2351 new_keybud[0] = (char)(it + table->alphabet_offset);
2352 list_push(results, strdup(new_keybud), &free);
2353 }
2354 }
2355 }
2356 } else if (table->mode == HASH_CLASSIC) {
2357 ht_foreach(node, table) {
2358 HASH_NODE* hnode = (HASH_NODE*)node->ptr;
2359 if (strncasecmp(keybud, hnode->key, strlen(keybud)) == 0) {
2360 char* key = strdup(hnode->key);
2361 if (list_push(results, key, &free) == FALSE) {
2362 // n_log( LOG_ERR ,"not enough space in list or memory error, key %s not pushed !" , key );
2363 Free(key);
2364 }
2365 }
2366 }
2367 } else {
2368 n_log(LOG_ERR, "unsupported mode %d", table->mode);
2369 return NULL;
2370 }
2371 if (results && results->nb_items < 1)
2372 list_destroy(&results);
2373 return results;
2374} /* ht_get_completion_list(...) */
2375
2381int is_prime(size_t nb) {
2382 /* quick test for first primes */
2383 if (nb <= 1) return FALSE;
2384 if (nb <= 3) return TRUE;
2385
2386 /* skip middle five numbers in below loop */
2387 if ((nb % 2 == 0) || (nb % 3 == 0))
2388 return FALSE;
2389
2390 /* looping */
2391 for (size_t it = 5; it * it <= nb; it = it + 6) {
2392 if ((nb % it == 0) || (nb % (it + 2) == 0))
2393 return FALSE;
2394 }
2395 return TRUE;
2396} /* is_prime() */
2397
2403size_t next_prime(size_t nb) {
2404 if (nb <= 1)
2405 return 2;
2406
2407 size_t next_prime = nb;
2408 do {
2409 next_prime++;
2410 } while (is_prime(next_prime) == FALSE);
2411
2412 return next_prime;
2413} /* next_prime() */
2414
2421 __n_assert(table, return FALSE);
2422 __n_assert(table->mode == HASH_CLASSIC, return FALSE);
2423
2424 if (table->size == 0) return FALSE;
2425
2426 size_t nb_collisionned_lists = 0;
2427
2428 for (size_t hash_it = 0; hash_it < table->size; hash_it++) {
2429 if (table->hash_table[hash_it] && table->hash_table[hash_it]->nb_items > 1) {
2430 nb_collisionned_lists++;
2431 }
2432 }
2433 size_t collision_percentage = (100 * nb_collisionned_lists) / table->size;
2434 return (int)collision_percentage;
2435} /* ht_get_table_collision_percentage() */
2436
2443 __n_assert(table, return 0);
2444
2445 size_t optimum_size = (size_t)((double)table->nb_keys * 1.3);
2446 if (is_prime(optimum_size) != TRUE)
2447 optimum_size = next_prime(optimum_size);
2448 return optimum_size;
2449} /* ht_get_optimal_size() */
2450
2457int ht_resize(HASH_TABLE** table, size_t size) {
2458 __n_assert((*table), return FALSE);
2459
2460 if (size < 1) {
2461 n_log(LOG_ERR, "invalid size %d for hash table %p", size, (*table));
2462 return FALSE;
2463 }
2464 HT_FOREACH(node, (*table), { node->need_rehash = 1; });
2465
2466 if (size > (*table)->size) {
2467 Realloc((*table)->hash_table, LIST*, size);
2468 if (!(*table)->hash_table) {
2469 n_log(LOG_ERR, "Realloc did not augment the size the table !");
2470 } else {
2471 for (size_t it = (*table)->size; it < size; it++) {
2472 (*table)->hash_table[it] = new_generic_list(MAX_LIST_ITEMS);
2473 // if no valid table then unroll previsouly created slots
2474 if (!(*table)->hash_table[it]) {
2475 n_log(LOG_ERR, "Can't allocate table -> hash_table[ %d ] !", it);
2476 for (size_t it_delete = 0; it_delete < it; it_delete++) {
2477 list_destroy(&(*table)->hash_table[it_delete]);
2478 }
2479 Free((*table)->hash_table);
2480 Free((*table));
2481 return FALSE;
2482 }
2483 }
2484 for (size_t it = 0; it < size; it++) {
2485 if (((*table)->hash_table[it])) {
2486 while ((*table)->hash_table[it]->start) {
2487 HASH_NODE* hash_node = (HASH_NODE*)(*table)->hash_table[it]->start->ptr;
2488 if (hash_node->need_rehash == 0)
2489 break;
2490 hash_node->need_rehash = 0;
2491 LIST_NODE* node = list_node_shift((*table)->hash_table[it]);
2492 node->next = node->prev = NULL;
2493 size_t index = (hash_node->hash_value) % (size);
2494 list_node_push((*table)->hash_table[index], node);
2495 }
2496 }
2497 }
2498 }
2499 } else {
2500 for (size_t it = 0; it < (*table)->size; it++) {
2501 if (((*table)->hash_table[it])) {
2502 while ((*table)->hash_table[it]->start) {
2503 HASH_NODE* hash_node = (HASH_NODE*)(*table)->hash_table[it]->start->ptr;
2504 if (hash_node->need_rehash == 0)
2505 break;
2506 hash_node->need_rehash = 0;
2507 LIST_NODE* node = list_node_shift((*table)->hash_table[it]);
2508 node->next = node->prev = NULL;
2509 size_t index = (hash_node->hash_value) % (size);
2510 list_node_push((*table)->hash_table[index], node);
2511 }
2512 }
2513 }
2514 for (size_t it = size; it < (*table)->size; it++) {
2515 list_destroy(&(*table)->hash_table[it]);
2516 }
2517 Realloc((*table)->hash_table, LIST*, size);
2518 if (!(*table)->hash_table) {
2519 n_log(LOG_ERR, "Realloc did not reduce the resize the table !");
2520 }
2521 }
2522 (*table)->size = size;
2523
2524 return TRUE;
2525} /* ht_resize() */
2526
2533 __n_assert((*table), return FALSE);
2534
2535 size_t optimal_size = ht_get_optimal_size((*table));
2536 if (optimal_size == FALSE) {
2537 return FALSE;
2538 }
2539
2540 int collision_percentage = ht_get_table_collision_percentage((*table));
2541 if (collision_percentage == FALSE)
2542 return FALSE;
2543
2544 int resize_result = ht_resize(&(*table), optimal_size);
2545 if (resize_result == FALSE) {
2546 return FALSE;
2547 }
2548
2549 collision_percentage = ht_get_table_collision_percentage((*table));
2550 if (collision_percentage == FALSE) {
2551 return FALSE;
2552 }
2553
2554 return TRUE;
2555} /* ht_optimize() */
#define FreeNoLog(__ptr)
Free Handler without log.
Definition n_common.h:251
#define FALL_THROUGH
fall through macro for switch cases, avoid warning at compilation
Definition n_common.h:55
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:187
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:258
#define FORCE_INLINE
FORCE_INLINE portable macro.
Definition n_common.h:147
#define Realloc(__ptr, __struct, __size)
Realloc Handler to get errors.
Definition n_common.h:213
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:242
int(* ht_put_int)(struct HASH_TABLE *table, const char *key, int64_t val)
put an integer
Definition n_hash.h:134
size_t alphabet_length
HASH_TRIE mode: size of alphabet and so size of children allocated array.
Definition n_hash.h:110
int need_rehash
flag to mark a node for rehash
Definition n_hash.h:106
HASH_NODE *(* ht_get_node)(struct HASH_TABLE *table, const char *key)
get HASH_NODE at 'key' from table
Definition n_hash.h:132
char key_id
key id of the node if any
Definition n_hash.h:94
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:150
int(* ht_put_string)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string
Definition n_hash.h:140
char * key
string key of the node if any, else NULL
Definition n_hash.h:92
int64_t ival
integral type
Definition n_hash.h:80
int is_leaf
HASH_TRIE mode: does it have a value.
Definition n_hash.h:104
HASH_NODE * root
HASH_TRIE mode: Start of tree.
Definition n_hash.h:124
void * ptr
pointer type
Definition n_hash.h:84
union HASH_DATA data
data inside the node
Definition n_hash.h:100
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:148
int type
type of the node
Definition n_hash.h:98
int(* empty_ht)(struct HASH_TABLE *table)
empty a hash table.
Definition n_hash.h:156
LIST ** hash_table
HASH_CLASSIC mode: preallocated hash table.
Definition n_hash.h:122
size_t alphabet_offset
HASH_TRIE mode: offset to deduce to individual key digits.
Definition n_hash.h:128
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:146
size_t alphabet_length
HASH_TRIE mode: size of the alphabet.
Definition n_hash.h:126
unsigned int mode
hashing mode, murmurhash and classic HASH_MURMUR, or HASH_TRIE
Definition n_hash.h:130
size_t seed
table's seed
Definition n_hash.h:120
int(* destroy_ht)(struct HASH_TABLE **table)
destroy a hash table
Definition n_hash.h:158
int(* ht_put_string_ptr)(struct HASH_TABLE *table, const char *key, char *val)
put an char *string pointer
Definition n_hash.h:142
int(* ht_remove)(struct HASH_TABLE *table, const char *key)
remove given's key node from the table
Definition n_hash.h:152
void(* ht_print)(struct HASH_TABLE *table)
print table
Definition n_hash.h:160
char * string
char *type
Definition n_hash.h:86
int(* ht_put_double)(struct HASH_TABLE *table, const char *key, double val)
put a double
Definition n_hash.h:136
struct HASH_NODE ** children
HASH_TRIE mode: pointers to children.
Definition n_hash.h:108
HASH_VALUE hash_value
numeric key of the node if any, else < 0
Definition n_hash.h:96
double fval
double type
Definition n_hash.h:82
size_t size
size of the hash table
Definition n_hash.h:116
int(* ht_put_ptr)(struct HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr))
put a a pointer
Definition n_hash.h:138
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:144
size_t nb_keys
total number of used keys in the table
Definition n_hash.h:118
LIST *(* ht_search)(struct HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
search elements given an expression
Definition n_hash.h:154
void(* destroy_func)(void *ptr)
destroy_func
Definition n_hash.h:102
int ht_get_ptr(HASH_TABLE *table, const char *key, void **val)
get pointer at 'key' from 'table'
Definition n_hash.c:2047
#define ht_foreach(__ITEM_, __HASH_)
ForEach macro helper (classic / old)
Definition n_hash.h:168
int ht_put_ptr_ex(HASH_TABLE *table, HASH_VALUE hash_value, void *val, void(*destructor)(void *ptr))
put a pointer value with given key in the targeted hash table (HASH_CLASSIC only)
Definition n_hash.c:2245
char * ht_node_type(HASH_NODE *node)
get the type of a node , text version
Definition n_hash.c:1271
LIST * ht_search(HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
seach table for matching nodes
Definition n_hash.c:2160
int destroy_ht(HASH_TABLE **table)
empty a table and destroy it
Definition n_hash.c:2180
int ht_remove(HASH_TABLE *table, const char *key)
remove and delete node at key in table
Definition n_hash.c:2138
HASH_NODE * ht_get_node_ex(HASH_TABLE *table, HASH_VALUE hash_value)
return the associated key's node inside the hash_table (HASH_CLASSIC only)
Definition n_hash.c:2191
#define HASH_PTR
value of pointer type inside the hash node
Definition n_hash.h:56
HASH_TABLE * new_ht(size_t size)
Create a hash table with the given size.
Definition n_hash.c:1948
#define MurmurHash(__key, __len, __seed, __out)
Murmur hash macro helper 64 bits.
Definition n_hash.h:70
int ht_get_table_collision_percentage(HASH_TABLE *table)
get table collision percentage (HASH_CLASSIC mode only)
Definition n_hash.c:2420
int ht_get_double(HASH_TABLE *table, const char *key, double *val)
get double at 'key' from 'table'
Definition n_hash.c:2021
#define HASH_DOUBLE
value of double type inside the hash node
Definition n_hash.h:52
int empty_ht(HASH_TABLE *table)
empty a table
Definition n_hash.c:2170
#define HASH_STRING
value of char * type inside the hash node
Definition n_hash.h:54
void ht_print(HASH_TABLE *table)
print contents of table
Definition n_hash.c:2148
LIST * ht_get_completion_list(HASH_TABLE *table, const char *keybud, size_t max_results)
get next matching keys in table tree
Definition n_hash.c:2335
size_t HASH_VALUE
type of a HASH_VALUE
Definition n_hash.h:75
int ht_put_double(HASH_TABLE *table, const char *key, double value)
put a double value with given key in the targeted hash table
Definition n_hash.c:2073
size_t ht_get_optimal_size(HASH_TABLE *table)
get optimal array size based on nb=(number_of_key*1.3) && if( !isprime(nb) )nb=nextprime(nb) (HASH_CL...
Definition n_hash.c:2442
int ht_get_string(HASH_TABLE *table, const char *key, char **val)
get string at 'key' from 'table'
Definition n_hash.c:2060
int ht_put_string(HASH_TABLE *table, const char *key, char *string)
put a string value (copy/dup) with given key in the targeted hash table
Definition n_hash.c:2113
int ht_resize(HASH_TABLE **table, size_t size)
rehash table according to size (HASH_CLASSIC mode only)
Definition n_hash.c:2457
void MurmurHash3_x86_128(const void *key, const size_t len, const uint32_t seed, void *out)
MurmurHash3 was written by Austin Appleby, and is placed in the public domain.
Definition n_hash.c:981
void MurmurHash3_x64_128(const void *key, const size_t len, const uint64_t seed, void *out)
MurmurHash3 was written by Austin Appleby, and is placed in the public domain.
Definition n_hash.c:1149
int ht_remove_ex(HASH_TABLE *table, HASH_VALUE hash_value)
Remove a key from a hash table (HASH_CLASSIC only)
Definition n_hash.c:2294
#define HASH_CLASSIC
Murmur hash using hash key string, hash key numeric value, index table with lists of elements.
Definition n_hash.h:60
HASH_NODE * ht_get_node(HASH_TABLE *table, const char *key)
get node at 'key' from 'table'
Definition n_hash.c:2008
HASH_TABLE * new_ht_trie(size_t alphabet_length, size_t alphabet_offset)
create a TRIE hash table with the alphabet_size, each key value beeing decreased by alphabet_offset
Definition n_hash.c:1902
#define HASH_TRIE
TRIE tree using hash key string.
Definition n_hash.h:62
int ht_put_ptr(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr))
put a pointer to the string value with given key in the targeted hash table
Definition n_hash.c:2100
int ht_optimize(HASH_TABLE **table)
try an automatic optimization of the table
Definition n_hash.c:2532
#define HASH_INT
compatibility with existing rot func
Definition n_hash.h:50
void MurmurHash3_x86_32(const void *key, const size_t len, const uint32_t seed, void *out)
MurmurHash3 was written by Austin Appleby, and is placed in the public domain.
Definition n_hash.c:923
int ht_put_string_ptr(HASH_TABLE *table, const char *key, char *string)
put a string value (pointer) with given key in the targeted hash table
Definition n_hash.c:2126
#define HT_FOREACH(__ITEM_, __HASH_,...)
ForEach macro helper.
Definition n_hash.h:192
int ht_get_ptr_ex(HASH_TABLE *table, HASH_VALUE hash_value, void **val)
Retrieve a pointer value in the hash table, at the given key.
Definition n_hash.c:2219
#define HASH_UNKNOWN
value of unknow type inside the hash node
Definition n_hash.h:58
structure of a hash table node
Definition n_hash.h:90
structure of a hash table
Definition n_hash.h:114
size_t nb_max_items
maximum number of item in the list.
Definition n_list.h:43
struct LIST_NODE * prev
pointer to the previous node
Definition n_list.h:34
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:46
size_t nb_items
number of item currently in the list
Definition n_list.h:41
struct LIST_NODE * next
pointer to the next node
Definition n_list.h:32
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:199
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper.
Definition n_list.h:65
#define remove_list_node(__LIST_, __NODE_, __TYPE_)
Remove macro helper for void pointer casting.
Definition n_list.h:76
LIST_NODE * list_node_shift(LIST *list)
Get a LIST_NODE pointer from the start of the list.
Definition n_list.c:145
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:518
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:55
int list_node_push(LIST *list, LIST_NODE *node)
Add a filled node to the end of the list.
Definition n_list.c:96
Structure of a generic LIST container.
Definition n_list.h:39
Structure of a generic list node.
Definition n_list.h:24
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:69
#define LOG_DEBUG
debug-level messages
Definition n_log.h:64
#define LOG_ERR
error conditions
Definition n_log.h:56
Common headers and low-level functions & define.
void _ht_node_destroy(void *node)
destroy a HASH_NODE by first calling the HASH_NODE destructor
Definition n_hash.c:88
int _destroy_ht(HASH_TABLE **table)
Free and set the table to NULL.
Definition n_hash.c:1834
int _ht_get_double(HASH_TABLE *table, const char *key, double *val)
Retrieve a double value in the hash table, at the given key.
Definition n_hash.c:1682
HASH_NODE * _ht_new_double_node(HASH_TABLE *table, const char *key, double value)
node creation, HASH_CLASSIC mode
Definition n_hash.c:1379
int _ht_put_double(HASH_TABLE *table, const char *key, double value)
put a double value with given key in the targeted hash table
Definition n_hash.c:1508
HASH_NODE * _ht_new_string_ptr_node(HASH_TABLE *table, const char *key, char *value)
node creation, HASH_CLASSIC mode, pointer to string value
Definition n_hash.c:1426
int _ht_put_string_trie(HASH_TABLE *table, const char *key, char *string)
put a duplicate of the string value with given key in the targeted hash table [TRIE HASH TABLE)
Definition n_hash.c:357
int _ht_get_ptr(HASH_TABLE *table, const char *key, void **val)
Retrieve a pointer value in the hash table, at the given key.
Definition n_hash.c:1711
HASH_NODE * _ht_new_node_trie(HASH_TABLE *table, const char key)
node creation, HASH_CLASSIC mode
Definition n_hash.c:32
int _ht_depth_first_search(HASH_NODE *node, LIST *results)
recursive, helper for ht_get_completion_list, get the list of leaf starting from node
Definition n_hash.c:790
void _ht_print_trie(HASH_TABLE *table)
Generic print func call for trie trees.
Definition n_hash.c:727
int _ht_get_string_trie(HASH_TABLE *table, const char *key, char **val)
Retrieve an char *string value in the hash table, at the given key.
Definition n_hash.c:604
void _ht_print_trie_helper(HASH_TABLE *table, HASH_NODE *node)
Recursive function to print trie tree's keys and values.
Definition n_hash.c:693
size_t _ht_check_trie_divergence(HASH_TABLE *table, const char *key)
check and return branching index in key if any
Definition n_hash.c:123
HASH_NODE * _ht_get_node_trie(HASH_TABLE *table, const char *key)
retrieve a HASH_NODE at key from table
Definition n_hash.c:515
int _ht_put_string(HASH_TABLE *table, const char *key, char *string)
put a null terminated char *string with given key in the targeted hash table (copy of string)
Definition n_hash.c:1582
HASH_NODE * _ht_new_ptr_node(HASH_TABLE *table, const char *key, void *value, void(*destructor)(void *ptr))
node creation, HASH_CLASSIC mode, pointer to string value
Definition n_hash.c:1449
int _ht_put_string_ptr_trie(HASH_TABLE *table, const char *key, char *string)
put a pointer to the string value with given key in the targeted hash table [TRIE HASH TABLE)
Definition n_hash.c:419
int _ht_put_ptr(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr))
put a pointer value with given key in the targeted hash table
Definition n_hash.c:1543
void _ht_print(HASH_TABLE *table)
Generic print func call for classic hash tables.
Definition n_hash.c:1857
HASH_NODE * _ht_new_node(HASH_TABLE *table, const char *key)
node creation, HASH_CLASSIC mode
Definition n_hash.c:1321
char * _ht_find_longest_prefix_trie(HASH_TABLE *table, const char *key)
find the longest prefix string that is not the current key
Definition n_hash.c:158
int _ht_get_ptr_trie(HASH_TABLE *table, const char *key, void **val)
Retrieve a pointer value in the hash table, at the given key.
Definition n_hash.c:632
int _ht_get_string(HASH_TABLE *table, const char *key, char **val)
Retrieve a char *string value in the hash table, at the given key.
Definition n_hash.c:1738
int _empty_ht(HASH_TABLE *table)
Empty a hash table (CLASSIC mode)
Definition n_hash.c:1811
#define BIG_CONSTANT(x)
max unsigned long long
Definition n_hash.c:814
int _ht_is_leaf_node_trie(HASH_TABLE *table, const char *key)
Search a key and tell if it's holding a value (leaf)
Definition n_hash.c:66
int _ht_put_string_ptr(HASH_TABLE *table, const char *key, char *string)
put a null terminated char *string with given key in the targeted hash table (pointer)
Definition n_hash.c:1618
LIST * _ht_search_trie(HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
Search tree's keys and apply a matching func to put results in the list.
Definition n_hash.c:768
int _ht_put_double_trie(HASH_TABLE *table, const char *key, double value)
put a double value with given key in the targeted hash table [TRIE HASH TABLE)
Definition n_hash.c:307
HASH_NODE * _ht_get_node(HASH_TABLE *table, const char *key)
return the associated key's node inside the hash_table
Definition n_hash.c:1288
#define BYTESWAP64(x)
32 bits bytes swap
Definition n_hash.c:845
#define BYTESWAP32(x)
32 bits bytes swap
Definition n_hash.c:841
int _destroy_ht_trie(HASH_TABLE **table)
Free and set the table to NULL (TRIE mode)
Definition n_hash.c:676
int _ht_put_ptr_trie(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr))
put a pointer to the string value with given key in the targeted hash table [TRIE HASH TABLE)
Definition n_hash.c:470
int _empty_ht_trie(HASH_TABLE *table)
Empty a TRIE hash table.
Definition n_hash.c:658
int _ht_get_double_trie(HASH_TABLE *table, const char *key, double *val)
Retrieve an double value in the hash table, at the given key.
Definition n_hash.c:576
int _ht_remove(HASH_TABLE *table, const char *key)
Remove a key from a hash table.
Definition n_hash.c:1764
int _ht_remove_trie(HASH_TABLE *table, const char *key)
Remove a key from a trie table and destroy the node.
Definition n_hash.c:191
LIST * _ht_search(HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
Search hash table's keys and apply a matching func to put results in the list.
Definition n_hash.c:1875
HASH_NODE * _ht_new_string_node(HASH_TABLE *table, const char *key, char *value)
node creation, HASH_CLASSIC mode, strdup of value
Definition n_hash.c:1401
void _ht_search_trie_helper(LIST *results, HASH_NODE *node, int(*node_is_matching)(HASH_NODE *node))
Recursive function to search tree's keys and apply a matching func to put results in the list.
Definition n_hash.c:746
#define ROTL64(x, r)
64 bit rotate left
Definition n_hash.c:810
#define ROTL32(x, r)
32 bit rotate left
Definition n_hash.c:812
Hash functions and table.
Generic log system.
N_STR and string function declaration.