forked from Qihoo360/evpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhsieh.c
70 lines (59 loc) · 1.61 KB
/
hsieh.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh
* derivative license.
* See: http://www.azillionmonkeys.com/qed/weblicense.html for license
* details.
* http://www.azillionmonkeys.com/qed/hash.html
*/
#include "common.h"
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__))
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context __attribute__((unused)))
{
uint32_t hash = 0, tmp;
int rem;
if (key_length <= 0 || key == NULL)
return 0;
rem = key_length & 3;
key_length >>= 2;
/* Main loop */
for (;key_length > 0; key_length--)
{
hash += get16bits (key);
tmp = (get16bits (key+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
key += 2*sizeof (uint16_t);
hash += hash >> 11;
}
/* Handle end cases */
switch (rem)
{
case 3: hash += get16bits (key);
hash ^= hash << 16;
hash ^= (uint32_t)key[sizeof (uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += get16bits (key);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += (unsigned char)(*key);
hash ^= hash << 10;
hash += hash >> 1;
default:
break;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}