1
0
mirror of https://github.com/nextapps-de/flexsearch.git synced 2025-09-30 07:18:57 +02:00
Files
flexsearch/dist/module-debug/keystore.js
2025-03-17 01:13:36 +01:00

389 lines
10 KiB
JavaScript

import { create_object } from "./common.js";
/**
* @param bitlength
* @constructor
*/
export function KeystoreObj(bitlength = 8) {
if (!this) {
return new KeystoreObj(bitlength);
}
this.index = create_object();
this.keys = [];
if (32 < bitlength) {
this.crc = lcg64;
this.bit = BigInt(bitlength);
} else {
this.crc = lcg;
this.bit = bitlength;
}
return (/*this.proxy =*/new Proxy(this, {
get(target, key) {
const address = target.crc(key),
obj = target.index[address];
return obj && obj[key];
},
set(target, key, value) {
const address = target.crc(key);
let obj = target.index[address];
if (!obj) {
target.index[address] = obj = create_object();
target.keys.push(address);
}
obj[key] = value;
return (/* tag? */ /* stringify */ /* stringify */ /* skip update: */ /* append: */ /* skip update: */ /* skip_update: */ /* skip deletion */
// splice:
!0 /*await rows.hasNext()*/
/*await rows.hasNext()*/ /*await rows.hasNext()*/
);
},
delete(target, key) {
const address = target.crc(key),
obj = target.index[address];
obj && delete obj[key];
return !0;
}
})
);
}
KeystoreObj.prototype.clear = function () {
this.index = create_object();
this.keys = [];
};
// KeystoreObj.prototype.destroy = function(){
// this.index = null;
// this.keys = null;
// this.proxy = null;
// };
function _slice(self, start, end, splice) {
let arr = [];
for (let i = 0, index; i < self.index.length; i++) {
index = self.index[i];
if (start >= index.length) {
start -= index.length;
} else {
const tmp = index[splice ? "splice" : "slice"](start, end),
length = tmp.length;
if (length) {
arr = arr.length ? arr.concat(tmp) : tmp;
end -= length;
if (splice) self.length -= length;
if (!end) break;
}
start = 0;
}
}
return arr;
}
/**
* @param arr
* @constructor
*/
export function KeystoreArray(arr) {
if (!this) {
return new KeystoreArray(arr);
}
this.index = arr ? [arr] : [];
this.length = arr ? arr.length : 0;
const self = this;
return (/*this.proxy =*/new Proxy([], {
get(target, key) {
if ("length" === key) {
return self.length;
}
if ("push" === key) {
return function (value) {
self.index[self.index.length - 1].push(value);
self.length++;
};
}
if ("pop" === key) {
return function () {
if (self.length) {
self.length--;
return self.index[self.index.length - 1].pop();
}
};
}
if ("indexOf" === key) {
return function (key) {
let index = 0;
for (let i = 0, arr, tmp; i < self.index.length; i++) {
arr = self.index[i];
//if(!arr.includes(key)) continue;
tmp = arr.indexOf(key);
if (0 <= tmp) return index + tmp;
index += arr.length;
}
return -1;
};
}
if ("includes" === key) {
return function (key) {
for (let i = 0; i < self.index.length; i++) {
if (self.index[i].includes(key)) {
return !0;
}
}
return (/* suggest */ /* append: */ /* enrich */!1
);
};
}
if ("slice" === key) {
return function (start, end) {
return _slice(self, start || 0, end || self.length, !1);
};
}
if ("splice" === key) {
return function (start, end) {
return _slice(self, start || 0, end || self.length, !0);
};
}
if ("constructor" === key) {
return Array;
}
if ("symbol" == typeof key /*|| isNaN(key)*/) {
// not supported
return;
}
const arr = self.index[0 | key / 2147483648];
return arr && arr[key];
},
set(target, key, value) {
const index = 0 | key / 2147483648,
arr = self.index[index] || (self.index[index] = []);
arr[key] = value;
self.length++;
return !0;
}
})
);
}
KeystoreArray.prototype.clear = function () {
this.index.length = 0;
};
KeystoreArray.prototype.destroy = function () {
this.index = null;
this.proxy = null;
};
KeystoreArray.prototype.push = function () {};
/**
* @param bitlength
* @constructor
*/
export function KeystoreMap(bitlength = 8) {
if (!this) {
return new KeystoreMap(bitlength);
}
this.index = create_object();
this.refs = [];
this.size = 0;
if (32 < bitlength) {
this.crc = lcg64;
this.bit = BigInt(bitlength);
} else {
this.crc = lcg;
this.bit = bitlength;
}
}
KeystoreMap.prototype.get = function (key) {
const address = this.crc(key),
map = this.index[address];
return map && map.get(key);
};
KeystoreMap.prototype.set = function (key, value) {
const address = this.crc(key);
let map = this.index[address];
if (map) {
let size = map.size;
map.set(key, value);
size -= map.size;
size && this.size++;
} else {
this.index[address] = map = new Map([[key, value]]);
this.refs.push(map);
}
};
/**
* @param bitlength
* @constructor
*/
export function KeystoreSet(bitlength = 8) {
if (!this) {
return new KeystoreSet(bitlength);
}
// using plain Object with numeric key access
// just for max performance
this.index = create_object();
this.refs = [];
if (32 < bitlength) {
this.crc = lcg64;
this.bit = BigInt(bitlength);
} else {
this.crc = lcg;
this.bit = bitlength;
}
}
KeystoreSet.prototype.add = function (key) {
const address = this.crc(key);
let set = this.index[address];
if (set) {
let size = set.size;
set.add(key);
size -= set.size;
size && this.size++;
} else {
this.index[address] = set = new Set([key]);
this.refs.push(set);
}
};
KeystoreMap.prototype.has = KeystoreSet.prototype.has = function (key) {
const address = this.crc(key),
map_or_set = this.index[address];
return map_or_set && map_or_set.has(key);
};
/*
KeystoreMap.prototype.size =
KeystoreSet.prototype.size = function(){
let size = 0;
const values = Object.values(this.index);
for(let i = 0; i < values.length; i++){
size += values[i].size;
}
return size;
};
*/
KeystoreMap.prototype.delete = KeystoreSet.prototype.delete = function (key) {
const address = this.crc(key),
map_or_set = this.index[address];
// set && (set.size === 1
// ? this.index.delete(address)
// : set.delete(key));
map_or_set && map_or_set.delete(key) && this.size--;
};
KeystoreMap.prototype.clear = KeystoreSet.prototype.clear = function () {
this.index = create_object();
this.refs = [];
this.size = 0;
};
// KeystoreMap.prototype.destroy =
// KeystoreSet.prototype.destroy = function(){
// this.index = null;
// this.refs = null;
// this.proxy = null;
// };
KeystoreMap.prototype.values = KeystoreSet.prototype.values = function* () {
// alternatively iterate through this.keys[]
//const refs = Object.values(this.index);
for (let i = 0; i < this.refs.length; i++) {
for (let value of this.refs[i].values()) {
yield value;
}
}
};
KeystoreMap.prototype.keys = KeystoreSet.prototype.keys = function* () {
//const values = Object.values(this.index);
for (let i = 0; i < this.refs.length; i++) {
for (let key of this.refs[i].keys()) {
yield key;
}
}
};
KeystoreMap.prototype.entries = KeystoreSet.prototype.entries = function* () {
//const values = Object.values(this.index);
for (let i = 0; i < this.refs.length; i++) {
for (let entry of this.refs[i].entries()) {
yield entry;
}
}
};
/**
* Linear Congruential Generator (LCG)
* @param str
* @this {KeystoreMap|KeystoreSet}
*/
function lcg(str) {
let range = 2 ** this.bit - 1;
if ("number" == typeof str) {
return str & range;
}
let crc = 0,
bit = this.bit + 1;
for (let i = 0; i < str.length; i++) {
crc = (crc * bit ^ str.charCodeAt(i)) & range;
}
// shift Int32 to UInt32 because negative numbers
// extremely slows down key lookup
return 32 === this.bit ? crc + 2147483648 : crc; // & 0xFFFF;
}
/**
* @param str
* @this {KeystoreMap|KeystoreSet}
*/
function lcg64(str) {
let range = BigInt(2) ** /** @type {!BigInt} */this.bit - BigInt(1),
type = typeof str;
if ("bigint" == type) {
return (/** @type {!BigInt} */str & range
);
}
if ("number" == type) {
return BigInt(str) & range;
}
let crc = BigInt(0),
bit = /** @type {!BigInt} */this.bit + BigInt(1);
for (let i = 0; i < str.length; i++) {
crc = (crc * bit ^ BigInt(str.charCodeAt(i))) & range;
}
return crc; // & 0xFFFFFFFFFFFFFFFF;
}