hash-sum.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. 'use strict';
  2. function pad (hash, len) {
  3. while (hash.length < len) {
  4. hash = '0' + hash;
  5. }
  6. return hash;
  7. }
  8. function fold (hash, text) {
  9. var i;
  10. var chr;
  11. var len;
  12. if (text.length === 0) {
  13. return hash;
  14. }
  15. for (i = 0, len = text.length; i < len; i++) {
  16. chr = text.charCodeAt(i);
  17. hash = ((hash << 5) - hash) + chr;
  18. hash |= 0;
  19. }
  20. return hash < 0 ? hash * -2 : hash;
  21. }
  22. function foldObject (hash, o, seen) {
  23. return Object.keys(o).sort().reduce(foldKey, hash);
  24. function foldKey (hash, key) {
  25. return foldValue(hash, o[key], key, seen);
  26. }
  27. }
  28. function foldValue (input, value, key, seen) {
  29. var hash = fold(fold(fold(input, key), toString(value)), typeof value);
  30. if (value === null) {
  31. return fold(hash, 'null');
  32. }
  33. if (value === undefined) {
  34. return fold(hash, 'undefined');
  35. }
  36. if (typeof value === 'object' || typeof value === 'function') {
  37. if (seen.indexOf(value) !== -1) {
  38. return fold(hash, '[Circular]' + key);
  39. }
  40. seen.push(value);
  41. var objHash = foldObject(hash, value, seen)
  42. if (!('valueOf' in value) || typeof value.valueOf !== 'function') {
  43. return objHash;
  44. }
  45. try {
  46. return fold(objHash, String(value.valueOf()))
  47. } catch (err) {
  48. return fold(objHash, '[valueOf exception]' + (err.stack || err.message))
  49. }
  50. }
  51. return fold(hash, value.toString());
  52. }
  53. function toString (o) {
  54. return Object.prototype.toString.call(o);
  55. }
  56. function sum (o) {
  57. return pad(foldValue(0, o, '', []).toString(16), 8);
  58. }
  59. module.exports = sum;