You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.5 KiB
69 lines
1.5 KiB
'use strict'; |
|
|
|
function pad (hash, len) { |
|
while (hash.length < len) { |
|
hash = '0' + hash; |
|
} |
|
return hash; |
|
} |
|
|
|
function fold (hash, text) { |
|
var i; |
|
var chr; |
|
var len; |
|
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; |
|
} |
|
return hash < 0 ? hash * -2 : hash; |
|
} |
|
|
|
function foldObject (hash, o, seen) { |
|
return Object.keys(o).sort().reduce(foldKey, hash); |
|
function foldKey (hash, key) { |
|
return foldValue(hash, o[key], key, seen); |
|
} |
|
} |
|
|
|
function foldValue (input, value, key, seen) { |
|
var 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); |
|
|
|
var objHash = foldObject(hash, value, seen) |
|
|
|
if (!('valueOf' in value) || typeof value.valueOf !== 'function') { |
|
return objHash; |
|
} |
|
|
|
try { |
|
return fold(objHash, String(value.valueOf())) |
|
} catch (err) { |
|
return fold(objHash, '[valueOf exception]' + (err.stack || err.message)) |
|
} |
|
} |
|
return fold(hash, value.toString()); |
|
} |
|
|
|
function toString (o) { |
|
return Object.prototype.toString.call(o); |
|
} |
|
|
|
function sum (o) { |
|
return pad(foldValue(0, o, '', []).toString(16), 8); |
|
} |
|
|
|
module.exports = sum;
|
|
|