9a7e93e9c70b7254fc835c500d965dba2ed9e42a
[awesomized/libmemcached] / libhashkit / hashkit.c
1 /* HashKit
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 */
8
9 #include "common.h"
10
11 static const hashkit_st global_default_hash= {
12 .base_hash= {
13 .function= hashkit_one_at_a_time,
14 .context= NULL
15 },
16 };
17
18 /**
19 @note We make no assumptions that "hashk" has been, or not been allocated from heap/stack. We just know we didn't do it.
20 */
21 hashkit_st *hashkit_create(hashkit_st *self)
22 {
23 if (self == NULL)
24 {
25 self= (hashkit_st *)malloc(sizeof(hashkit_st));
26 if (self == NULL)
27 {
28 return NULL;
29 }
30
31 self->options.is_allocated= true;
32 }
33 else
34 {
35 self->options.is_allocated= false;
36 }
37
38 self->base_hash= global_default_hash.base_hash;
39
40 return self;
41 }
42
43
44 void hashkit_free(hashkit_st *self)
45 {
46 if (hashkit_is_allocated(self))
47 {
48 free(self);
49 }
50 }
51
52 hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
53 {
54 if (source == NULL)
55 {
56 return hashkit_create(destination);
57 }
58
59 /* new_clone will be a pointer to destination */
60 destination= hashkit_create(destination);
61
62 // Should only happen on allocation failure.
63 if (destination == NULL)
64 {
65 return NULL;
66 }
67
68 destination->base_hash= source->base_hash;
69
70 return destination;
71 }
72
73 bool hashkit_compare(const hashkit_st *first, const hashkit_st *second)
74 {
75 if (first->base_hash.function == second->base_hash.function &&
76 first->base_hash.context == second->base_hash.context)
77 return true;
78
79 return false;
80 }
81
82 uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length)
83 {
84 return self->base_hash.function(key, key_length, self->base_hash.context);
85 }
86
87 hashkit_return_t hashkit_set_base_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
88 {
89 switch (hash_algorithm)
90 {
91 case HASHKIT_HASH_DEFAULT:
92 self->base_hash.function= hashkit_one_at_a_time;
93 break;
94 case HASHKIT_HASH_MD5:
95 self->base_hash.function= hashkit_md5;
96 break;
97 case HASHKIT_HASH_CRC:
98 self->base_hash.function= hashkit_crc32;
99 break;
100 case HASHKIT_HASH_FNV1_64:
101 self->base_hash.function= hashkit_fnv1_64;
102 break;
103 case HASHKIT_HASH_FNV1A_64:
104 self->base_hash.function= hashkit_fnv1a_64;
105 break;
106 case HASHKIT_HASH_FNV1_32:
107 self->base_hash.function= hashkit_fnv1_32;
108 break;
109 case HASHKIT_HASH_FNV1A_32:
110 self->base_hash.function= hashkit_fnv1a_32;
111 break;
112 case HASHKIT_HASH_HSIEH:
113 #ifdef HAVE_HSIEH_HASH
114 self->base_hash.function= hashkit_hsieh;
115 break;
116 #else
117 return HASHKIT_FAILURE;
118 #endif
119 case HASHKIT_HASH_MURMUR:
120 self->base_hash.function= hashkit_murmur;
121 break;
122 case HASHKIT_HASH_JENKINS:
123 self->base_hash.function= hashkit_jenkins;
124 break;
125 case HASHKIT_HASH_CUSTOM:
126 case HASHKIT_HASH_MAX:
127 default:
128 return HASHKIT_FAILURE;
129 break;
130 }
131
132 self->base_hash.context= NULL;
133
134 return HASHKIT_SUCCESS;
135 }
136
137 hashkit_return_t hashkit_set_base_function_custom(hashkit_st *self, hashkit_hash_fn function, void *context)
138 {
139 if (function)
140 {
141 self->base_hash.function= function;
142 self->base_hash.context= context;
143
144 return HASHKIT_SUCCESS;
145 }
146
147 return HASHKIT_FAILURE;
148 }
149
150 hashkit_hash_algorithm_t hashkit_get_base_function(const hashkit_st *self)
151 {
152 if (self->base_hash.function == hashkit_one_at_a_time)
153 {
154 return HASHKIT_HASH_DEFAULT;
155 }
156 else if (self->base_hash.function == hashkit_md5)
157 {
158 return HASHKIT_HASH_MD5;
159 }
160 else if (self->base_hash.function == hashkit_crc32)
161 {
162 return HASHKIT_HASH_CRC;
163 }
164 else if (self->base_hash.function == hashkit_fnv1_64)
165 {
166 return HASHKIT_HASH_FNV1_64;
167 }
168 else if (self->base_hash.function == hashkit_fnv1a_64)
169 {
170 return HASHKIT_HASH_FNV1A_64;
171 }
172 else if (self->base_hash.function == hashkit_fnv1_32)
173 {
174 return HASHKIT_HASH_FNV1_32;
175 }
176 else if (self->base_hash.function == hashkit_fnv1a_32)
177 {
178 return HASHKIT_HASH_FNV1A_32;
179 }
180 #ifdef HAVE_HSIEH_HASH
181 else if (self->base_hash.function == hashkit_hsieh)
182 {
183 return HASHKIT_HASH_HSIEH;
184 }
185 #endif
186 else if (self->base_hash.function == hashkit_murmur)
187 {
188 return HASHKIT_HASH_MURMUR;
189 }
190 else if (self->base_hash.function == hashkit_jenkins)
191 {
192 return HASHKIT_HASH_JENKINS;
193 }
194
195 return HASHKIT_HASH_CUSTOM;
196 }
197
198 uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
199 {
200 switch (hash_algorithm)
201 {
202 case HASHKIT_HASH_DEFAULT:
203 return libhashkit_one_at_a_time(key, key_length);
204 case HASHKIT_HASH_MD5:
205 return libhashkit_md5(key, key_length);
206 case HASHKIT_HASH_CRC:
207 return libhashkit_crc32(key, key_length);
208 case HASHKIT_HASH_FNV1_64:
209 return libhashkit_fnv1_64(key, key_length);
210 case HASHKIT_HASH_FNV1A_64:
211 return libhashkit_fnv1a_64(key, key_length);
212 case HASHKIT_HASH_FNV1_32:
213 return libhashkit_fnv1_32(key, key_length);
214 case HASHKIT_HASH_FNV1A_32:
215 return libhashkit_fnv1a_32(key, key_length);
216 case HASHKIT_HASH_HSIEH:
217 #ifdef HAVE_HSIEH_HASH
218 return libhashkit_hsieh(key, key_length);
219 #else
220 return 1;
221 #endif
222 case HASHKIT_HASH_MURMUR:
223 return libhashkit_murmur(key, key_length);
224 case HASHKIT_HASH_JENKINS:
225 return libhashkit_jenkins(key, key_length);
226 case HASHKIT_HASH_CUSTOM:
227 case HASHKIT_HASH_MAX:
228 default:
229 #ifdef HAVE_DEBUG
230 fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
231 fflush(stderr);
232 assert(0);
233 #endif
234 break;
235 }
236
237 return 1;
238 }