71 lines
1.9 KiB
JavaScript
71 lines
1.9 KiB
JavaScript
export default function(size, hash, equal, keyType, keyEmpty, valueType) {
|
|
if (arguments.length === 3) {
|
|
keyType = valueType = Array;
|
|
keyEmpty = null;
|
|
}
|
|
|
|
var keystore = new keyType(size = 1 << Math.max(4, Math.ceil(Math.log(size) / Math.LN2))),
|
|
valstore = new valueType(size),
|
|
mask = size - 1;
|
|
|
|
for (var i = 0; i < size; ++i) {
|
|
keystore[i] = keyEmpty;
|
|
}
|
|
|
|
function set(key, value) {
|
|
var index = hash(key) & mask,
|
|
matchKey = keystore[index],
|
|
collisions = 0;
|
|
while (matchKey != keyEmpty) {
|
|
if (equal(matchKey, key)) return valstore[index] = value;
|
|
if (++collisions >= size) throw new Error("full hashmap");
|
|
matchKey = keystore[index = (index + 1) & mask];
|
|
}
|
|
keystore[index] = key;
|
|
valstore[index] = value;
|
|
return value;
|
|
}
|
|
|
|
function maybeSet(key, value) {
|
|
var index = hash(key) & mask,
|
|
matchKey = keystore[index],
|
|
collisions = 0;
|
|
while (matchKey != keyEmpty) {
|
|
if (equal(matchKey, key)) return valstore[index];
|
|
if (++collisions >= size) throw new Error("full hashmap");
|
|
matchKey = keystore[index = (index + 1) & mask];
|
|
}
|
|
keystore[index] = key;
|
|
valstore[index] = value;
|
|
return value;
|
|
}
|
|
|
|
function get(key, missingValue) {
|
|
var index = hash(key) & mask,
|
|
matchKey = keystore[index],
|
|
collisions = 0;
|
|
while (matchKey != keyEmpty) {
|
|
if (equal(matchKey, key)) return valstore[index];
|
|
if (++collisions >= size) break;
|
|
matchKey = keystore[index = (index + 1) & mask];
|
|
}
|
|
return missingValue;
|
|
}
|
|
|
|
function keys() {
|
|
var keys = [];
|
|
for (var i = 0, n = keystore.length; i < n; ++i) {
|
|
var matchKey = keystore[i];
|
|
if (matchKey != keyEmpty) keys.push(matchKey);
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
return {
|
|
set: set,
|
|
maybeSet: maybeSet, // set if unset
|
|
get: get,
|
|
keys: keys
|
|
};
|
|
}
|