1 |
|
2 |
|
3 |
|
4 | export default (arr, prefix = 'h') => `h${hash(arr)}`
|
5 | function hash(arr) {
|
6 | let str = (Array.isArray(arr)
|
7 | ? arr
|
8 | : Object.keys(arr).map(k => `${k}:${JSON.stringify(arr[k])}`)).join(',')
|
9 | return murmur2(str, str.length).toString(36)
|
10 | }
|
11 |
|
12 | export function murmur2(str, seed) {
|
13 | let m = 0x5bd1e995
|
14 | let r = 24
|
15 | let h = seed ^ str.length
|
16 | let length = str.length
|
17 | let currentIndex = 0
|
18 |
|
19 | while (length >= 4) {
|
20 | let k = UInt32(str, currentIndex)
|
21 |
|
22 | k = Umul32(k, m)
|
23 | k ^= k >>> r
|
24 | k = Umul32(k, m)
|
25 |
|
26 | h = Umul32(h, m)
|
27 | h ^= k
|
28 |
|
29 | currentIndex += 4
|
30 | length -= 4
|
31 | }
|
32 |
|
33 | switch (length) {
|
34 | case 3:
|
35 | h ^= UInt16(str, currentIndex)
|
36 | h ^= str.charCodeAt(currentIndex + 2) << 16
|
37 | h = Umul32(h, m)
|
38 | break
|
39 |
|
40 | case 2:
|
41 | h ^= UInt16(str, currentIndex)
|
42 | h = Umul32(h, m)
|
43 | break
|
44 |
|
45 | case 1:
|
46 | h ^= str.charCodeAt(currentIndex)
|
47 | h = Umul32(h, m)
|
48 | break
|
49 | }
|
50 |
|
51 | h ^= h >>> 13
|
52 | h = Umul32(h, m)
|
53 | h ^= h >>> 15
|
54 |
|
55 | return h >>> 0
|
56 | }
|
57 |
|
58 | function UInt32(str, pos) {
|
59 | return (
|
60 | str.charCodeAt(pos++) +
|
61 | (str.charCodeAt(pos++) << 8) +
|
62 | (str.charCodeAt(pos++) << 16) +
|
63 | (str.charCodeAt(pos) << 24)
|
64 | )
|
65 | }
|
66 |
|
67 | function UInt16(str, pos) {
|
68 | return str.charCodeAt(pos++) + (str.charCodeAt(pos++) << 8)
|
69 | }
|
70 |
|
71 | function Umul32(n, m) {
|
72 | n = n | 0
|
73 | m = m | 0
|
74 | let nlo = n & 0xffff
|
75 | let nhi = n >>> 16
|
76 | let res = (nlo * m + (((nhi * m) & 0xffff) << 16)) | 0
|
77 | return res
|
78 | }
|