#include "cx/hash_key.h"
#include "cx/compare.h"
#include <string.h>
void cx_hash_murmur(CxHashKey *key) {
const unsigned char *data = key->data;
if (data ==
NULL) {
key->hash =
1574210520u;
return;
}
size_t len = key->len;
unsigned m =
0x5bd1e995;
unsigned r =
24;
unsigned h =
25 ^ (
unsigned) len;
unsigned i =
0;
while (len >=
4) {
unsigned k = data[i +
0] &
0xFF;
k |= (data[i +
1] &
0xFF) <<
8;
k |= (data[i +
2] &
0xFF) <<
16;
k |= (data[i +
3] &
0xFF) <<
24;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
i +=
4;
len -=
4;
}
switch (len) {
case 3:
h ^= (data[i +
2] &
0xFF) <<
16;
cx_attr_fallthrough;
case 2:
h ^= (data[i +
1] &
0xFF) <<
8;
cx_attr_fallthrough;
case 1:
h ^= (data[i +
0] &
0xFF);
h *= m;
cx_attr_fallthrough;
default:
;
}
h ^= h >>
13;
h *= m;
h ^= h >>
15;
key->hash = h;
}
uint32_t cx_hash_u32(
uint32_t x) {
x = ((x >>
16) ^ x) *
0x45d9f3bu;
x = ((x >>
16) ^ x) *
0x45d9f3bu;
x = (x >>
16) ^ x;
return x;
}
uint64_t cx_hash_u64(
uint64_t x) {
x = (x ^ (x >>
30)) *
UINT64_C(
0xbf58476d1ce4e5b9);
x = (x ^ (x >>
27)) *
UINT64_C(
0x94d049bb133111eb);
x = x ^ (x >>
31);
return x;
}
CxHashKey cx_hash_key_str(
const char *str) {
CxHashKey key;
key.data = str;
key.len = str ==
NULL ?
0 : strlen(str);
cx_hash_murmur(&key);
return key;
}
CxHashKey cx_hash_key_ustr(
unsigned const char *str) {
CxHashKey key;
key.data = str;
key.len = str ==
NULL ?
0 : strlen((
const char*)str);
cx_hash_murmur(&key);
return key;
}
CxHashKey cx_hash_key_cxstr(cxstring str) {
return cx_hash_key(str.ptr, str.length);
}
CxHashKey cx_hash_key_mutstr(cxmutstr str) {
return cx_hash_key(str.ptr, str.length);
}
CxHashKey cx_hash_key_bytes(
const unsigned char *bytes,
size_t len
) {
CxHashKey key;
key.data = bytes;
key.len = len;
cx_hash_murmur(&key);
return key;
}
CxHashKey cx_hash_key(
const void *obj,
size_t len
) {
CxHashKey key;
key.data = obj;
key.len = len;
cx_hash_murmur(&key);
return key;
}
CxHashKey cx_hash_key_u32(
uint32_t x) {
CxHashKey key;
key.data =
NULL;
key.len =
0;
key.hash = cx_hash_u32(x);
return key;
}
CxHashKey cx_hash_key_u64(
uint64_t x) {
CxHashKey key;
key.data =
NULL;
key.len =
0;
key.hash = cx_hash_u64(x);
return key;
}
int cx_hash_key_cmp(
const void *l,
const void *r) {
const CxHashKey *left = l;
const CxHashKey *right = r;
int d;
d = cx_vcmp_uint64(left->hash, right->hash);
if (d !=
0)
return d;
d = cx_vcmp_size(left->len, right->len);
if (d !=
0)
return d;
if (left->len ==
0)
return 0;
return memcmp(left->data, right->data, left->len);
}