1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | import * as LongExports from 'long';
|
20 |
|
21 | const Long =
|
22 |
|
23 | LongExports.default || LongExports;
|
24 | export function hexToLong(hex) {
|
25 | return Long.fromString(hex, true, 16);
|
26 | }
|
27 |
|
28 |
|
29 | const k0 = hexToLong('c3a5c85c97cb3127');
|
30 |
|
31 | const k1 = hexToLong('b492b66fbe98f273');
|
32 |
|
33 | const k2 = hexToLong('9ae16a3b2f90404f');
|
34 | function shiftMix(val) {
|
35 | return val.xor(val.shru(47));
|
36 | }
|
37 | function fetch(s, offset, numBytes) {
|
38 | const bytes = s.slice(offset, offset + numBytes);
|
39 | return Long.fromBytes(Array.from(bytes), true, true);
|
40 | }
|
41 | function fetch64(s, offset) {
|
42 | return fetch(s, offset, 8);
|
43 | }
|
44 | function fetch32(s, offset) {
|
45 | return fetch(s, offset, 4);
|
46 | }
|
47 | function rotate64(val, shift) {
|
48 |
|
49 | return shift === 0 ? val : val.shru(shift).or(val.shl(64 - shift));
|
50 | }
|
51 | function hashLen16(u, v, mul = hexToLong('9ddfea08eb382d69')) {
|
52 |
|
53 | let a = u.xor(v).mul(mul);
|
54 | a = a.xor(a.shru(47));
|
55 | let b = v.xor(a).mul(mul);
|
56 | b = b.xor(b.shru(47));
|
57 | b = b.mul(mul);
|
58 | return b;
|
59 | }
|
60 |
|
61 |
|
62 | function weakHashLen32WithSeeds(w, x, y, z, a, b) {
|
63 | a = a.add(w);
|
64 | b = rotate64(b.add(a).add(z), 21);
|
65 | const c = a;
|
66 | a = a.add(x);
|
67 | a = a.add(y);
|
68 | b = b.add(rotate64(a, 44));
|
69 | return [a.add(z), b.add(c)];
|
70 | }
|
71 | function weakHashLen32WithSeedsStr(s, offset, a, b) {
|
72 | return weakHashLen32WithSeeds(fetch64(s, offset), fetch64(s, offset + 8), fetch64(s, offset + 16), fetch64(s, offset + 24), a, b);
|
73 | }
|
74 | function hashLen0to16(s, len = s.length) {
|
75 | if (len >= 8) {
|
76 | const mul = k2.add(len * 2);
|
77 | const a = fetch64(s, 0).add(k2);
|
78 | const b = fetch64(s, len - 8);
|
79 | const c = rotate64(b, 37).mul(mul).add(a);
|
80 | const d = rotate64(a, 25).add(b).mul(mul);
|
81 | return hashLen16(c, d, mul);
|
82 | }
|
83 | if (len >= 4) {
|
84 | const mul = k2.add(len * 2);
|
85 | const a = fetch32(s, 0);
|
86 | return hashLen16(a.shl(3).add(len), fetch32(s, len - 4), mul);
|
87 | }
|
88 | if (len > 0) {
|
89 | const a = s[0];
|
90 | const b = s[len >> 1];
|
91 | const c = s[len - 1];
|
92 | const y = a + (b << 8);
|
93 | const z = len + (c << 2);
|
94 | return shiftMix(k2.mul(y).xor(k0.mul(z))).mul(k2);
|
95 | }
|
96 | return k2;
|
97 | }
|
98 | function hashLen17to32(s, len = s.length) {
|
99 | const mul = k2.add(len * 2);
|
100 | const a = fetch64(s, 0).mul(k1);
|
101 | const b = fetch64(s, 8);
|
102 | const c = fetch64(s, len - 8).mul(mul);
|
103 | const d = fetch64(s, len - 16).mul(k2);
|
104 | return hashLen16(rotate64(a.add(b), 43).add(rotate64(c, 30)).add(d), a.add(rotate64(b.add(k2), 18)).add(c), mul);
|
105 | }
|
106 | function hashLen33to64(s, len = s.length) {
|
107 | const mul = k2.add(len * 2);
|
108 | const a = fetch64(s, 0).mul(k2);
|
109 | const b = fetch64(s, 8);
|
110 | const c = fetch64(s, len - 8).mul(mul);
|
111 | const d = fetch64(s, len - 16).mul(k2);
|
112 | const y = rotate64(a.add(b), 43).add(rotate64(c, 30)).add(d);
|
113 | const z = hashLen16(y, a.add(rotate64(b.add(k2), 18)).add(c), mul);
|
114 | const e = fetch64(s, 16).mul(mul);
|
115 | const f = fetch64(s, 24);
|
116 | const g = y.add(fetch64(s, len - 32)).mul(mul);
|
117 | const h = z.add(fetch64(s, len - 24)).mul(mul);
|
118 | return hashLen16(rotate64(e.add(f), 43).add(rotate64(g, 30)).add(h), e.add(rotate64(f.add(a), 18)).add(g), mul);
|
119 | }
|
120 | export function fingerPrint64(s, len = s.length) {
|
121 | const seed = Long.fromNumber(81, true);
|
122 | if (len <= 32) {
|
123 | if (len <= 16) {
|
124 | return hashLen0to16(s, len);
|
125 | }
|
126 | else {
|
127 | return hashLen17to32(s, len);
|
128 | }
|
129 | }
|
130 | else if (len <= 64) {
|
131 | return hashLen33to64(s, len);
|
132 | }
|
133 |
|
134 |
|
135 | let x = seed;
|
136 | let y = seed.mul(k1).add(113);
|
137 | let z = shiftMix(y.mul(k2).add(113)).mul(k2);
|
138 | let v = [Long.UZERO, Long.UZERO];
|
139 | let w = [Long.UZERO, Long.UZERO];
|
140 | x = x.mul(k2).add(fetch64(s, 0));
|
141 | let offset = 0;
|
142 |
|
143 | const end = ((len - 1) >> 6) * 64;
|
144 | const last64 = end + ((len - 1) & 63) - 63;
|
145 | do {
|
146 | x = rotate64(x.add(y).add(v[0]).add(fetch64(s, offset + 8)), 37).mul(k1);
|
147 | y = rotate64(y.add(v[1]).add(fetch64(s, offset + 48)), 42).mul(k1);
|
148 | x = x.xor(w[1]);
|
149 | y = y.add(v[0]).add(fetch64(s, offset + 40));
|
150 | z = rotate64(z.add(w[0]), 33).mul(k1);
|
151 | v = weakHashLen32WithSeedsStr(s, offset, v[1].mul(k1), x.add(w[0]));
|
152 | w = weakHashLen32WithSeedsStr(s, offset + 32, z.add(w[1]), y.add(fetch64(s, offset + 16)));
|
153 | [z, x] = [x, z];
|
154 | offset += 64;
|
155 | } while (offset !== end);
|
156 | const mul = k1.add(z.and(0xff).shl(1));
|
157 |
|
158 | offset = last64;
|
159 | w[0] = w[0].add((len - 1) & 63);
|
160 | v[0] = v[0].add(w[0]);
|
161 | w[0] = w[0].add(v[0]);
|
162 | x = rotate64(x.add(y).add(v[0]).add(fetch64(s, offset + 8)), 37).mul(mul);
|
163 | y = rotate64(y.add(v[1]).add(fetch64(s, offset + 48)), 42).mul(mul);
|
164 | x = x.xor(w[1].mul(9));
|
165 | y = y.add(v[0].mul(9).add(fetch64(s, offset + 40)));
|
166 | z = rotate64(z.add(w[0]), 33).mul(mul);
|
167 | v = weakHashLen32WithSeedsStr(s, offset, v[1].mul(mul), x.add(w[0]));
|
168 | w = weakHashLen32WithSeedsStr(s, offset + 32, z.add(w[1]), y.add(fetch64(s, offset + 16)));
|
169 | [z, x] = [x, z];
|
170 | return hashLen16(hashLen16(v[0], w[0], mul).add(shiftMix(y).mul(k0)).add(z), hashLen16(v[1], w[1], mul).add(x), mul);
|
171 | }
|
172 |
|
\ | No newline at end of file |