Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_hash.c
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#include "nilorea/n_str.h"
28#include "nilorea/n_log.h"
29#include "nilorea/n_list.h"
30#include "nilorea/n_hash.h"
31
32#define NB_HASH_ELEMENTS 24
33
35typedef struct DATA {
39 int value;
40} DATA;
41
46void destroy_data(void* ptr) {
47 DATA* data = (DATA*)ptr;
48 free_nstr(&data->rnd_str);
49 Free(data);
50}
51
52int main(void) {
54
55 HASH_TABLE* htable = new_ht(NB_HASH_ELEMENTS / 3);
56 LIST* keys_list = new_generic_list(NB_HASH_ELEMENTS + 1);
57 DATA* data = NULL;
58 char* str = NULL;
59
60 n_log(LOG_INFO, "Filling HashTable with %d random elements", NB_HASH_ELEMENTS);
61 for (int it = 0; it < NB_HASH_ELEMENTS; it++) {
62 N_STR* nkey = NULL;
63 int randomizator = rand() % 4;
64 nstrprintf(nkey, "key%d_%d", it, randomizator);
65 switch (randomizator) {
66 default:
67 case 0:
68 ht_put_int(htable, _nstr(nkey), 666);
69 n_log(LOG_INFO, "Put int 666 with key %s", _nstr(nkey));
70 break;
71 case 1:
72 ht_put_double(htable, _nstr(nkey), 3.14);
73 n_log(LOG_INFO, "Put double 3.14 with key %s", _nstr(nkey));
74 break;
75 case 2:
76 Malloc(data, DATA, 1);
77 data->rnd_str = NULL;
78 nstrprintf(data->rnd_str, "%s%d", _nstr(nkey), rand() % 10);
79 data->value = 7;
80 ht_put_ptr(htable, _nstr(nkey), data, &destroy_data, NULL);
81 n_log(LOG_INFO, "Put ptr rnd_str %s value %d with key %s", _nstr(data->rnd_str), data->value, _nstr(nkey));
82 break;
83 case 3:
84 Malloc(str, char, 64);
85 snprintf(str, 64, "%s%d", _nstr(nkey), rand() % 10);
86 ht_put_string(htable, _nstr(nkey), str);
87 n_log(LOG_INFO, "Put string %s key %s", str, _nstr(nkey));
88 Free(str);
89 break;
90 }
91 /* asving key for ulterior use */
92 list_push(keys_list, nkey, free_nstr_ptr);
93 }
94
95 n_log(LOG_INFO, "Reading hash table with ht_foreach");
96 HT_FOREACH(node, htable,
97 {
98 n_log(LOG_INFO, "HT_FOREACH hash: %u, key:%s", node->hash_value, _str(node->key));
99 });
100 HT_FOREACH_R(node, htable, hash_iterator,
101 {
102 n_log(LOG_INFO, "HT_FOREACH_R hash: %u, key:%s", node->hash_value, _str(node->key));
103 });
104
105 size_t optimal_size = ht_get_optimal_size(htable);
106 n_log(LOG_INFO, "########");
107 n_log(LOG_INFO, "collisions: %d %%", ht_get_table_collision_percentage(htable));
108 n_log(LOG_INFO, "table size: %zu , table optimal size: %zu", htable->size, optimal_size);
109 n_log(LOG_INFO, "resizing to %zu returned %d", optimal_size, ht_resize(&htable, optimal_size));
110 n_log(LOG_INFO, "collisions after resize: %d %%", ht_get_table_collision_percentage(htable));
111 n_log(LOG_INFO, "########");
112
113 if (ht_optimize(&htable) == FALSE) {
114 n_log(LOG_ERR, "Error when optimizing table %p", htable);
115 }
116 n_log(LOG_INFO, "collisions after ht_optimize: %d %%", ht_get_table_collision_percentage(htable));
117 n_log(LOG_INFO, "########");
118
119 LIST* results = ht_get_completion_list(htable, "key", NB_HASH_ELEMENTS);
120 if (results) {
121 list_foreach(node, results) {
122 n_log(LOG_INFO, "completion result: %s", (char*)node->ptr);
123 }
124 list_destroy(&results);
125 }
126
127 int matching_nodes(HASH_NODE * node) {
128 if (strncasecmp("key", node->key, 3) == 0)
129 return TRUE;
130 return FALSE;
131 }
132 results = ht_search(htable, &matching_nodes);
133 list_foreach(node, results) {
134 n_log(LOG_INFO, "htsearch: key: %s", (char*)node->ptr);
135 }
136 list_destroy(&results);
137
138 /* test ht_get_ptr */
139 Malloc(data, DATA, 1);
140 if (data) {
141 data->rnd_str = NULL;
142 nstrprintf(data->rnd_str, "ptr_test_value");
143 data->value = 42;
144 ht_put_ptr(htable, "ptr_test_key", data, &destroy_data, NULL);
145 void* retrieved = NULL;
146 ht_get_ptr(htable, "ptr_test_key", &retrieved);
147 if (retrieved) {
148 DATA* rd = (DATA*)retrieved;
149 n_log(LOG_INFO, "ht_get_ptr: value=%d str=%s", rd->value, _nstr(rd->rnd_str));
150 }
151 }
152
153 /* test ht_remove */
154 ht_put_int(htable, "remove_me", 999);
155 n_log(LOG_INFO, "Before ht_remove, table has entries");
156 ht_remove(htable, "remove_me");
157 n_log(LOG_INFO, "After ht_remove(\"remove_me\")");
158 {
159 HASH_INT_TYPE check_val = -1;
160 if (ht_get_int(htable, "remove_me", &check_val) == FALSE) {
161 n_log(LOG_INFO, "ht_remove confirmed: key no longer found");
162 }
163 }
164
165 /* test ht_duplicate */
166 HASH_TABLE* htable_copy = ht_duplicate(htable);
167 if (htable_copy) {
168 n_log(LOG_INFO, "ht_duplicate: created copy with size %ld", htable_copy->size);
169 destroy_ht(&htable_copy);
170 }
171
172 list_destroy(&keys_list);
173 destroy_ht(&htable);
174
175 /* testing empty destroy */
176 htable = new_ht(1024);
177 empty_ht(htable);
178 destroy_ht(&htable);
179
180 htable = new_ht_trie(256, 32);
181
182 ht_put_int(htable, "TestInt", 1);
183 ht_put_double(htable, "TestDouble", 2.0);
184 ht_put_string(htable, "TestString", "MyString");
185 HASH_INT_TYPE ival = -1;
186 double fval = -1.0;
187 ht_get_int(htable, "TestInt", &ival);
188 ht_get_double(htable, "TestDouble", &fval);
189 char* string = NULL;
190 ht_get_string(htable, "TestString", &string);
191 n_log(LOG_INFO, "Trie:%ld %f %s", (long)ival, fval, string);
192
193 results = ht_get_completion_list(htable, "Test", 10);
194 if (results) {
195 list_foreach(node, results) {
196 n_log(LOG_INFO, "completion result: %s", (char*)node->ptr);
197 }
198 list_destroy(&results);
199 }
200
201 destroy_ht(&htable);
202
203 exit(0);
204
205} /* END_OF_MAIN */
int main(void)
int value
int value
Definition ex_hash.c:39
void destroy_data(void *ptr)
destroy a DATA struct
Definition ex_hash.c:46
#define NB_HASH_ELEMENTS
Definition ex_hash.c:32
N_STR * rnd_str
string holder
Definition ex_hash.c:37
string and int holder
Definition ex_hash.c:35
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define _str(__PTR)
define true
Definition n_common.h:192
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
Definition n_common.h:198
char * key
string key of the node if any, else NULL
Definition n_hash.h:113
size_t size
size of the hash table
Definition n_hash.h:139
int ht_get_ptr(HASH_TABLE *table, const char *key, void **val)
get pointer at 'key' from 'table'
Definition n_hash.c:2100
LIST * ht_search(HASH_TABLE *table, int(*node_is_matching)(HASH_NODE *node))
seach table for matching nodes
Definition n_hash.c:2214
HASH_TABLE * ht_duplicate(HASH_TABLE *table)
duplicate a hash table (all pointers should have a duplicator func set)
Definition n_hash.c:2636
int destroy_ht(HASH_TABLE **table)
empty a table and destroy it
Definition n_hash.c:2234
#define HT_FOREACH_R(__ITEM_, __HASH_, __ITERATOR,...)
ForEach macro helper.
Definition n_hash.h:261
int ht_remove(HASH_TABLE *table, const char *key)
remove and delete node at key in table
Definition n_hash.c:2192
HASH_TABLE * new_ht(size_t size)
Create a hash table with the given size.
Definition n_hash.c:2001
int ht_get_table_collision_percentage(HASH_TABLE *table)
get table collision percentage (HASH_CLASSIC mode only)
Definition n_hash.c:2477
int ht_get_double(HASH_TABLE *table, const char *key, double *val)
get double at 'key' from 'table'
Definition n_hash.c:2074
int empty_ht(HASH_TABLE *table)
empty a table
Definition n_hash.c:2224
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:2391
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:2126
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:2501
int ht_put_ptr(HASH_TABLE *table, const char *key, void *ptr, void(*destructor)(void *ptr), void *(*duplicator)(void *ptr))
put an arbitrary pointer value with given key in the targeted hash table
Definition n_hash.c:2154
int ht_get_string(HASH_TABLE *table, const char *key, char **val)
get string at 'key' from 'table'
Definition n_hash.c:2113
#define HASH_INT_TYPE
type of a HASH_INT in 64 bits
Definition n_hash.h:92
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:2167
int ht_resize(HASH_TABLE **table, size_t size)
rehash table according to size (HASH_CLASSIC mode only)
Definition n_hash.c:2520
int ht_get_int(HASH_TABLE *table, const char *key, int64_t *val)
get node at 'key' from 'table'
Definition n_hash.c:2087
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:1955
int ht_put_int(HASH_TABLE *table, const char *key, int64_t value)
put an integral value with given key in the targeted hash table
Definition n_hash.c:2139
int ht_optimize(HASH_TABLE **table)
try an automatic optimization of the table (HASH_CLASSIC mode only)
Definition n_hash.c:2602
#define HT_FOREACH(__ITEM_, __HASH_,...)
ForEach macro helper.
Definition n_hash.h:215
structure of a hash table node
Definition n_hash.h:111
structure of a hash table
Definition n_hash.h:137
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:227
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:88
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:547
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:36
Structure of a generic LIST container.
Definition n_list.h:58
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:120
#define LOG_INFO
informational
Definition n_log.h:81
void free_nstr_ptr(void *ptr)
Free a N_STR pointer structure.
Definition n_str.c:69
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:201
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:115
A box including a string and his lenght.
Definition n_str.h:60
Hash functions and table.
List structures and definitions.
Generic log system.
N_STR and string function declaration.