From 4c8ad76035a17bf3e8f7d6b2de6474af4f02af23 Mon Sep 17 00:00:00 2001 From: rizrmd Date: Thu, 18 Jul 2024 16:18:12 +0000 Subject: [PATCH] add hash-sum --- utils/hash-sum.ts | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 utils/hash-sum.ts diff --git a/utils/hash-sum.ts b/utils/hash-sum.ts new file mode 100755 index 0000000..a745d11 --- /dev/null +++ b/utils/hash-sum.ts @@ -0,0 +1,71 @@ +function pad(hash: string, len: number): string { + while (hash.length < len) { + hash = "0" + hash; + } + return hash; +} + +function fold(hash: number, text: string): number { + let i: number; + let chr: number; + let len: number; + if (text.length === 0) { + return hash; + } + for (i = 0, len = text.length; i < len; i++) { + chr = text.charCodeAt(i); + hash = (hash << 5) - hash + chr; + hash |= 0; // Convert to 32bit integer + } + return hash < 0 ? hash * -2 : hash; +} + +function foldObject(hash: number, o: any, seen: any[]): number { + return Object.keys(o).sort().reduce(foldKey, hash); + function foldKey(hash: number, key: string): number { + return foldValue(hash, o[key], key, seen); + } +} + +function foldValue( + input: number, + value: any, + key: string, + seen: any[] +): number { + let hash = fold(fold(fold(input, key), toString(value)), typeof value); + if (value === null) { + return fold(hash, "null"); + } + if (value === undefined) { + return fold(hash, "undefined"); + } + if (typeof value === "object" || typeof value === "function") { + if (seen.indexOf(value) !== -1) { + return fold(hash, "[Circular]" + key); + } + seen.push(value); + + const objHash = foldObject(hash, value, seen); + + if (!("valueOf" in value) || typeof value.valueOf !== "function") { + return objHash; + } + + try { + return fold(objHash, String(value.valueOf())); + } catch (err: any) { + return fold(objHash, "[valueOf exception]" + (err.stack || err.message)); + } + } + return fold(hash, value.toString()); +} + +function toString(o: any): string { + return Object.prototype.toString.call(o); +} + +export function hashSum(o: any): string { + return pad(foldValue(0, o, "", []).toString(16), 8); +} +