]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Hash function duk_util_hashbytes(). | |
3 | * | |
4 | * Currently, 32-bit MurmurHash2. | |
5 | * | |
6 | * Don't rely on specific hash values; hash function may be endianness | |
7 | * dependent, for instance. | |
8 | */ | |
9 | ||
10 | #include "duk_internal.h" | |
11 | ||
b9c3bfeb | 12 | #if defined(DUK_USE_STRHASH_DENSE) |
7c673cae FG |
13 | /* 'magic' constants for Murmurhash2 */ |
14 | #define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL) | |
15 | #define DUK__MAGIC_R 24 | |
16 | ||
17 | DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) { | |
18 | duk_uint32_t h = seed ^ ((duk_uint32_t) len); | |
19 | ||
20 | while (len >= 4) { | |
21 | /* Portability workaround is required for platforms without | |
22 | * unaligned access. The replacement code emulates little | |
23 | * endian access even on big endian architectures, which is | |
24 | * OK as long as it is consistent for a build. | |
25 | */ | |
26 | #ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS | |
b9c3bfeb | 27 | duk_uint32_t k = *((const duk_uint32_t *) (const void *) data); |
7c673cae FG |
28 | #else |
29 | duk_uint32_t k = ((duk_uint32_t) data[0]) | | |
30 | (((duk_uint32_t) data[1]) << 8) | | |
31 | (((duk_uint32_t) data[2]) << 16) | | |
32 | (((duk_uint32_t) data[3]) << 24); | |
33 | #endif | |
34 | ||
35 | k *= DUK__MAGIC_M; | |
36 | k ^= k >> DUK__MAGIC_R; | |
37 | k *= DUK__MAGIC_M; | |
38 | h *= DUK__MAGIC_M; | |
39 | h ^= k; | |
40 | data += 4; | |
41 | len -= 4; | |
42 | } | |
43 | ||
44 | switch (len) { | |
45 | case 3: h ^= data[2] << 16; | |
46 | case 2: h ^= data[1] << 8; | |
47 | case 1: h ^= data[0]; | |
48 | h *= DUK__MAGIC_M; | |
49 | } | |
50 | ||
51 | h ^= h >> 13; | |
52 | h *= DUK__MAGIC_M; | |
53 | h ^= h >> 15; | |
54 | ||
55 | return h; | |
56 | } | |
b9c3bfeb | 57 | #endif /* DUK_USE_STRHASH_DENSE */ |