enumset32
Version:
High-performance, typesafe, small ordered set implemented in TypeScript
192 lines • 5.29 kB
JavaScript
/*!
* Copyright (c) 2019 Justin Johansson
*/
export class _UniversalEnumset32 {
constructor(enumObject) {
let e = Object.create(null);
let m = Object.create(null);
let u = 0 | 0;
let names = Object.getOwnPropertyNames(enumObject);
for (let i = 0; i < names.length; ++i) {
let n = names[i];
let v = enumObject[n];
if (typeof v === 'number') {
e[(e[n] = v)] = n;
let mv = 1 << v;
m[n] = mv;
u |= mv;
}
}
this.Enum = Object.freeze(e);
this.Member = Object.freeze(m);
this._univ = u;
}
static create(enumObject) {
return Object.freeze(new _UniversalEnumset32(enumObject));
}
get Empty() {
return (0 | 0);
}
set() {
let res = 0;
let i;
for (i = 0; i < arguments.length; ++i) {
res |= 1 << arguments[i];
}
return res & this._univ;
}
add(set, member) {
let s = set & this._univ;
let m = +member;
return (s | (1 << m)) & this._univ;
}
addAll(set1, set2, ...sets) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
let res = s1 | s2;
for (let i = 0; i < sets.length; ++i) {
res |= sets[i];
}
return res & this._univ;
}
complement(set) {
let s = set & this._univ;
return ~s & this._univ;
}
retain(set, member) {
let s = set & this._univ;
let m = +member;
return s & (1 << m) & this._univ;
}
retainAll(set1, set2, ...sets) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
let res = s1 & s2;
for (let i = 0; i < sets.length; ++i) {
res &= sets[i];
}
return res & this._univ;
}
remove(set, member) {
let s = set & this._univ;
let m = +member;
return s & ~(1 << m) & this._univ;
}
removeAll(set1, set2, ...sets) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
let res = s1 & ~s2;
for (let i = 0; i < sets.length; ++i) {
res &= ~sets[i];
}
return res & this._univ;
}
toggle(set, member) {
let s = set & this._univ;
let m = +member;
return (s ^ (1 << m)) & this._univ;
}
toggleAll(set1, set2, ...sets) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
let res = s1 ^ s2;
for (let i = 0; i < sets.length; ++i) {
res ^= sets[i];
}
return res & this._univ;
}
empty(set) {
let s = set & this._univ;
return s === 0;
}
excludes(set, member) {
let s = set & this._univ;
let m = +member;
return this.excludesEvery(s, (1 << m));
}
excludesEvery(set1, set2) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
return (s1 & s2) === 0;
}
excludesSome(set1, set2) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
return (s1 & s2) !== s2;
}
includes(set, member) {
let s = set & this._univ;
let m = +member;
return this.includesEvery(s, (1 << m));
}
includesEvery(set1, set2) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
return (s1 & s2) === s2;
}
includesSome(set1, set2) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
return (s1 & s2) !== 0;
}
count(set) {
let s = set & this._univ;
if (s >= 0) {
let card = s - ((s >> 1) & 0o33333333333) - ((s >> 2) & 0o11111111111);
return ((card + (card >> 3)) & 0o30707070707) % 0o77;
}
return this.count((set & 0o17777777777)) + 1;
}
enumEntries(set) {
let s = set & this._univ;
let entries = [];
for (let i = 0; i < 32; ++i) {
if (s & (1 << i)) {
entries.push([this.Enum[i], i]);
}
}
return entries;
}
enumKeys(set) {
let s = set & this._univ;
let keys = [];
for (let i = 0; i < 32; ++i) {
if (s & (1 << i)) {
keys.push(this.Enum[i]);
}
}
return keys;
}
enumValues(set) {
let s = set & this._univ;
let values = [];
for (let i = 0; i < 32; ++i) {
if (s & (1 << i)) {
values.push(i);
}
}
return values;
}
equal(set1, set2) {
let s1 = set1 & this._univ;
let s2 = set2 & this._univ;
return s1 === s2;
}
isEnumKey(key) {
return typeof key === 'string' && typeof this.Enum[key] === 'number';
}
isEnumValue(value) {
return typeof value === 'number' && typeof this.Enum[value] === 'string';
}
toDigitString(set, radix) {
let s = set & this._univ;
return (s >>> 0).toString(radix);
}
valueOf() {
return (this._univ | 0);
}
}
export function UniversalEnumset32(enumObject) {
return _UniversalEnumset32.create(enumObject);
}
//# sourceMappingURL=index.js.map