11cb0ef41Sopenharmony_ci/** 21cb0ef41Sopenharmony_ci * @preserve 31cb0ef41Sopenharmony_ci * JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013) 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * @author <a href="mailto:jensyt@gmail.com">Jens Taylor</a> 61cb0ef41Sopenharmony_ci * @see http://github.com/homebrewing/brauhaus-diff 71cb0ef41Sopenharmony_ci * @author <a href="mailto:gary.court@gmail.com">Gary Court</a> 81cb0ef41Sopenharmony_ci * @see http://github.com/garycourt/murmurhash-js 91cb0ef41Sopenharmony_ci * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a> 101cb0ef41Sopenharmony_ci * @see http://sites.google.com/site/murmurhash/ 111cb0ef41Sopenharmony_ci */ 121cb0ef41Sopenharmony_ci(function(){ 131cb0ef41Sopenharmony_ci var cache; 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci // Call this function without `new` to use the cached object (good for 161cb0ef41Sopenharmony_ci // single-threaded environments), or with `new` to create a new object. 171cb0ef41Sopenharmony_ci // 181cb0ef41Sopenharmony_ci // @param {string} key A UTF-16 or ASCII string 191cb0ef41Sopenharmony_ci // @param {number} seed An optional positive integer 201cb0ef41Sopenharmony_ci // @return {object} A MurmurHash3 object for incremental hashing 211cb0ef41Sopenharmony_ci function MurmurHash3(key, seed) { 221cb0ef41Sopenharmony_ci var m = this instanceof MurmurHash3 ? this : cache; 231cb0ef41Sopenharmony_ci m.reset(seed) 241cb0ef41Sopenharmony_ci if (typeof key === 'string' && key.length > 0) { 251cb0ef41Sopenharmony_ci m.hash(key); 261cb0ef41Sopenharmony_ci } 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci if (m !== this) { 291cb0ef41Sopenharmony_ci return m; 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci }; 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci // Incrementally add a string to this hash 341cb0ef41Sopenharmony_ci // 351cb0ef41Sopenharmony_ci // @param {string} key A UTF-16 or ASCII string 361cb0ef41Sopenharmony_ci // @return {object} this 371cb0ef41Sopenharmony_ci MurmurHash3.prototype.hash = function(key) { 381cb0ef41Sopenharmony_ci var h1, k1, i, top, len; 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci len = key.length; 411cb0ef41Sopenharmony_ci this.len += len; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci k1 = this.k1; 441cb0ef41Sopenharmony_ci i = 0; 451cb0ef41Sopenharmony_ci switch (this.rem) { 461cb0ef41Sopenharmony_ci case 0: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) : 0; 471cb0ef41Sopenharmony_ci case 1: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 8 : 0; 481cb0ef41Sopenharmony_ci case 2: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 16 : 0; 491cb0ef41Sopenharmony_ci case 3: 501cb0ef41Sopenharmony_ci k1 ^= len > i ? (key.charCodeAt(i) & 0xff) << 24 : 0; 511cb0ef41Sopenharmony_ci k1 ^= len > i ? (key.charCodeAt(i++) & 0xff00) >> 8 : 0; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci this.rem = (len + this.rem) & 3; // & 3 is same as % 4 551cb0ef41Sopenharmony_ci len -= this.rem; 561cb0ef41Sopenharmony_ci if (len > 0) { 571cb0ef41Sopenharmony_ci h1 = this.h1; 581cb0ef41Sopenharmony_ci while (1) { 591cb0ef41Sopenharmony_ci k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; 601cb0ef41Sopenharmony_ci k1 = (k1 << 15) | (k1 >>> 17); 611cb0ef41Sopenharmony_ci k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci h1 ^= k1; 641cb0ef41Sopenharmony_ci h1 = (h1 << 13) | (h1 >>> 19); 651cb0ef41Sopenharmony_ci h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci if (i >= len) { 681cb0ef41Sopenharmony_ci break; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci k1 = ((key.charCodeAt(i++) & 0xffff)) ^ 721cb0ef41Sopenharmony_ci ((key.charCodeAt(i++) & 0xffff) << 8) ^ 731cb0ef41Sopenharmony_ci ((key.charCodeAt(i++) & 0xffff) << 16); 741cb0ef41Sopenharmony_ci top = key.charCodeAt(i++); 751cb0ef41Sopenharmony_ci k1 ^= ((top & 0xff) << 24) ^ 761cb0ef41Sopenharmony_ci ((top & 0xff00) >> 8); 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci k1 = 0; 801cb0ef41Sopenharmony_ci switch (this.rem) { 811cb0ef41Sopenharmony_ci case 3: k1 ^= (key.charCodeAt(i + 2) & 0xffff) << 16; 821cb0ef41Sopenharmony_ci case 2: k1 ^= (key.charCodeAt(i + 1) & 0xffff) << 8; 831cb0ef41Sopenharmony_ci case 1: k1 ^= (key.charCodeAt(i) & 0xffff); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci this.h1 = h1; 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci this.k1 = k1; 901cb0ef41Sopenharmony_ci return this; 911cb0ef41Sopenharmony_ci }; 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Get the result of this hash 941cb0ef41Sopenharmony_ci // 951cb0ef41Sopenharmony_ci // @return {number} The 32-bit hash 961cb0ef41Sopenharmony_ci MurmurHash3.prototype.result = function() { 971cb0ef41Sopenharmony_ci var k1, h1; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci k1 = this.k1; 1001cb0ef41Sopenharmony_ci h1 = this.h1; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci if (k1 > 0) { 1031cb0ef41Sopenharmony_ci k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; 1041cb0ef41Sopenharmony_ci k1 = (k1 << 15) | (k1 >>> 17); 1051cb0ef41Sopenharmony_ci k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; 1061cb0ef41Sopenharmony_ci h1 ^= k1; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci h1 ^= this.len; 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci h1 ^= h1 >>> 16; 1121cb0ef41Sopenharmony_ci h1 = (h1 * 0xca6b + (h1 & 0xffff) * 0x85eb0000) & 0xffffffff; 1131cb0ef41Sopenharmony_ci h1 ^= h1 >>> 13; 1141cb0ef41Sopenharmony_ci h1 = (h1 * 0xae35 + (h1 & 0xffff) * 0xc2b20000) & 0xffffffff; 1151cb0ef41Sopenharmony_ci h1 ^= h1 >>> 16; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci return h1 >>> 0; 1181cb0ef41Sopenharmony_ci }; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci // Reset the hash object for reuse 1211cb0ef41Sopenharmony_ci // 1221cb0ef41Sopenharmony_ci // @param {number} seed An optional positive integer 1231cb0ef41Sopenharmony_ci MurmurHash3.prototype.reset = function(seed) { 1241cb0ef41Sopenharmony_ci this.h1 = typeof seed === 'number' ? seed : 0; 1251cb0ef41Sopenharmony_ci this.rem = this.k1 = this.len = 0; 1261cb0ef41Sopenharmony_ci return this; 1271cb0ef41Sopenharmony_ci }; 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci // A cached object to use. This can be safely used if you're in a single- 1301cb0ef41Sopenharmony_ci // threaded environment, otherwise you need to create new hashes to use. 1311cb0ef41Sopenharmony_ci cache = new MurmurHash3(); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci if (typeof(module) != 'undefined') { 1341cb0ef41Sopenharmony_ci module.exports = MurmurHash3; 1351cb0ef41Sopenharmony_ci } else { 1361cb0ef41Sopenharmony_ci this.MurmurHash3 = MurmurHash3; 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci}()); 139