23
23
* Basic hash implementation, like we have seen tons off already.
24
24
*/
25
25
#include "picohash.h"
26
+ #include "siphash.h"
26
27
#include <stdlib.h>
27
28
#include <string.h>
28
29
29
30
picohash_table * picohash_create_ex (size_t nb_bin ,
30
- uint64_t (* picohash_hash )(const void * ),
31
+ uint64_t (* picohash_hash )(const void * , const uint8_t * ),
31
32
int (* picohash_compare )(const void * , const void * ),
32
- picohash_item * (* picohash_key_to_item )(const void * ))
33
+ picohash_item * (* picohash_key_to_item )(const void * ),
34
+ const uint8_t * hash_seed )
33
35
{
36
+ static const uint8_t null_seed [16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
34
37
picohash_table * t = (picohash_table * )malloc (sizeof (picohash_table ));
35
38
size_t items_length = sizeof (picohash_item * ) * nb_bin ;
36
39
t -> hash_bin = NULL ;
@@ -48,21 +51,22 @@ picohash_table* picohash_create_ex(size_t nb_bin,
48
51
t -> picohash_hash = picohash_hash ;
49
52
t -> picohash_compare = picohash_compare ;
50
53
t -> picohash_key_to_item = picohash_key_to_item ;
54
+ t -> hash_seed = (hash_seed == NULL )? null_seed : hash_seed ;
51
55
}
52
56
53
57
return t ;
54
58
}
55
59
56
60
picohash_table * picohash_create (size_t nb_bin ,
57
- uint64_t (* picohash_hash )(const void * ),
61
+ uint64_t (* picohash_hash )(const void * , const uint8_t * ),
58
62
int (* picohash_compare )(const void * , const void * ))
59
63
{
60
- return picohash_create_ex (nb_bin , picohash_hash , picohash_compare , NULL );
64
+ return picohash_create_ex (nb_bin , picohash_hash , picohash_compare , NULL , NULL );
61
65
}
62
66
63
67
picohash_item * picohash_retrieve (picohash_table * hash_table , const void * key )
64
68
{
65
- uint64_t hash = hash_table -> picohash_hash (key );
69
+ uint64_t hash = hash_table -> picohash_hash (key , hash_table -> hash_seed );
66
70
uint32_t bin = (uint32_t )(hash % hash_table -> nb_bin );
67
71
picohash_item * item = hash_table -> hash_bin [bin ];
68
72
@@ -79,7 +83,7 @@ picohash_item* picohash_retrieve(picohash_table* hash_table, const void* key)
79
83
80
84
int picohash_insert (picohash_table * hash_table , const void * key )
81
85
{
82
- uint64_t hash = hash_table -> picohash_hash (key );
86
+ uint64_t hash = hash_table -> picohash_hash (key , hash_table -> hash_seed );
83
87
uint32_t bin = (uint32_t )(hash % hash_table -> nb_bin );
84
88
int ret = 0 ;
85
89
picohash_item * item ;
@@ -150,19 +154,21 @@ void picohash_delete_key(picohash_table* hash_table, void* key, int delete_key_t
150
154
151
155
void picohash_delete (picohash_table * hash_table , int delete_key_too )
152
156
{
153
- for (uint32_t i = 0 ; i < hash_table -> nb_bin ; i ++ ) {
154
- picohash_item * item = hash_table -> hash_bin [i ];
155
- while (item != NULL ) {
156
- picohash_item * tmp = item ;
157
- const void * key_to_delete = tmp -> key ;
158
-
159
- item = item -> next_in_bin ;
160
-
161
- if (hash_table -> picohash_key_to_item == NULL ) {
162
- free (tmp );
163
- }
164
- if (delete_key_too ) {
165
- free ((void * )key_to_delete );
157
+ if (hash_table -> count > 0 ) {
158
+ for (uint32_t i = 0 ; i < hash_table -> nb_bin ; i ++ ) {
159
+ picohash_item * item = hash_table -> hash_bin [i ];
160
+ while (item != NULL ) {
161
+ picohash_item * tmp = item ;
162
+ const void * key_to_delete = tmp -> key ;
163
+
164
+ item = item -> next_in_bin ;
165
+
166
+ if (hash_table -> picohash_key_to_item == NULL ) {
167
+ free (tmp );
168
+ }
169
+ if (delete_key_too ) {
170
+ free ((void * )key_to_delete );
171
+ }
166
172
}
167
173
}
168
174
}
@@ -171,23 +177,43 @@ void picohash_delete(picohash_table* hash_table, int delete_key_too)
171
177
free (hash_table );
172
178
}
173
179
174
- uint64_t picohash_hash_mix (uint64_t hash , uint64_t h2 )
175
- {
176
- h2 ^= (hash << 17 ) ^ (hash >> 37 );
177
- hash ^= ((h2 << 31 ) ^ (h2 >> 17 ));
178
-
179
- return hash ;
180
- }
181
-
182
- uint64_t picohash_bytes (const uint8_t * key , uint32_t length )
180
+ uint64_t picohash_bytes (const uint8_t * bytes , size_t length , const uint8_t * hash_seed )
183
181
{
184
- uint64_t hash = 0xDEADBEEF ;
182
+ uint64_t hash =
183
+ ((uint64_t )hash_seed [8 ]) +
184
+ (((uint64_t )hash_seed [9 ]) << 8 ) +
185
+ (((uint64_t )hash_seed [10 ]) << 16 ) +
186
+ (((uint64_t )hash_seed [11 ]) << 24 ) +
187
+ (((uint64_t )hash_seed [12 ]) << 32 ) +
188
+ (((uint64_t )hash_seed [13 ]) << 40 ) +
189
+ (((uint64_t )hash_seed [14 ]) << 48 ) +
190
+ (((uint64_t )hash_seed [15 ]) << 56 );
191
+ int rotate = 11 ;
185
192
186
193
for (uint32_t i = 0 ; i < length ; i ++ ) {
187
- hash ^= key [i ];
188
- hash ^= ((hash << 31 ) ^ (hash >> 17 ));
194
+ hash ^= bytes [i ];
195
+ hash ^= hash_seed [i & 15 ];
196
+ hash ^= (hash << 8 );
197
+ hash += (hash >> rotate );
198
+ rotate = (int )(hash & 31 ) + 11 ;
189
199
}
190
-
200
+ hash ^= ( hash >> rotate );
191
201
return hash ;
192
202
}
193
203
204
+ uint64_t picohash_siphash (const uint8_t * bytes , size_t length , const uint8_t * hash_seed )
205
+ {
206
+ uint8_t sip_out [8 ];
207
+ uint64_t hash ;
208
+ (void )siphash (bytes , length , hash_seed , sip_out , 8 );
209
+ hash =
210
+ (uint64_t )sip_out [0 ] +
211
+ (((uint64_t )sip_out [1 ]) << 8 ) +
212
+ (((uint64_t )sip_out [2 ]) << 16 ) +
213
+ (((uint64_t )sip_out [3 ]) << 24 ) +
214
+ (((uint64_t )sip_out [4 ]) << 32 ) +
215
+ (((uint64_t )sip_out [5 ]) << 40 ) +
216
+ (((uint64_t )sip_out [6 ]) << 48 ) +
217
+ (((uint64_t )sip_out [7 ]) << 56 );
218
+ return hash ;
219
+ }
0 commit comments