refactored Utils.js to use es6 classes
use const/let for better scoping use jsdoc
This commit is contained in:
parent
5b607b34ba
commit
dadd69ef97
|
@ -10,15 +10,15 @@ function arrayToString(a) {
|
|||
String.prototype.seed = String.prototype.seed || Math.round(Math.random() * Math.pow(2, 32));
|
||||
|
||||
String.prototype.hashCode = function () {
|
||||
var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i,
|
||||
key = this.toString();
|
||||
const key = this.toString();
|
||||
let h1b, k1;
|
||||
|
||||
remainder = key.length & 3; // key.length % 4
|
||||
bytes = key.length - remainder;
|
||||
h1 = String.prototype.seed;
|
||||
c1 = 0xcc9e2d51;
|
||||
c2 = 0x1b873593;
|
||||
i = 0;
|
||||
const remainder = key.length & 3; // key.length % 4
|
||||
const bytes = key.length - remainder;
|
||||
let h1 = String.prototype.seed;
|
||||
const c1 = 0xcc9e2d51;
|
||||
const c2 = 0x1b873593;
|
||||
let i = 0;
|
||||
|
||||
while (i < bytes) {
|
||||
k1 =
|
||||
|
@ -73,337 +73,336 @@ function standardHashCodeFunction(a) {
|
|||
return a.hashCode();
|
||||
}
|
||||
|
||||
function Set(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
}
|
||||
class Set {
|
||||
constructor(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
}
|
||||
|
||||
Object.defineProperty(Set.prototype, "length", {
|
||||
get: function () {
|
||||
var l = 0;
|
||||
for (var key in this.data) {
|
||||
add(value) {
|
||||
const hash = this.hashFunction(value);
|
||||
const key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
const values = this.data[key];
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
values.push(value);
|
||||
return value;
|
||||
} else {
|
||||
this.data[key] = [value];
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
contains(value) {
|
||||
return this.get(value) != null;
|
||||
}
|
||||
|
||||
get(value) {
|
||||
const hash = this.hashFunction(value);
|
||||
const key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
const values = this.data[key];
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
values() {
|
||||
let l = [];
|
||||
for (const key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return arrayToString(this.values());
|
||||
}
|
||||
|
||||
get length(){
|
||||
let l = 0;
|
||||
for (const key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l + this.data[key].length;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
Set.prototype.add = function (value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var values = this.data[key];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
values.push(value);
|
||||
return value;
|
||||
} else {
|
||||
this.data[key] = [value];
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
Set.prototype.contains = function (value) {
|
||||
return this.get(value) != null;
|
||||
};
|
||||
|
||||
Set.prototype.get = function (value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var values = this.data[key];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Set.prototype.values = function () {
|
||||
var l = [];
|
||||
for (var key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
Set.prototype.toString = function () {
|
||||
return arrayToString(this.values());
|
||||
};
|
||||
|
||||
function BitSet() {
|
||||
this.data = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
BitSet.prototype.add = function (value) {
|
||||
this.data[value] = true;
|
||||
};
|
||||
|
||||
BitSet.prototype.or = function (set) {
|
||||
var bits = this;
|
||||
Object.keys(set.data).map(function (alt) {
|
||||
bits.add(alt);
|
||||
});
|
||||
};
|
||||
|
||||
BitSet.prototype.remove = function (value) {
|
||||
delete this.data[value];
|
||||
};
|
||||
|
||||
BitSet.prototype.contains = function (value) {
|
||||
return this.data[value] === true;
|
||||
};
|
||||
|
||||
BitSet.prototype.values = function () {
|
||||
return Object.keys(this.data);
|
||||
};
|
||||
|
||||
BitSet.prototype.minValue = function () {
|
||||
return Math.min.apply(null, this.values());
|
||||
};
|
||||
|
||||
BitSet.prototype.hashCode = function () {
|
||||
var hash = new Hash();
|
||||
hash.update(this.values());
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
BitSet.prototype.equals = function (other) {
|
||||
if (!(other instanceof BitSet)) {
|
||||
return false;
|
||||
class BitSet {
|
||||
constructor() {
|
||||
this.data = [];
|
||||
}
|
||||
return this.hashCode() === other.hashCode();
|
||||
};
|
||||
|
||||
Object.defineProperty(BitSet.prototype, "length", {
|
||||
get: function () {
|
||||
add(value) {
|
||||
this.data[value] = true;
|
||||
}
|
||||
|
||||
or(set) {
|
||||
const bits = this;
|
||||
Object.keys(set.data).map(function (alt) {
|
||||
bits.add(alt);
|
||||
});
|
||||
}
|
||||
|
||||
remove(value) {
|
||||
delete this.data[value];
|
||||
}
|
||||
|
||||
contains(value) {
|
||||
return this.data[value] === true;
|
||||
}
|
||||
|
||||
values() {
|
||||
return Object.keys(this.data);
|
||||
}
|
||||
|
||||
minValue() {
|
||||
return Math.min.apply(null, this.values());
|
||||
}
|
||||
|
||||
hashCode() {
|
||||
const hash = new Hash();
|
||||
hash.update(this.values());
|
||||
return hash.finish();
|
||||
}
|
||||
|
||||
equals(other) {
|
||||
if (!(other instanceof BitSet)) {
|
||||
return false;
|
||||
}
|
||||
return this.hashCode() === other.hashCode();
|
||||
}
|
||||
|
||||
toString() {
|
||||
return "{" + this.values().join(", ") + "}";
|
||||
}
|
||||
|
||||
get length(){
|
||||
return this.values().length;
|
||||
}
|
||||
});
|
||||
|
||||
BitSet.prototype.toString = function () {
|
||||
return "{" + this.values().join(", ") + "}";
|
||||
};
|
||||
|
||||
function Map(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
Object.defineProperty(Map.prototype, "length", {
|
||||
get: function () {
|
||||
var l = 0;
|
||||
for (var hashKey in this.data) {
|
||||
|
||||
class Map {
|
||||
constructor(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
}
|
||||
|
||||
put(key, value) {
|
||||
const hashKey = "hash_" + this.hashFunction(key);
|
||||
if (hashKey in this.data) {
|
||||
const entries = this.data[hashKey];
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key)) {
|
||||
const oldValue = entry.value;
|
||||
entry.value = value;
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
entries.push({key:key, value:value});
|
||||
return value;
|
||||
} else {
|
||||
this.data[hashKey] = [{key:key, value:value}];
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
containsKey(key) {
|
||||
const hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
const entries = this.data[hashKey];
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
const hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
const entries = this.data[hashKey];
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
entries() {
|
||||
let l = [];
|
||||
for (const key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
getKeys() {
|
||||
return this.entries().map(function(e) {
|
||||
return e.key;
|
||||
});
|
||||
}
|
||||
|
||||
getValues() {
|
||||
return this.entries().map(function(e) {
|
||||
return e.value;
|
||||
});
|
||||
}
|
||||
|
||||
toString() {
|
||||
const ss = this.entries().map(function(entry) {
|
||||
return '{' + entry.key + ':' + entry.value + '}';
|
||||
});
|
||||
return '[' + ss.join(", ") + ']';
|
||||
}
|
||||
|
||||
get length(){
|
||||
let l = 0;
|
||||
for (const hashKey in this.data) {
|
||||
if (hashKey.indexOf("hash_") === 0) {
|
||||
l = l + this.data[hashKey].length;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Map.prototype.put = function (key, value) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if (hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key)) {
|
||||
var oldValue = entry.value;
|
||||
entry.value = value;
|
||||
return oldValue;
|
||||
|
||||
class AltDict {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
get(key) {
|
||||
key = "k-" + key;
|
||||
if (key in this.data) {
|
||||
return this.data[key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
put(key, value) {
|
||||
key = "k-" + key;
|
||||
this.data[key] = value;
|
||||
}
|
||||
|
||||
values() {
|
||||
const data = this.data;
|
||||
const keys = Object.keys(this.data);
|
||||
return keys.map(function (key) {
|
||||
return data[key];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DoubleDict {
|
||||
constructor(defaultMapCtor) {
|
||||
this.defaultMapCtor = defaultMapCtor || Map;
|
||||
this.cacheMap = new this.defaultMapCtor();
|
||||
}
|
||||
|
||||
get(a, b) {
|
||||
const d = this.cacheMap.get(a) || null;
|
||||
return d === null ? null : (d.get(b) || null);
|
||||
}
|
||||
|
||||
set(a, b, o) {
|
||||
let d = this.cacheMap.get(a) || null;
|
||||
if (d === null) {
|
||||
d = new this.defaultMapCtor();
|
||||
this.cacheMap.put(a, d);
|
||||
}
|
||||
d.put(b, o);
|
||||
}
|
||||
}
|
||||
|
||||
class Hash {
|
||||
constructor() {
|
||||
this.count = 0;
|
||||
this.hash = 0;
|
||||
}
|
||||
|
||||
update() {
|
||||
for(let i=0;i<arguments.length;i++) {
|
||||
const value = arguments[i];
|
||||
if (value == null)
|
||||
continue;
|
||||
if(Array.isArray(value))
|
||||
this.update.apply(this, value);
|
||||
else {
|
||||
let k = 0;
|
||||
switch (typeof(value)) {
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
continue;
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
k = value;
|
||||
break;
|
||||
case 'string':
|
||||
k = value.hashCode();
|
||||
break;
|
||||
default:
|
||||
if(value.updateHashCode)
|
||||
value.updateHashCode(this);
|
||||
else
|
||||
console.log("No updateHashCode for " + value.toString())
|
||||
continue;
|
||||
}
|
||||
k = k * 0xCC9E2D51;
|
||||
k = (k << 15) | (k >>> (32 - 15));
|
||||
k = k * 0x1B873593;
|
||||
this.count = this.count + 1;
|
||||
let hash = this.hash ^ k;
|
||||
hash = (hash << 13) | (hash >>> (32 - 13));
|
||||
hash = hash * 5 + 0xE6546B64;
|
||||
this.hash = hash;
|
||||
}
|
||||
}
|
||||
entries.push({key:key, value:value});
|
||||
return value;
|
||||
} else {
|
||||
this.data[hashKey] = [{key:key, value:value}];
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
Map.prototype.containsKey = function (key) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return true;
|
||||
}
|
||||
finish() {
|
||||
let hash = this.hash ^ (this.count * 4);
|
||||
hash = hash ^ (hash >>> 16);
|
||||
hash = hash * 0x85EBCA6B;
|
||||
hash = hash ^ (hash >>> 13);
|
||||
hash = hash * 0xC2B2AE35;
|
||||
hash = hash ^ (hash >>> 16);
|
||||
return hash;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Map.prototype.get = function (key) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Map.prototype.entries = function () {
|
||||
var l = [];
|
||||
for (var key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.getKeys = function () {
|
||||
return this.entries().map(function(e) {
|
||||
return e.key;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.getValues = function () {
|
||||
return this.entries().map(function(e) {
|
||||
return e.value;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.toString = function () {
|
||||
var ss = this.entries().map(function(entry) {
|
||||
return '{' + entry.key + ':' + entry.value + '}';
|
||||
});
|
||||
return '[' + ss.join(", ") + ']';
|
||||
};
|
||||
|
||||
|
||||
function AltDict() {
|
||||
this.data = {};
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
AltDict.prototype.get = function (key) {
|
||||
key = "k-" + key;
|
||||
if (key in this.data) {
|
||||
return this.data[key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
AltDict.prototype.put = function (key, value) {
|
||||
key = "k-" + key;
|
||||
this.data[key] = value;
|
||||
};
|
||||
|
||||
AltDict.prototype.values = function () {
|
||||
var data = this.data;
|
||||
var keys = Object.keys(this.data);
|
||||
return keys.map(function (key) {
|
||||
return data[key];
|
||||
});
|
||||
};
|
||||
|
||||
function DoubleDict(defaultMapCtor) {
|
||||
this.defaultMapCtor = defaultMapCtor || Map;
|
||||
this.cacheMap = new this.defaultMapCtor();
|
||||
return this;
|
||||
}
|
||||
|
||||
function Hash() {
|
||||
this.count = 0;
|
||||
this.hash = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Hash.prototype.update = function () {
|
||||
for(var i=0;i<arguments.length;i++) {
|
||||
var value = arguments[i];
|
||||
if (value == null)
|
||||
continue;
|
||||
if(Array.isArray(value))
|
||||
this.update.apply(this, value);
|
||||
else {
|
||||
var k = 0;
|
||||
switch (typeof(value)) {
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
continue;
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
k = value;
|
||||
break;
|
||||
case 'string':
|
||||
k = value.hashCode();
|
||||
break;
|
||||
default:
|
||||
if(value.updateHashCode)
|
||||
value.updateHashCode(this);
|
||||
else
|
||||
console.log("No updateHashCode for " + value.toString())
|
||||
continue;
|
||||
}
|
||||
k = k * 0xCC9E2D51;
|
||||
k = (k << 15) | (k >>> (32 - 15));
|
||||
k = k * 0x1B873593;
|
||||
this.count = this.count + 1;
|
||||
var hash = this.hash ^ k;
|
||||
hash = (hash << 13) | (hash >>> (32 - 13));
|
||||
hash = hash * 5 + 0xE6546B64;
|
||||
this.hash = hash;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Hash.prototype.finish = function () {
|
||||
var hash = this.hash ^ (this.count * 4);
|
||||
hash = hash ^ (hash >>> 16);
|
||||
hash = hash * 0x85EBCA6B;
|
||||
hash = hash ^ (hash >>> 13);
|
||||
hash = hash * 0xC2B2AE35;
|
||||
hash = hash ^ (hash >>> 16);
|
||||
return hash;
|
||||
};
|
||||
|
||||
function hashStuff() {
|
||||
var hash = new Hash();
|
||||
const hash = new Hash();
|
||||
hash.update.apply(hash, arguments);
|
||||
return hash.finish();
|
||||
}
|
||||
|
||||
DoubleDict.prototype.get = function (a, b) {
|
||||
var d = this.cacheMap.get(a) || null;
|
||||
return d === null ? null : (d.get(b) || null);
|
||||
};
|
||||
|
||||
DoubleDict.prototype.set = function (a, b, o) {
|
||||
var d = this.cacheMap.get(a) || null;
|
||||
if (d === null) {
|
||||
d = new this.defaultMapCtor();
|
||||
this.cacheMap.put(a, d);
|
||||
}
|
||||
d.put(b, o);
|
||||
};
|
||||
|
||||
|
||||
function escapeWhitespace(s, escapeSpaces) {
|
||||
s = s.replace(/\t/g, "\\t")
|
||||
|
@ -419,33 +418,34 @@ function titleCase(str) {
|
|||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function equalArrays(a, b)
|
||||
{
|
||||
function equalArrays(a, b) {
|
||||
if (!Array.isArray(a) || !Array.isArray(b))
|
||||
return false;
|
||||
if (a == b)
|
||||
return true;
|
||||
if (a.length != b.length)
|
||||
return false;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] == b[i])
|
||||
continue;
|
||||
if (!a[i].equals(b[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
exports.Hash = Hash;
|
||||
exports.Set = Set;
|
||||
exports.Map = Map;
|
||||
exports.BitSet = BitSet;
|
||||
exports.AltDict = AltDict;
|
||||
exports.DoubleDict = DoubleDict;
|
||||
exports.hashStuff = hashStuff;
|
||||
exports.escapeWhitespace = escapeWhitespace;
|
||||
exports.arrayToString = arrayToString;
|
||||
exports.titleCase = titleCase;
|
||||
exports.equalArrays = equalArrays;
|
||||
module.exports = {
|
||||
Hash,
|
||||
Set,
|
||||
Map,
|
||||
BitSet,
|
||||
AltDict,
|
||||
DoubleDict,
|
||||
hashStuff,
|
||||
escapeWhitespace,
|
||||
arrayToString,
|
||||
titleCase,
|
||||
equalArrays
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue