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 #include "cx/hash_key.h"
30 #include "cx/compare.h"
31 #include <string.h>
32
33 void cx_hash_murmur(CxHashKey *key) {
34 const unsigned char *data = key->data;
35 if (data ==
NULL) {
36
37 key->hash =
1574210520u;
38 return;
39 }
40 size_t len = key->len;
41
42 unsigned m =
0x5bd1e995;
43 unsigned r =
24;
44 unsigned h =
25 ^ (
unsigned) len;
45 unsigned i =
0;
46 while (len >=
4) {
47 unsigned k = data[i +
0] &
0xFF;
48 k |= (data[i +
1] &
0xFF) <<
8;
49 k |= (data[i +
2] &
0xFF) <<
16;
50 k |= (data[i +
3] &
0xFF) <<
24;
51
52 k *= m;
53 k ^= k >> r;
54 k *= m;
55
56 h *= m;
57 h ^= k;
58
59 i +=
4;
60 len -=
4;
61 }
62
63 switch (len) {
64 case 3:
65 h ^= (data[i +
2] &
0xFF) <<
16;
66 cx_attr_fallthrough;
67 case 2:
68 h ^= (data[i +
1] &
0xFF) <<
8;
69 cx_attr_fallthrough;
70 case 1:
71 h ^= (data[i +
0] &
0xFF);
72 h *= m;
73 cx_attr_fallthrough;
74 default:
75 ;
76 }
77
78 h ^= h >>
13;
79 h *= m;
80 h ^= h >>
15;
81
82 key->hash = h;
83 }
84
85
86 uint32_t cx_hash_u32(
uint32_t x) {
87 x = ((x >>
16) ^ x) *
0x45d9f3bu;
88 x = ((x >>
16) ^ x) *
0x45d9f3bu;
89 x = (x >>
16) ^ x;
90 return x;
91 }
92
93 uint64_t cx_hash_u64(
uint64_t x) {
94 x = (x ^ (x >>
30)) *
UINT64_C(
0xbf58476d1ce4e5b9);
95 x = (x ^ (x >>
27)) *
UINT64_C(
0x94d049bb133111eb);
96 x = x ^ (x >>
31);
97 return x;
98 }
99
100 CxHashKey cx_hash_key_str(
const char *str) {
101 CxHashKey key;
102 key.data = str;
103 key.len = str ==
NULL ?
0 : strlen(str);
104 cx_hash_murmur(&key);
105 return key;
106 }
107
108 CxHashKey cx_hash_key_ustr(
unsigned const char *str) {
109 CxHashKey key;
110 key.data = str;
111 key.len = str ==
NULL ?
0 : strlen((
const char*)str);
112 cx_hash_murmur(&key);
113 return key;
114 }
115
116 CxHashKey cx_hash_key_cxstr(cxstring str) {
117 return cx_hash_key(str.ptr, str.length);
118 }
119
120 CxHashKey cx_hash_key_mutstr(cxmutstr str) {
121 return cx_hash_key(str.ptr, str.length);
122 }
123
124 CxHashKey cx_hash_key_bytes(
125 const unsigned char *bytes,
126 size_t len
127 ) {
128 CxHashKey key;
129 key.data = bytes;
130 key.len = len;
131 cx_hash_murmur(&key);
132 return key;
133 }
134
135 CxHashKey cx_hash_key(
136 const void *obj,
137 size_t len
138 ) {
139 CxHashKey key;
140 key.data = obj;
141 key.len = len;
142 cx_hash_murmur(&key);
143 return key;
144 }
145
146 CxHashKey cx_hash_key_u32(
uint32_t x) {
147 CxHashKey key;
148 key.data =
NULL;
149 key.len =
0;
150 key.hash = cx_hash_u32(x);
151 return key;
152 }
153
154 CxHashKey cx_hash_key_u64(
uint64_t x) {
155 CxHashKey key;
156 key.data =
NULL;
157 key.len =
0;
158 key.hash = cx_hash_u64(x);
159 return key;
160 }
161
162 int cx_hash_key_cmp(
const void *l,
const void *r) {
163 const CxHashKey *left = l;
164 const CxHashKey *right = r;
165 int d;
166 d = cx_vcmp_uint64(left->hash, right->hash);
167 if (d !=
0)
return d;
168 d = cx_vcmp_size(left->len, right->len);
169 if (d !=
0)
return d;
170 if (left->len ==
0)
return 0;
171 return memcmp(left->data, right->data, left->len);
172 }
173