UNPKG

unreal.js

Version:

A pak reader for games like VALORANT & Fortnite written in Node.JS

263 lines (262 loc) 11.2 kB
"use strict"; /* * Copyright (C) 2012 tamtam180 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CityHash = void 0; const Long = __importStar(require("long")); /** * @author tamtam180 - kirscheless at gmail.com * @author modified by amrsatrio * @author ported by Sprayxe * @see <a href="https://opensource.googleblog.com/2011/04/introducing-cityhash.html">https://opensource.googleblog.com/2011/04/introducing-cityhash.html</a> * @see <a href="https://github.com/google/cityhash">https://github.com/google/cityhash</a> */ class CityHash { static toLongLE(b, i) { return Long.fromNumber((b[i + 7]), true).shl(56) .add(Long.fromNumber((b[i + 6] & 255), true).shl(48)) .add(Long.fromNumber((b[i + 5] & 255), true).shl(40)) .add(Long.fromNumber((b[i + 4] & 255), true).shl(32)) .add(Long.fromNumber((b[i + 3] & 255), true).shl(24)) .add(Long.fromNumber((b[i + 2] & 255), true).shl(16)) .add(Long.fromNumber((b[i + 1] & 255), true).shl(8)) .add(b[i] & 255); } static toIntLE(b, i) { return (((b[i + 3] & 255) << 24) + ((b[i + 2] & 255) << 16) + ((b[i + 1] & 255) << 8) + (b[i] & 255)); } static bswap64(value) { const b1 = value.and(0xff); const b2 = (value.shr(8)).and(0xff); const b3 = (value.shr(16)).and(0xff); const b4 = (value.shr(24)).and(0xff); const b5 = (value.shr(32)).and(0xff); const b6 = (value.shr(40)).and(0xff); const b7 = (value.shr(48)).and(0xff); const b8 = (value.shr(56)).and(0xff); return (b1.shl(56)) .or(b2.shl(48)) .or(b3.shl(40)) .or(b4.shl(32)) .or(b5.shl(24)) .or(b6.shl(16)) .or(b7.shl(8)) .or(b8); } static fetch64(s, pos) { return this.toLongLE(s, pos); } static fetch32(s, pos) { return this.toIntLE(s, pos); } /** * Bitwise right rotate. Normally this will compile to a single * instruction, especially if the shift is a manifest constant. */ static rotate(val, shift) { // Avoid shifting by 64: doing so yields an undefined result. return shift === 0 ? val : val.shru(shift).or(val.shl(64 - shift)); } static shiftMix(val) { return val.xor(val.shru(47)); } static hashLen16(u, v) { return this.cityHash128to64(u, v); } static hashLen16Mul(u, v, mul) { // Murmur-inspired hashing. let a = u.xor(v).multiply(mul); a = a.xor(a.shru(47)); let b = v.xor(a).multiply(mul); b = b.xor(b.shru(47)); b = b.multiply(mul); return b; } static hashLen0to16(s, pos, len) { if (len > 8) { const mul = this.k2.add(len * 2); const a = this.fetch64(s, pos).add(this.k2); const b = this.fetch64(s, pos + len - 8); const c = this.rotate(b, 37).multiply(mul).add(a); const d = (this.rotate(a, 25).add(b)).multiply(mul); return this.hashLen16Mul(c, d, mul); } if (len >= 4) { const mul = this.k2.add(len * 2); const a = this.fetch32(s, pos); return this.hashLen16Mul(Long.fromNumber(len + (a << 3), true), Long.fromNumber(this.fetch32(s, pos + len - 4), true), mul); } if (len > 0) { const a = s[pos] & 0xFF; const b = s[pos + (len >>> 1)] & 0xFF; const c = s[pos + len - 1] & 0xFF; const y = a + (b << 8); const z = len + (c << 2); return this.shiftMix(this.k2.multiply(y).xor(this.k0.multiply(z))).multiply(this.k2); } return this.k2; } /** * This probably works well for 16-byte strings as well, but it may be overkill * in that case. */ static hashLen17to32(s, pos, len) { const mul = this.k2.add(len * 2); const a = this.fetch64(s, pos).multiply(this.k1); const b = this.fetch64(s, pos + 8); const c = this.fetch64(s, pos + len - 8).multiply(mul); const d = this.fetch64(s, pos + len - 16).multiply(this.k2); return this.hashLen16Mul(this.rotate(a.add(b), 43).add(this.rotate(c, 30).add(d)), a.add(this.rotate(b.add(this.k2), 18)).add(c), mul); } /** * Return a 16-byte hash for 48 bytes. Quick and dirty. * Callers do best to use "random-looking" values for a and b. */ static weakHashLen32WithSeeds0(w, x, y, z, a, b) { a = a.add(w); b = this.rotate(b.add(a).add(z), 21); const c = a; a = a.add(x); a = a.add(y); b = b.add(this.rotate(a, 44)); return [a.add(z), b.add(c)]; } /** * Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. */ static weakHashLen32WithSeeds1(s, pos, a, b) { return this.weakHashLen32WithSeeds0(this.fetch64(s, pos), this.fetch64(s, pos + 8), this.fetch64(s, pos + 16), this.fetch64(s, pos + 24), a, b); } /** * Return an 8-byte hash for 33 to 64 bytes. */ static hashLen33to64(s, pos, len) { const mul = this.k2.add(len * 2); let a = this.fetch64(s, pos).multiply(this.k2); let b = this.fetch64(s, pos + 8); const c = this.fetch64(s, pos + len - 24); const d = this.fetch64(s, pos + len - 32); const e = this.fetch64(s, pos + 16).multiply(this.k2); const f = this.fetch64(s, pos + 24).multiply(9); const g = this.fetch64(s, pos + len - 8); const h = this.fetch64(s, pos + len - 16).multiply(mul); const u = this.rotate(a.add(g), 43).add(this.rotate(b, 30).add(c).multiply(9)); const v = a.add(g).xor(d).add(f).add(1); const w = this.bswap64(u.add(v).multiply(mul)).add(h); const x = this.rotate(e.add(f), 42).add(c); const y = this.bswap64(v.add(w).multiply(mul)).add(g).multiply(mul); const z = e.add(f).add(c); a = this.bswap64(x.add(z).multiply(mul).add(y)).add(b); b = this.shiftMix(z.add(a).multiply(mul).add(d).add(h)).multiply(mul); return b.add(x); } /** * Hash function for a byte array. */ static cityHash64(s, pos, len) { if (len <= 32) { if (len <= 16) { return this.hashLen0to16(s, pos, len); } else { return this.hashLen17to32(s, pos, len); } } else if (len <= 64) { return this.hashLen33to64(s, pos, len); } // For strings over 64 bytes we hash the end first, and then as we // loop we keep 56 bytes of state: v, w, x, y, and z. let x = this.fetch64(s, pos + len - 40); let y = this.fetch64(s, pos + len - 16).add(this.fetch64(s, pos + len - 56)); let z = this.hashLen16(this.fetch64(s, pos + len - 48).add(len), this.fetch64(s, pos + len - 24)); let v = this.weakHashLen32WithSeeds1(s, pos + len - 64, Long.fromNumber(len, true), z); let w = this.weakHashLen32WithSeeds1(s, pos + len - 32, y.add(this.k1), x); x = x.multiply(this.k1).add(this.fetch64(s, pos)); // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. len = (len - 1) & (~63); do { x = this.rotate(x.add(y).add(v[0]).add(this.fetch64(s, pos + 8)), 37).multiply(this.k1); y = this.rotate(y.add(v[1]).add(this.fetch64(s, pos + 48)), 42).multiply(this.k1); x = x.xor(w[1]); y = y.add(v[0].add(this.fetch64(s, pos + 40))); z = this.rotate(z.add(w[0]), 33).multiply(this.k1); v = this.weakHashLen32WithSeeds1(s, pos, v[1].multiply(this.k1), x.add(w[0])); w = this.weakHashLen32WithSeeds1(s, pos + 32, z.add(w[1]), y.add(this.fetch64(s, pos + 16))); { const swap = z; z = x; x = swap; } pos += 64; len -= 64; } while (len !== 0); return this.hashLen16(this.hashLen16(v[0], w[0]).add(this.shiftMix(y).multiply(this.k1)).add(z), this.hashLen16(v[1], w[1]).add(x)); } /** * Hash function for a byte array. For convenience, a 64-bit seed is also * hashed into the result. */ static cityHash64WithSeed(s, pos, len, seed) { return this.cityHash64WithSeeds(s, pos, len, this.k2, seed); } static cityHash64WithSeeds(s, pos, len, seed0, seed1) { return this.hashLen16(this.cityHash64(s, pos, len).subtract(seed0), seed1); } /** * Hash function for a byte array. Most useful in 32-bit binaries. */ static cityHash32(s, pos, len) { return Long.fromNumber(-1); } /** * Hash 128 input bits down to 64 bits of output. * This is intended to be a reasonably good hash function. */ static cityHash128to64(u, v) { const kMul = Long.fromString("11376068507788127593", true); let a = u.xor(v).multiply(kMul); a = a.xor(a.shru(47)); let b = v.xor(a).multiply(kMul); b = b.xor(b.shru(47)); b = b.multiply(kMul); return b; } } exports.CityHash = CityHash; // Some primes between 2^63 and 2^64 for various uses. CityHash.k0 = Long.fromString("14097894508562428199", true); CityHash.k1 = Long.fromString("13011662864482103923", true); CityHash.k2 = Long.fromString("11160318154034397263", true);