1 #include "hash_state.h"
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <limits.h>
5 #include <string.h>
6 
7 //#define DEBUG
8 #include "debug.h"
9 
10 const char *cmph_hash_names[] = { "jenkins", NULL };
11 
hash_state_new(CMPH_HASH hashfunc,cmph_uint32 hashsize)12 hash_state_t *hash_state_new(CMPH_HASH hashfunc, cmph_uint32 hashsize)
13 {
14 	hash_state_t *state = NULL;
15 	switch (hashfunc)
16 	{
17 		case CMPH_HASH_JENKINS:
18 	  		DEBUGP("Jenkins function - %u\n", hashsize);
19 			state = (hash_state_t *)jenkins_state_new(hashsize);
20 	  		DEBUGP("Jenkins function created\n");
21 			break;
22 		default:
23 			assert(0);
24 	}
25 	state->hashfunc = hashfunc;
26 	return state;
27 }
hash(hash_state_t * state,const char * key,cmph_uint32 keylen)28 cmph_uint32 hash(hash_state_t *state, const char *key, cmph_uint32 keylen)
29 {
30 	switch (state->hashfunc)
31 	{
32 		case CMPH_HASH_JENKINS:
33 			return jenkins_hash((jenkins_state_t *)state, key, keylen);
34 		default:
35 			assert(0);
36 	}
37 	assert(0);
38 	return 0;
39 }
40 
hash_vector(hash_state_t * state,const char * key,cmph_uint32 keylen,cmph_uint32 * hashes)41 void hash_vector(hash_state_t *state, const char *key, cmph_uint32 keylen, cmph_uint32 * hashes)
42 {
43 	switch (state->hashfunc)
44 	{
45 		case CMPH_HASH_JENKINS:
46 			jenkins_hash_vector_((jenkins_state_t *)state, key, keylen, hashes);
47 			break;
48 		default:
49 			assert(0);
50 	}
51 }
52 
53 
hash_state_dump(hash_state_t * state,char ** buf,cmph_uint32 * buflen)54 void hash_state_dump(hash_state_t *state, char **buf, cmph_uint32 *buflen)
55 {
56 	char *algobuf;
57 	size_t len;
58 	switch (state->hashfunc)
59 	{
60 		case CMPH_HASH_JENKINS:
61 			jenkins_state_dump((jenkins_state_t *)state, &algobuf, buflen);
62 			if (*buflen == UINT_MAX) {
63                 goto cmph_cleanup;
64             }
65 			break;
66 		default:
67 			assert(0);
68 	}
69 	*buf = (char *)malloc(strlen(cmph_hash_names[state->hashfunc]) + 1 + *buflen);
70 	memcpy(*buf, cmph_hash_names[state->hashfunc], strlen(cmph_hash_names[state->hashfunc]) + 1);
71 	DEBUGP("Algobuf is %u\n", *(cmph_uint32 *)algobuf);
72 	len = *buflen;
73 	memcpy(*buf + strlen(cmph_hash_names[state->hashfunc]) + 1, algobuf, len);
74 	*buflen  = (cmph_uint32)strlen(cmph_hash_names[state->hashfunc]) + 1 + *buflen;
75 cmph_cleanup:
76 	free(algobuf);
77 	return;
78 }
79 
hash_state_copy(hash_state_t * src_state)80 hash_state_t * hash_state_copy(hash_state_t *src_state)
81 {
82 	hash_state_t *dest_state = NULL;
83 	switch (src_state->hashfunc)
84 	{
85 		case CMPH_HASH_JENKINS:
86 			dest_state = (hash_state_t *)jenkins_state_copy((jenkins_state_t *)src_state);
87 			break;
88 		default:
89 			assert(0);
90 	}
91 	dest_state->hashfunc = src_state->hashfunc;
92 	return dest_state;
93 }
94 
hash_state_load(const char * buf,cmph_uint32 buflen)95 hash_state_t *hash_state_load(const char *buf, cmph_uint32 buflen)
96 {
97 	cmph_uint32 i;
98 	cmph_uint32 offset;
99 	CMPH_HASH hashfunc = CMPH_HASH_COUNT;
100 	for (i = 0; i < CMPH_HASH_COUNT; ++i)
101 	{
102 		if (strcmp(buf, cmph_hash_names[i]) == 0)
103 		{
104 			hashfunc = (CMPH_HASH)(i);
105 			break;
106 		}
107 	}
108 	if (hashfunc == CMPH_HASH_COUNT) return NULL;
109 	offset = (cmph_uint32)strlen(cmph_hash_names[hashfunc]) + 1;
110 	switch (hashfunc)
111 	{
112 		case CMPH_HASH_JENKINS:
113 			return (hash_state_t *)jenkins_state_load(buf + offset, buflen - offset);
114 		default:
115 			return NULL;
116 	}
117 	return NULL;
118 }
hash_state_destroy(hash_state_t * state)119 void hash_state_destroy(hash_state_t *state)
120 {
121 	switch (state->hashfunc)
122 	{
123 		case CMPH_HASH_JENKINS:
124 			jenkins_state_destroy((jenkins_state_t *)state);
125 			break;
126 		default:
127 			assert(0);
128 	}
129 	return;
130 }
131 
132 /** \fn void hash_state_pack(hash_state_t *state, void *hash_packed)
133  *  \brief Support the ability to pack a hash function into a preallocated contiguous memory space pointed by hash_packed.
134  *  \param state points to the hash function
135  *  \param hash_packed pointer to the contiguous memory area used to store the hash function. The size of hash_packed must be at least hash_state_packed_size()
136  *
137  * Support the ability to pack a hash function into a preallocated contiguous memory space pointed by hash_packed.
138  * However, the hash function type must be packed outside.
139  */
hash_state_pack(hash_state_t * state,void * hash_packed)140 void hash_state_pack(hash_state_t *state, void *hash_packed)
141 {
142 	switch (state->hashfunc)
143 	{
144 		case CMPH_HASH_JENKINS:
145 			// pack the jenkins hash function
146 			jenkins_state_pack((jenkins_state_t *)state, hash_packed);
147 			break;
148 		default:
149 			assert(0);
150 	}
151 	return;
152 }
153 
154 /** \fn cmph_uint32 hash_state_packed_size(CMPH_HASH hashfunc)
155  *  \brief Return the amount of space needed to pack a hash function.
156  *  \param hashfunc function type
157  *  \return the size of the packed function or zero for failures
158  */
hash_state_packed_size(CMPH_HASH hashfunc)159 cmph_uint32 hash_state_packed_size(CMPH_HASH hashfunc)
160 {
161 	cmph_uint32 size = 0;
162 	switch (hashfunc)
163 	{
164 		case CMPH_HASH_JENKINS:
165 			size += jenkins_state_packed_size();
166 			break;
167 		default:
168 			assert(0);
169 	}
170 	return size;
171 }
172 
173 /** \fn cmph_uint32 hash_packed(void *hash_packed, CMPH_HASH hashfunc, const char *k, cmph_uint32 keylen)
174  *  \param hash_packed is a pointer to a contiguous memory area
175  *  \param hashfunc is the type of the hash function packed in hash_packed
176  *  \param key is a pointer to a key
177  *  \param keylen is the key length
178  *  \return an integer that represents a hash value of 32 bits.
179  */
hash_packed(void * hash_packed,CMPH_HASH hashfunc,const char * k,cmph_uint32 keylen)180 cmph_uint32 hash_packed(void *hash_packed, CMPH_HASH hashfunc, const char *k, cmph_uint32 keylen)
181 {
182 	switch (hashfunc)
183 	{
184 		case CMPH_HASH_JENKINS:
185 			return jenkins_hash_packed(hash_packed, k, keylen);
186 		default:
187 			assert(0);
188 	}
189 	assert(0);
190 	return 0;
191 }
192 
193 /** \fn hash_vector_packed(void *hash_packed, CMPH_HASH hashfunc, const char *k, cmph_uint32 keylen, cmph_uint32 * hashes)
194  *  \param hash_packed is a pointer to a contiguous memory area
195  *  \param key is a pointer to a key
196  *  \param keylen is the key length
197  *  \param hashes is a pointer to a memory large enough to fit three 32-bit integers.
198  */
hash_vector_packed(void * hash_packed,CMPH_HASH hashfunc,const char * k,cmph_uint32 keylen,cmph_uint32 * hashes)199 void hash_vector_packed(void *hash_packed, CMPH_HASH hashfunc, const char *k, cmph_uint32 keylen, cmph_uint32 * hashes)
200 {
201 	switch (hashfunc)
202 	{
203 		case CMPH_HASH_JENKINS:
204 			jenkins_hash_vector_packed(hash_packed, k, keylen, hashes);
205 			break;
206 		default:
207 			assert(0);
208 	}
209 }
210 
211 
212 /** \fn CMPH_HASH hash_get_type(hash_state_t *state);
213  *  \param state is a pointer to a hash_state_t structure
214  *  \return the hash function type pointed by state
215  */
hash_get_type(hash_state_t * state)216 CMPH_HASH hash_get_type(hash_state_t *state)
217 {
218 	return state->hashfunc;
219 }
220