transitory
Version:
In-memory cache with high hit rates via LFU eviction. Supports time-based expiration, automatic loading and metrics.
92 lines • 3.32 kB
JavaScript
const C1 = 0xcc9e2d51;
const C2 = 0x1b873593;
/**
* Tiny helper to perform a multiply that's slightly safer to use for hashing.
*
* @param a -
* @param b -
* @returns a * b
*/
function safeishMultiply(a, b) {
return ((a & 0xffff) * b) + ((((a >>> 16) * b) & 0xffff) << 16);
}
/**
* Utility for calculating stable hashcodes for keys used in a cache.
*
* @param obj -
* object to hash
* @param seed -
* seed to hash with
* @returns
* hash code
*/
export function hashcode(obj, seed = 0) {
switch (typeof obj) {
case 'string':
{
let hash = seed;
const n = obj.length & ~0x3;
for (let i = 0; i < n; i += 4) {
let k1 = ((obj.charCodeAt(i) & 0xffff)) |
((obj.charCodeAt(i + 1) & 0xffff) << 8) |
((obj.charCodeAt(i + 2) & 0xffff) << 16) |
((obj.charCodeAt(i + 3) & 0xffff) << 24);
k1 = safeishMultiply(k1, C1);
k1 = (k1 << 15) | (k1 >>> 17);
k1 = safeishMultiply(k1, C2);
hash ^= k1;
hash = (hash << 13) | (hash >>> 19);
hash = (hash * 5) + 0xe6546b64;
}
{
let k1 = 0;
switch (obj.length & 3) {
case 3:
k1 ^= (obj.charCodeAt(n + 2) & 0xffff) << 16;
// eslint-disable-next-line no-fallthrough
case 2:
k1 ^= (obj.charCodeAt(n + 1) & 0xffff) << 8;
// eslint-disable-next-line no-fallthrough
case 1:
k1 ^= (obj.charCodeAt(n) & 0xffff);
k1 = safeishMultiply(k1, C1);
k1 = (k1 << 15) | (k1 >>> 17);
k1 = safeishMultiply(k1, C2);
hash ^= k1;
}
}
hash ^= obj.length;
hash ^= hash >>> 16;
hash = safeishMultiply(hash, 0x85ebca6b);
hash ^= hash >>> 13;
hash = safeishMultiply(hash, 0xc2b2ae35);
hash ^= hash >>> 16;
return hash >>> 0;
}
case 'number':
{
let hash = obj;
hash = safeishMultiply(hash, C1);
hash = (hash << 15) | (hash >>> 17);
hash = safeishMultiply(hash, C2);
hash = (hash << 13) | (hash >>> 19);
hash = (hash * 5) + 0xe6546b64;
hash ^= hash >>> 16;
hash = safeishMultiply(hash, 0x85ebca6b);
hash ^= hash >>> 13;
hash = safeishMultiply(hash, 0xc2b2ae35);
hash ^= hash >>> 16;
hash ^= 1;
return hash >>> 0;
}
case 'boolean':
{
return obj ? 1231 : 1237;
}
case 'undefined':
return 0;
default:
throw new Error('The given value can not be used as a key in a cache, value was: ' + String(obj));
}
}
//# sourceMappingURL=hashcode.js.map