Added full support for custom hash functions.
[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 /**
53 @note We do assume source is valid. If source does not exist, we allocate.
54 */
55 hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
56 {
57 if (source == NULL)
58 {
59 return hashkit_create(destination);
60 }
61
62 /* new_clone will be a pointer to destination */
63 destination= hashkit_create(destination);
64
65 // Should only happen on allocation failure.
66 if (destination == NULL)
67 {
68 return NULL;
69 }
70
71 destination->base_hash= source->base_hash;
72
73 return destination;
74 }
75
76
77 uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length)
78 {
79 return self->base_hash.function(key, key_length, self->base_hash.context);
80 }
81
82 hashkit_return_t hashkit_set_base_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
83 {
84 switch (hash_algorithm)
85 {
86 case HASHKIT_HASH_DEFAULT:
87 self->base_hash.function= hashkit_one_at_a_time;
88 break;
89 case HASHKIT_HASH_MD5:
90 self->base_hash.function= hashkit_md5;
91 break;
92 case HASHKIT_HASH_CRC:
93 self->base_hash.function= hashkit_crc32;
94 break;
95 case HASHKIT_HASH_FNV1_64:
96 self->base_hash.function= hashkit_fnv1_64;
97 break;
98 case HASHKIT_HASH_FNV1A_64:
99 self->base_hash.function= hashkit_fnv1a_64;
100 break;
101 case HASHKIT_HASH_FNV1_32:
102 self->base_hash.function= hashkit_fnv1_32;
103 break;
104 case HASHKIT_HASH_FNV1A_32:
105 self->base_hash.function= hashkit_fnv1a_32;
106 break;
107 case HASHKIT_HASH_HSIEH:
108 #ifdef HAVE_HSIEH_HASH
109 self->base_hash.function= hashkit_hsieh;
110 break;
111 #else
112 return HASHKIT_FAILURE;
113 #endif
114 case HASHKIT_HASH_MURMUR:
115 self->base_hash.function= hashkit_murmur;
116 break;
117 case HASHKIT_HASH_JENKINS:
118 self->base_hash.function= hashkit_jenkins;
119 break;
120 case HASHKIT_HASH_MAX:
121 default:
122 return HASHKIT_FAILURE;
123 break;
124 }
125
126 self->base_hash.context= NULL;
127
128 return HASHKIT_SUCCESS;
129 }
130
131 hashkit_return_t hashkit_set_base_function_custom(hashkit_st *self, hashkit_hash_fn function, void *context)
132 {
133 if (function)
134 {
135 self->base_hash.function= function;
136 self->base_hash.context= context;
137
138 return HASHKIT_SUCCESS;
139 }
140
141 return HASHKIT_FAILURE;
142 }
143
144 uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
145 {
146 switch (hash_algorithm)
147 {
148 case HASHKIT_HASH_DEFAULT:
149 return libhashkit_one_at_a_time(key, key_length);
150 case HASHKIT_HASH_MD5:
151 return libhashkit_md5(key, key_length);
152 case HASHKIT_HASH_CRC:
153 return libhashkit_crc32(key, key_length);
154 case HASHKIT_HASH_FNV1_64:
155 return libhashkit_fnv1_64(key, key_length);
156 case HASHKIT_HASH_FNV1A_64:
157 return libhashkit_fnv1a_64(key, key_length);
158 case HASHKIT_HASH_FNV1_32:
159 return libhashkit_fnv1_32(key, key_length);
160 case HASHKIT_HASH_FNV1A_32:
161 return libhashkit_fnv1a_32(key, key_length);
162 case HASHKIT_HASH_HSIEH:
163 #ifdef HAVE_HSIEH_HASH
164 return libhashkit_hsieh(key, key_length);
165 #else
166 return 1;
167 #endif
168 case HASHKIT_HASH_MURMUR:
169 return libhashkit_murmur(key, key_length);
170 case HASHKIT_HASH_JENKINS:
171 return libhashkit_jenkins(key, key_length);
172 case HASHKIT_HASH_MAX:
173 default:
174 #ifdef HAVE_DEBUG
175 fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
176 fflush(stderr);
177 assert(0);
178 #endif
179 break;
180 }
181
182 return 1;
183 }