cache-mapset
Advanced tools
Comparing version 1.0.0-beta.1 to 1.0.0-beta.2
@@ -1,1 +0,2 @@ | ||
export { isNonNegativeNumber } from "@miyauci/isx/numeric/is_non_negative_number.js"; | ||
export { assertNonNegativeNumber } from "@miyauci/assertion/number/assert_non_negative_number.js"; | ||
export { EmplaceableMap } from "@miyauci/upsert"; |
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
export { isNonNegativeNumber } from "@miyauci/isx/numeric/is_non_negative_number.js"; | ||
export { assertNonNegativeNumber } from "@miyauci/assertion/number/assert_non_negative_number.js"; | ||
export { EmplaceableMap } from "@miyauci/upsert"; |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with FIFO algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class FIFOMap<K, V> implements MapLike<K, V> { | ||
export declare class FIFOMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
get(key: K): V | undefined; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with FIFO algorithm. | ||
*/ | ||
export declare class FIFOSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class FIFOSet<T> extends BaseSet<T> { | ||
protected cache: FIFOMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
108
esm/fifo.js
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -14,4 +8,4 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _FIFOMap_instances, _FIFOMap_cache, _FIFOMap_capacity, _FIFOMap_firstKey_get, _FIFOSet_instances, _FIFOSet_cache, _FIFOSet_capacity, _FIFOSet_first_get; | ||
import { assertCapacity } from "./utils.js"; | ||
var _FIFOMap_instances, _FIFOMap_firstKey_get; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with FIFO algorithm. | ||
@@ -26,42 +20,31 @@ * @example | ||
*/ | ||
export class FIFOMap { | ||
constructor(maxNumOfEntries) { | ||
export class FIFOMap extends BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_FIFOMap_instances.add(this); | ||
_FIFOMap_cache.set(this, void 0); | ||
_FIFOMap_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _FIFOMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _FIFOMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").has(key); | ||
get(key) { | ||
return this.cache.get(key); | ||
} | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _FIFOMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (this.has(key)) { | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").set(key, value); | ||
if (this.cache.has(key)) { | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
if (__classPrivateFieldGet(this, _FIFOMap_capacity, "f") <= __classPrivateFieldGet(this, _FIFOMap_cache, "f").size) | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").delete(__classPrivateFieldGet(this, _FIFOMap_instances, "a", _FIFOMap_firstKey_get)); | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").set(key, value); | ||
if (this.capacity <= this.cache.size) | ||
this.cache.delete(__classPrivateFieldGet(this, _FIFOMap_instances, "a", _FIFOMap_firstKey_get)); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
get(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").get(key); | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").size; | ||
} | ||
} | ||
_FIFOMap_cache = new WeakMap(), _FIFOMap_capacity = new WeakMap(), _FIFOMap_instances = new WeakSet(), _FIFOMap_firstKey_get = function _FIFOMap_firstKey_get() { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").keys().next().value; | ||
_FIFOMap_instances = new WeakSet(), _FIFOMap_firstKey_get = function _FIFOMap_firstKey_get() { | ||
return this.cache.keys().next().value; | ||
}; | ||
@@ -77,36 +60,19 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with FIFO algorithm. | ||
*/ | ||
export class FIFOSet { | ||
constructor(maxNumOfValues) { | ||
_FIFOSet_instances.add(this); | ||
_FIFOSet_cache.set(this, void 0); | ||
_FIFOSet_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _FIFOSet_cache, new Set(), "f"); | ||
__classPrivateFieldSet(this, _FIFOSet_capacity, capacity, "f"); | ||
export class FIFOSet extends BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new FIFOMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").has(value); | ||
} | ||
add(value) { | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").has(value)) | ||
return this; | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").size >= __classPrivateFieldGet(this, _FIFOSet_capacity, "f")) | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").delete(__classPrivateFieldGet(this, _FIFOSet_instances, "a", _FIFOSet_first_get)); | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").size < __classPrivateFieldGet(this, _FIFOSet_capacity, "f")) | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").add(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").size; | ||
} | ||
} | ||
_FIFOSet_cache = new WeakMap(), _FIFOSet_capacity = new WeakMap(), _FIFOSet_instances = new WeakSet(), _FIFOSet_first_get = function _FIFOSet_first_get() { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").values().next().value; | ||
}; |
@@ -1,2 +0,3 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseSet } from "./utils.js"; | ||
import type { MapLike } from "./types.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LFU algorithm. | ||
@@ -13,3 +14,6 @@ * @example | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
has(key: K): boolean; | ||
@@ -31,10 +35,8 @@ get(key: K): V | undefined; | ||
*/ | ||
export declare class LFUSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LFUSet<T> extends BaseSet<T> { | ||
protected cache: LFUMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
@@ -14,4 +14,6 @@ // Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
}; | ||
var _LFUMap_instances, _LFUMap_values, _LFUMap_frequency, _LFUMap_minFrequency, _LFUMap_capacity, _LFUMap_evict, _LFUMap_updateFrequency, _LFUSet_cache; | ||
import { assertCapacity, EmplaceableMap } from "./utils.js"; | ||
var _LFUMap_instances, _LFUMap_values, _LFUMap_frequency, _LFUMap_minFrequency, _LFUMap_capacity, _LFUMap_evict, _LFUMap_updateFrequency; | ||
import { assertNonNegativeNumber, EmplaceableMap } from "./deps.js"; | ||
import { Msg } from "./constants.js"; | ||
import { BaseSet } from "./utils.js"; | ||
const INIT = 1; | ||
@@ -35,3 +37,3 @@ class Container { | ||
inc() { | ||
return this.count++; | ||
return ++this.count; | ||
} | ||
@@ -49,3 +51,6 @@ } | ||
export class LFUMap { | ||
constructor(maxNumOfEntries) { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
_LFUMap_instances.add(this); | ||
@@ -56,6 +61,9 @@ _LFUMap_values.set(this, new Map()); | ||
_LFUMap_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfEntries); | ||
assertNonNegativeNumber(maxNumOfEntries, Msg.InvalidCapacity, RangeError); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LFUMap_frequency, new EmplaceableMap(), "f"); | ||
__classPrivateFieldSet(this, _LFUMap_capacity, capacity, "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
@@ -139,24 +147,19 @@ has(key) { | ||
*/ | ||
export class LFUSet { | ||
constructor(maxNumOfValues) { | ||
_LFUSet_cache.set(this, void 0); | ||
__classPrivateFieldSet(this, _LFUSet_cache, new LFUMap(maxNumOfValues), "f"); | ||
export class LFUSet extends BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LFUMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").has(value); | ||
} | ||
add(value) { | ||
__classPrivateFieldGet(this, _LFUSet_cache, "f").set(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LFUSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").size; | ||
} | ||
} | ||
_LFUSet_cache = new WeakMap(); |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LIFO algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class LIFOMap<K, V> implements MapLike<K, V> { | ||
export declare class LIFOMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LIFO algorithm. | ||
*/ | ||
export declare class LIFOSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LIFOSet<T> extends BaseSet<T> { | ||
protected cache: LIFOMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
110
esm/lifo.js
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -14,4 +8,4 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _LIFOMap_instances, _LIFOMap_cache, _LIFOMap_capacity, _LIFOMap_latestKey_get, _LIFOSet_cache, _LIFOSet_capacity; | ||
import { assertCapacity } from "./utils.js"; | ||
var _LIFOMap_instances, _LIFOMap_latestKey_get; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LIFO algorithm. | ||
@@ -26,43 +20,32 @@ * @example | ||
*/ | ||
export class LIFOMap { | ||
constructor(maxNumOfEntries) { | ||
export class LIFOMap extends BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_LIFOMap_instances.add(this); | ||
_LIFOMap_cache.set(this, void 0); | ||
_LIFOMap_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LIFOMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LIFOMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").has(key); | ||
} | ||
get(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").get(key); | ||
return this.cache.get(key); | ||
} | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _LIFOMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOMap_cache, "f").has(key)) { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").set(key, value); | ||
if (this.cache.has(key)) { | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
if (__classPrivateFieldGet(this, _LIFOMap_capacity, "f") <= __classPrivateFieldGet(this, _LIFOMap_cache, "f").size) { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").delete(__classPrivateFieldGet(this, _LIFOMap_instances, "a", _LIFOMap_latestKey_get)); | ||
if (this.capacity <= this.cache.size) { | ||
this.cache.delete(__classPrivateFieldGet(this, _LIFOMap_instances, "a", _LIFOMap_latestKey_get)); | ||
} | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").set(key, value); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").size; | ||
} | ||
} | ||
_LIFOMap_cache = new WeakMap(), _LIFOMap_capacity = new WeakMap(), _LIFOMap_instances = new WeakSet(), _LIFOMap_latestKey_get = function _LIFOMap_latestKey_get() { | ||
return [...__classPrivateFieldGet(this, _LIFOMap_cache, "f").keys()].pop(); | ||
_LIFOMap_instances = new WeakSet(), _LIFOMap_latestKey_get = function _LIFOMap_latestKey_get() { | ||
return [...this.cache.keys()].pop(); | ||
}; | ||
@@ -78,40 +61,19 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LIFO algorithm. | ||
*/ | ||
export class LIFOSet { | ||
constructor(maxNumOfValues) { | ||
_LIFOSet_cache.set(this, void 0); | ||
_LIFOSet_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _LIFOSet_cache, [], "f"); | ||
__classPrivateFieldSet(this, _LIFOSet_capacity, capacity, "f"); | ||
export class LIFOSet extends BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LIFOMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _LIFOSet_cache, "f").includes(value); | ||
} | ||
add(value) { | ||
if (!__classPrivateFieldGet(this, _LIFOSet_capacity, "f")) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOSet_cache, "f").includes(value)) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOSet_capacity, "f") <= __classPrivateFieldGet(this, _LIFOSet_cache, "f").length) { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").shift(); | ||
} | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").unshift(value); | ||
return this; | ||
} | ||
delete(value) { | ||
const index = __classPrivateFieldGet(this, _LIFOSet_cache, "f").findIndex((el) => el === value); | ||
if (index >= 0) { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").splice(index, 1); | ||
return true; | ||
} | ||
return false; | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").length = 0; | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LIFOSet_cache, "f").length; | ||
} | ||
} | ||
_LIFOSet_cache = new WeakMap(), _LIFOSet_capacity = new WeakMap(); |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LRU algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class LRUMap<K, V> implements MapLike<K, V> { | ||
export declare class LRUMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LRU algorithm. | ||
*/ | ||
export declare class LRUSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LRUSet<T> extends BaseSet<T> { | ||
protected cache: LRUMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
119
esm/lru.js
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -14,4 +8,4 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _LRUMap_instances, _LRUMap_cache, _LRUMap_capacity, _LRUMap_oldestKey_get, _LRUMap_rollup, _LRUSet_instances, _LRUSet_cache, _LRUSet_capacity, _LRUSet_rollup, _LRUSet_oldest_get; | ||
import { assertCapacity } from "./utils.js"; | ||
var _LRUMap_instances, _LRUMap_oldestKey_get, _LRUMap_rollup; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LRU algorithm. | ||
@@ -26,18 +20,16 @@ * @example | ||
*/ | ||
export class LRUMap { | ||
constructor(maxNumOfEntries) { | ||
export class LRUMap extends BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_LRUMap_instances.add(this); | ||
_LRUMap_cache.set(this, void 0); | ||
_LRUMap_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LRUMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LRUMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").has(key); | ||
} | ||
get(key) { | ||
const has = __classPrivateFieldGet(this, _LRUMap_cache, "f").has(key); | ||
const value = __classPrivateFieldGet(this, _LRUMap_cache, "f").get(key); | ||
const has = this.cache.has(key); | ||
const value = this.cache.get(key); | ||
if (has) | ||
@@ -48,27 +40,17 @@ __classPrivateFieldGet(this, _LRUMap_instances, "m", _LRUMap_rollup).call(this, key, value); | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _LRUMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LRUMap_cache, "f").has(key)) | ||
if (this.cache.has(key)) | ||
return __classPrivateFieldGet(this, _LRUMap_instances, "m", _LRUMap_rollup).call(this, key, value); | ||
if (__classPrivateFieldGet(this, _LRUMap_capacity, "f") <= __classPrivateFieldGet(this, _LRUMap_cache, "f").size) { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").delete(__classPrivateFieldGet(this, _LRUMap_instances, "a", _LRUMap_oldestKey_get)); | ||
} | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").set(key, value); | ||
if (this.capacity <= this.cache.size) | ||
this.cache.delete(__classPrivateFieldGet(this, _LRUMap_instances, "a", _LRUMap_oldestKey_get)); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").size; | ||
} | ||
} | ||
_LRUMap_cache = new WeakMap(), _LRUMap_capacity = new WeakMap(), _LRUMap_instances = new WeakSet(), _LRUMap_oldestKey_get = function _LRUMap_oldestKey_get() { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").keys().next().value; | ||
_LRUMap_instances = new WeakSet(), _LRUMap_oldestKey_get = function _LRUMap_oldestKey_get() { | ||
return this.cache.keys().next().value; | ||
}, _LRUMap_rollup = function _LRUMap_rollup(key, value) { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").delete(key); | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").set(key, value); | ||
this.cache.delete(key); | ||
this.cache.set(key, value); | ||
return this; | ||
@@ -85,44 +67,19 @@ }; | ||
*/ | ||
export class LRUSet { | ||
constructor(maxNumOfValues) { | ||
_LRUSet_instances.add(this); | ||
_LRUSet_cache.set(this, void 0); | ||
_LRUSet_capacity.set(this, void 0); | ||
assertCapacity(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _LRUSet_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LRUSet_cache, new Set(), "f"); | ||
export class LRUSet extends BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LRUMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
const has = __classPrivateFieldGet(this, _LRUSet_cache, "f").has(value); | ||
if (has) | ||
__classPrivateFieldGet(this, _LRUSet_instances, "m", _LRUSet_rollup).call(this, value); | ||
return has; | ||
} | ||
add(value) { | ||
if (!__classPrivateFieldGet(this, _LRUSet_capacity, "f")) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LRUSet_cache, "f").has(value)) | ||
return __classPrivateFieldGet(this, _LRUSet_instances, "m", _LRUSet_rollup).call(this, value); | ||
if (__classPrivateFieldGet(this, _LRUSet_capacity, "f") <= __classPrivateFieldGet(this, _LRUSet_cache, "f").size) | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").delete(__classPrivateFieldGet(this, _LRUSet_instances, "a", _LRUSet_oldest_get)); | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").add(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").size; | ||
} | ||
} | ||
_LRUSet_cache = new WeakMap(), _LRUSet_capacity = new WeakMap(), _LRUSet_instances = new WeakSet(), _LRUSet_rollup = function _LRUSet_rollup(value) { | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").delete(value); | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").add(value); | ||
return this; | ||
}, _LRUSet_oldest_get = function _LRUSet_oldest_get() { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").values().next().value; | ||
}; |
@@ -1,12 +0,23 @@ | ||
export interface EmplaceCallbacks<K, V> { | ||
/** Add entry. */ | ||
insert: (key: K) => V; | ||
/** Update the value. */ | ||
update: (existing: V, key: K) => V; | ||
import { MapLike, SetLike } from "./types.js"; | ||
export declare abstract class BaseMap<K, V> implements MapLike<K, V> { | ||
protected readonly cache: Readonly<Map<K, V>>; | ||
protected readonly capacity: number; | ||
/** | ||
* @throws {RangeError} If {@link capacity} is invalid range. | ||
*/ | ||
constructor(capacity: number); | ||
abstract get(key: K): V | undefined; | ||
abstract set(key: K, value: V): this; | ||
has(key: K): boolean; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
export declare class EmplaceableMap<K, V> extends Map<K, V> { | ||
/** Add a value to a map if the map does not already have something at {@link key}, and will also update an existing value at {@link key}. */ | ||
emplace(key: K, callbacks: EmplaceCallbacks<K, V>): V; | ||
export declare abstract class BaseSet<T> implements SetLike<T> { | ||
protected abstract cache: MapLike<T, void>; | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
/** Assert capacity is valid. */ | ||
export declare function assertCapacity(capacity: number): asserts capacity; |
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
import { isNonNegativeNumber } from "./deps.js"; | ||
export class EmplaceableMap extends Map { | ||
/** Add a value to a map if the map does not already have something at {@link key}, and will also update an existing value at {@link key}. */ | ||
emplace(key, callbacks) { | ||
const value = this.has(key) | ||
? callbacks.update(this.get(key), key) | ||
: callbacks.insert(key); | ||
this.set(key, value); | ||
return value; | ||
import { assertNonNegativeNumber } from "./deps.js"; | ||
import { Msg } from "./constants.js"; | ||
export class BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link capacity} is invalid range. | ||
*/ | ||
constructor(capacity) { | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "capacity", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
assertNonNegativeNumber(capacity, Msg.InvalidCapacity, RangeError); | ||
capacity = Math.floor(capacity); | ||
this.cache = new Map(); | ||
this.capacity = capacity; | ||
} | ||
has(key) { | ||
return this.cache.has(key); | ||
} | ||
delete(key) { | ||
return this.cache.delete(key); | ||
} | ||
clear() { | ||
return this.cache.clear(); | ||
} | ||
get size() { | ||
return this.cache.size; | ||
} | ||
} | ||
/** Assert capacity is valid. */ | ||
export function assertCapacity(capacity) { | ||
if (!isNonNegativeNumber(capacity)) { | ||
throw RangeError("capacity must be non-negative"); | ||
export class BaseSet { | ||
has(value) { | ||
return this.cache.has(value); | ||
} | ||
add(value) { | ||
this.cache.set(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return this.cache.delete(value); | ||
} | ||
clear() { | ||
this.cache.clear(); | ||
} | ||
get size() { | ||
return this.cache.size; | ||
} | ||
} |
{ | ||
"module": "./esm/lru.js", | ||
"main": "./script/lru.js", | ||
"module": "./esm/mod.js", | ||
"main": "./script/mod.js", | ||
"name": "cache-mapset", | ||
"version": "1.0.0-beta.1", | ||
"version": "1.0.0-beta.2", | ||
"description": "Maps and Sets with cache replacement policies, TC39 proposal-policy-map-set implementation", | ||
@@ -32,21 +32,10 @@ "keywords": [ | ||
".": { | ||
"import": "./esm/lru.js", | ||
"require": "./script/lru.js" | ||
}, | ||
"./lfu.js": { | ||
"import": "./esm/lfu.js", | ||
"require": "./script/lfu.js" | ||
}, | ||
"./fifo.js": { | ||
"import": "./esm/fifo.js", | ||
"require": "./script/fifo.js" | ||
}, | ||
"./lifo.js": { | ||
"import": "./esm/lifo.js", | ||
"require": "./script/lifo.js" | ||
"import": "./esm/mod.js", | ||
"require": "./script/mod.js" | ||
} | ||
}, | ||
"dependencies": { | ||
"@miyauci/isx": "1.4.0" | ||
"@miyauci/assertion": "1.0.0", | ||
"@miyauci/upsert": "1.1.0" | ||
} | ||
} |
196
README.md
# cache-mapset | ||
[![deno land](http://img.shields.io/badge/available%20on-deno.land/x-lightgrey.svg?logo=deno)](https://deno.land/x/cache-mapset) | ||
[![deno doc](https://doc.deno.land/badge.svg)](https://deno.land/x/cache-mapset/mod.ts) | ||
[![deno land](http://img.shields.io/badge/available%20on-deno.land/x-lightgrey.svg?logo=deno)](https://deno.land/x/cache_mapset) | ||
[![deno doc](https://doc.deno.land/badge.svg)](https://deno.land/x/cache_mapset?doc) | ||
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/TomokiMiyauci/cache-mapset)](https://github.com/TomokiMiyauci/cache-mapset/releases) | ||
[![codecov](https://codecov.io/github/TomokiMiyauci/cache-mapset/branch/main/graph/badge.svg)](https://codecov.io/gh/TomokiMiyauci/cache-mapset) | ||
[![GitHub](https://img.shields.io/github/license/TomokiMiyauci/cache-mapset)](https://github.com/TomokiMiyauci/cache-mapset/blob/main/LICENSE) | ||
[![License](https://img.shields.io/github/license/TomokiMiyauci/cache-mapset)](LICENSE) | ||
[![test](https://github.com/TomokiMiyauci/cache-mapset/actions/workflows/test.yaml/badge.svg)](https://github.com/TomokiMiyauci/cache-mapset/actions/workflows/test.yaml) | ||
[![NPM](https://nodei.co/npm/cache-mapset.png?mini=true)](https://nodei.co/npm/cache-mapset/) | ||
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg)](https://github.com/RichardLitt/standard-readme) | ||
[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) | ||
Maps and Sets with cache replacement policies, TC39 | ||
[proposal-policy-map-set](https://github.com/tc39/proposal-policy-map-set) | ||
implementation. | ||
implementation. This can be used as a cache for TC39 | ||
[proposal-function-memo](https://github.com/tc39/proposal-function-memo) and its | ||
[implementation](https://github.com/TomokiMiyauci/memo). | ||
This can be used as a cache for TC39 | ||
[proposal-function-memo](https://github.com/tc39/proposal-function-memo). See | ||
[memo](https://github.com/TomokiMiyauci/memo) for its implementation. | ||
## Usage | ||
## Common | ||
### FIFO | ||
List items common to all implementations. | ||
### Interface | ||
MapLike: | ||
```ts | ||
interface MapLike<K, V> { | ||
/** The number of entries. */ | ||
size: number; | ||
/** Whether has an entry with the given {@link key}. */ | ||
has: (key: K) => boolean; | ||
/** Returns the value of the entry with the given {@link key}, if any such entry exists; otherwise returns `undefined`. */ | ||
get: (key: K) => V | undefined; | ||
/** Adds an entry with the given {@link key} mapped to the given {@link value}. */ | ||
set: (key: K, value: V) => this; | ||
/** Deletes the entry with the given {@link key}. */ | ||
delete: (key: K) => boolean; | ||
/** Removes all entries. */ | ||
clear: () => void; | ||
} | ||
``` | ||
SetLike: | ||
```ts | ||
interface SetLike<T> { | ||
/** The number of values. */ | ||
size: number; | ||
/** Whether has the given {@link value}. */ | ||
has: (value: T) => boolean; | ||
/** Adds the given {@link value}. */ | ||
add: (value: T) => this; | ||
/** Deletes the given {@link value}. */ | ||
delete: (value: T) => boolean; | ||
/** Removes all values. */ | ||
clear: () => void; | ||
} | ||
``` | ||
### Throwing error | ||
All constructors specify a capacity as their first argument. | ||
If it is a negative number, an error is thrown. | ||
```ts | ||
import { FIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/fifo.ts"; | ||
import { assertThrows } from "https://deno.land/std/testing/asserts.ts"; | ||
assertThrows(() => new FIFOMap(-1)); | ||
``` | ||
## FIFO | ||
FIFO(First In, First Out) implementations. | ||
### FIFOMap | ||
#### FIFOMap | ||
@@ -93,3 +31,3 @@ When the upper limit is reached, replaces the entry with FIFO algorithm. | ||
```ts | ||
import { FIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/fifo.ts"; | ||
import { FIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -100,3 +38,3 @@ declare const maxNumOfEntries: number; | ||
### FIFOSet | ||
#### FIFOSet | ||
@@ -106,3 +44,3 @@ When the upper limit is reached, replaces the value with FIFO algorithm. | ||
```ts | ||
import { FIFOSet } from "https://deno.land/x/cache_mapset@$VERSION/fifo.ts"; | ||
import { FIFOSet } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -113,7 +51,7 @@ declare const maxNumOfValues: number; | ||
## LIFO | ||
### LIFO | ||
LIFO(Last In, First Out) implementations. | ||
### LIFOMap | ||
#### LIFOMap | ||
@@ -123,3 +61,3 @@ When the upper limit is reached, replaces the entry with LIFO algorithm. | ||
```ts | ||
import { LIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/lifo.ts"; | ||
import { LIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -130,3 +68,3 @@ declare const maxNumOfEntries: number; | ||
### LIFOSet | ||
#### LIFOSet | ||
@@ -136,3 +74,3 @@ When the upper limit is reached, replaces the value with LIFO algorithm. | ||
```ts | ||
import { LIFOSet } from "https://deno.land/x/cache_mapset@$VERSION/lifo.ts"; | ||
import { LIFOSet } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -143,7 +81,7 @@ declare const maxNumOfValues: number; | ||
## LRU | ||
### LRU | ||
LRU(Least Recently Used) implementations. | ||
### LRUMap | ||
#### LRUMap | ||
@@ -153,3 +91,3 @@ When the upper limit is reached, replaces the entry with LRU algorithm. | ||
```ts | ||
import { LRUMap } from "https://deno.land/x/cache_mapset@$VERSION/lru.ts"; | ||
import { LRUMap } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -160,3 +98,3 @@ declare const maxNumOfEntries: number; | ||
### LRUSet | ||
#### LRUSet | ||
@@ -166,3 +104,3 @@ When the upper limit is reached, replaces the value with LRU algorithm. | ||
```ts | ||
import { LRUSet } from "https://deno.land/x/cache_mapset@$VERSION/lru.ts"; | ||
import { LRUSet } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -173,7 +111,7 @@ declare const maxNumOfValues: number; | ||
## LFU | ||
### LFU | ||
LFU(Least Frequently Used) implementations. | ||
### LFUMap | ||
#### LFUMap | ||
@@ -183,3 +121,3 @@ When the upper limit is reached, replaces the entry with LFU algorithm. | ||
```ts | ||
import { LFUMap } from "https://deno.land/x/cache_mapset@$VERSION/lfu.ts"; | ||
import { LFUMap } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -190,3 +128,3 @@ declare const maxNumOfEntries: number; | ||
### LFUSet | ||
#### LFUSet | ||
@@ -196,3 +134,3 @@ When the upper limit is reached, replaces the value with LFU algorithm. | ||
```ts | ||
import { LFUSet } from "https://deno.land/x/cache_mapset@$VERSION/lfu.ts"; | ||
import { LFUSet } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
@@ -203,10 +141,78 @@ declare const maxNumOfValues: number; | ||
## Common | ||
List items common to all implementations. | ||
### Interface | ||
All instance have following members. | ||
MapLike: | ||
```ts | ||
interface MapLike<K, V> { | ||
/** The number of entries. */ | ||
size: number; | ||
/** Whether has an entry with the given {@link key}. */ | ||
has: (key: K) => boolean; | ||
/** Returns the value of the entry with the given {@link key}, if any such entry exists; otherwise returns `undefined`. */ | ||
get: (key: K) => V | undefined; | ||
/** Adds an entry with the given {@link key} mapped to the given {@link value}. */ | ||
set: (key: K, value: V) => this; | ||
/** Deletes the entry with the given {@link key}. */ | ||
delete: (key: K) => boolean; | ||
/** Removes all entries. */ | ||
clear: () => void; | ||
} | ||
``` | ||
SetLike: | ||
```ts | ||
interface SetLike<T> { | ||
/** The number of values. */ | ||
size: number; | ||
/** Whether has the given {@link value}. */ | ||
has: (value: T) => boolean; | ||
/** Adds the given {@link value}. */ | ||
add: (value: T) => this; | ||
/** Deletes the given {@link value}. */ | ||
delete: (value: T) => boolean; | ||
/** Removes all values. */ | ||
clear: () => void; | ||
} | ||
``` | ||
### Throwing error | ||
All constructors specify a capacity as their first argument. | ||
If it is a negative number, an error is thrown. | ||
```ts | ||
import { FIFOMap } from "https://deno.land/x/cache_mapset@$VERSION/mod.ts"; | ||
import { assertThrows } from "https://deno.land/std/testing/asserts.ts"; | ||
assertThrows(() => new FIFOMap(-1)); | ||
``` | ||
## API | ||
See [deno doc](https://deno.land/x/cache_mapset) for all APIs. | ||
See [deno doc](https://deno.land/x/cache_mapset?doc) for all APIs. | ||
## Contributing | ||
See [CONTRIBUTING.md](CONTRIBUTING.md) | ||
## License | ||
Copyright © 2023-present [Tomoki Miyauchi](https://github.com/TomokiMiyauci). | ||
Released under the [MIT](./LICENSE) license | ||
[MIT](LICENSE) © 2023 Tomoki Miyauchi |
@@ -1,1 +0,2 @@ | ||
export { isNonNegativeNumber } from "@miyauci/isx/numeric/is_non_negative_number.js"; | ||
export { assertNonNegativeNumber } from "@miyauci/assertion/number/assert_non_negative_number.js"; | ||
export { EmplaceableMap } from "@miyauci/upsert"; |
@@ -5,4 +5,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isNonNegativeNumber = void 0; | ||
var is_non_negative_number_js_1 = require("@miyauci/isx/numeric/is_non_negative_number.js"); | ||
Object.defineProperty(exports, "isNonNegativeNumber", { enumerable: true, get: function () { return is_non_negative_number_js_1.isNonNegativeNumber; } }); | ||
exports.EmplaceableMap = exports.assertNonNegativeNumber = void 0; | ||
var assert_non_negative_number_js_1 = require("@miyauci/assertion/number/assert_non_negative_number.js"); | ||
Object.defineProperty(exports, "assertNonNegativeNumber", { enumerable: true, get: function () { return assert_non_negative_number_js_1.assertNonNegativeNumber; } }); | ||
var upsert_1 = require("@miyauci/upsert"); | ||
Object.defineProperty(exports, "EmplaceableMap", { enumerable: true, get: function () { return upsert_1.EmplaceableMap; } }); |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with FIFO algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class FIFOMap<K, V> implements MapLike<K, V> { | ||
export declare class FIFOMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
get(key: K): V | undefined; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with FIFO algorithm. | ||
*/ | ||
export declare class FIFOSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class FIFOSet<T> extends BaseSet<T> { | ||
protected cache: FIFOMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
"use strict"; | ||
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -15,3 +9,3 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _FIFOMap_instances, _FIFOMap_cache, _FIFOMap_capacity, _FIFOMap_firstKey_get, _FIFOSet_instances, _FIFOSet_cache, _FIFOSet_capacity, _FIFOSet_first_get; | ||
var _FIFOMap_instances, _FIFOMap_firstKey_get; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -29,43 +23,32 @@ exports.FIFOSet = exports.FIFOMap = void 0; | ||
*/ | ||
class FIFOMap { | ||
constructor(maxNumOfEntries) { | ||
class FIFOMap extends utils_js_1.BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_FIFOMap_instances.add(this); | ||
_FIFOMap_cache.set(this, void 0); | ||
_FIFOMap_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _FIFOMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _FIFOMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").has(key); | ||
get(key) { | ||
return this.cache.get(key); | ||
} | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _FIFOMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (this.has(key)) { | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").set(key, value); | ||
if (this.cache.has(key)) { | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
if (__classPrivateFieldGet(this, _FIFOMap_capacity, "f") <= __classPrivateFieldGet(this, _FIFOMap_cache, "f").size) | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").delete(__classPrivateFieldGet(this, _FIFOMap_instances, "a", _FIFOMap_firstKey_get)); | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").set(key, value); | ||
if (this.capacity <= this.cache.size) | ||
this.cache.delete(__classPrivateFieldGet(this, _FIFOMap_instances, "a", _FIFOMap_firstKey_get)); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
get(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").get(key); | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _FIFOMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").size; | ||
} | ||
} | ||
exports.FIFOMap = FIFOMap; | ||
_FIFOMap_cache = new WeakMap(), _FIFOMap_capacity = new WeakMap(), _FIFOMap_instances = new WeakSet(), _FIFOMap_firstKey_get = function _FIFOMap_firstKey_get() { | ||
return __classPrivateFieldGet(this, _FIFOMap_cache, "f").keys().next().value; | ||
_FIFOMap_instances = new WeakSet(), _FIFOMap_firstKey_get = function _FIFOMap_firstKey_get() { | ||
return this.cache.keys().next().value; | ||
}; | ||
@@ -81,37 +64,20 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with FIFO algorithm. | ||
*/ | ||
class FIFOSet { | ||
constructor(maxNumOfValues) { | ||
_FIFOSet_instances.add(this); | ||
_FIFOSet_cache.set(this, void 0); | ||
_FIFOSet_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _FIFOSet_cache, new Set(), "f"); | ||
__classPrivateFieldSet(this, _FIFOSet_capacity, capacity, "f"); | ||
class FIFOSet extends utils_js_1.BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new FIFOMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").has(value); | ||
} | ||
add(value) { | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").has(value)) | ||
return this; | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").size >= __classPrivateFieldGet(this, _FIFOSet_capacity, "f")) | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").delete(__classPrivateFieldGet(this, _FIFOSet_instances, "a", _FIFOSet_first_get)); | ||
if (__classPrivateFieldGet(this, _FIFOSet_cache, "f").size < __classPrivateFieldGet(this, _FIFOSet_capacity, "f")) | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").add(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _FIFOSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").size; | ||
} | ||
} | ||
exports.FIFOSet = FIFOSet; | ||
_FIFOSet_cache = new WeakMap(), _FIFOSet_capacity = new WeakMap(), _FIFOSet_instances = new WeakSet(), _FIFOSet_first_get = function _FIFOSet_first_get() { | ||
return __classPrivateFieldGet(this, _FIFOSet_cache, "f").values().next().value; | ||
}; |
@@ -1,2 +0,3 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseSet } from "./utils.js"; | ||
import type { MapLike } from "./types.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LFU algorithm. | ||
@@ -13,3 +14,6 @@ * @example | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
has(key: K): boolean; | ||
@@ -31,10 +35,8 @@ get(key: K): V | undefined; | ||
*/ | ||
export declare class LFUSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LFUSet<T> extends BaseSet<T> { | ||
protected cache: LFUMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
@@ -15,5 +15,7 @@ "use strict"; | ||
}; | ||
var _LFUMap_instances, _LFUMap_values, _LFUMap_frequency, _LFUMap_minFrequency, _LFUMap_capacity, _LFUMap_evict, _LFUMap_updateFrequency, _LFUSet_cache; | ||
var _LFUMap_instances, _LFUMap_values, _LFUMap_frequency, _LFUMap_minFrequency, _LFUMap_capacity, _LFUMap_evict, _LFUMap_updateFrequency; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.LFUSet = exports.LFUMap = void 0; | ||
const deps_js_1 = require("./deps.js"); | ||
const constants_js_1 = require("./constants.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -38,3 +40,3 @@ const INIT = 1; | ||
inc() { | ||
return this.count++; | ||
return ++this.count; | ||
} | ||
@@ -52,3 +54,6 @@ } | ||
class LFUMap { | ||
constructor(maxNumOfEntries) { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
_LFUMap_instances.add(this); | ||
@@ -59,6 +64,9 @@ _LFUMap_values.set(this, new Map()); | ||
_LFUMap_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfEntries); | ||
(0, deps_js_1.assertNonNegativeNumber)(maxNumOfEntries, constants_js_1.Msg.InvalidCapacity, RangeError); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LFUMap_frequency, new utils_js_1.EmplaceableMap(), "f"); | ||
__classPrivateFieldSet(this, _LFUMap_frequency, new deps_js_1.EmplaceableMap(), "f"); | ||
__classPrivateFieldSet(this, _LFUMap_capacity, capacity, "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
@@ -143,25 +151,20 @@ has(key) { | ||
*/ | ||
class LFUSet { | ||
constructor(maxNumOfValues) { | ||
_LFUSet_cache.set(this, void 0); | ||
__classPrivateFieldSet(this, _LFUSet_cache, new LFUMap(maxNumOfValues), "f"); | ||
class LFUSet extends utils_js_1.BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LFUMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").has(value); | ||
} | ||
add(value) { | ||
__classPrivateFieldGet(this, _LFUSet_cache, "f").set(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LFUSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LFUSet_cache, "f").size; | ||
} | ||
} | ||
exports.LFUSet = LFUSet; | ||
_LFUSet_cache = new WeakMap(); |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LIFO algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class LIFOMap<K, V> implements MapLike<K, V> { | ||
export declare class LIFOMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LIFO algorithm. | ||
*/ | ||
export declare class LIFOSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LIFOSet<T> extends BaseSet<T> { | ||
protected cache: LIFOMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
"use strict"; | ||
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -15,3 +9,3 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _LIFOMap_instances, _LIFOMap_cache, _LIFOMap_capacity, _LIFOMap_latestKey_get, _LIFOSet_cache, _LIFOSet_capacity; | ||
var _LIFOMap_instances, _LIFOMap_latestKey_get; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -29,44 +23,33 @@ exports.LIFOSet = exports.LIFOMap = void 0; | ||
*/ | ||
class LIFOMap { | ||
constructor(maxNumOfEntries) { | ||
class LIFOMap extends utils_js_1.BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_LIFOMap_instances.add(this); | ||
_LIFOMap_cache.set(this, void 0); | ||
_LIFOMap_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LIFOMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LIFOMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").has(key); | ||
} | ||
get(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").get(key); | ||
return this.cache.get(key); | ||
} | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _LIFOMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOMap_cache, "f").has(key)) { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").set(key, value); | ||
if (this.cache.has(key)) { | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
if (__classPrivateFieldGet(this, _LIFOMap_capacity, "f") <= __classPrivateFieldGet(this, _LIFOMap_cache, "f").size) { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").delete(__classPrivateFieldGet(this, _LIFOMap_instances, "a", _LIFOMap_latestKey_get)); | ||
if (this.capacity <= this.cache.size) { | ||
this.cache.delete(__classPrivateFieldGet(this, _LIFOMap_instances, "a", _LIFOMap_latestKey_get)); | ||
} | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").set(key, value); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LIFOMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LIFOMap_cache, "f").size; | ||
} | ||
} | ||
exports.LIFOMap = LIFOMap; | ||
_LIFOMap_cache = new WeakMap(), _LIFOMap_capacity = new WeakMap(), _LIFOMap_instances = new WeakSet(), _LIFOMap_latestKey_get = function _LIFOMap_latestKey_get() { | ||
return [...__classPrivateFieldGet(this, _LIFOMap_cache, "f").keys()].pop(); | ||
_LIFOMap_instances = new WeakSet(), _LIFOMap_latestKey_get = function _LIFOMap_latestKey_get() { | ||
return [...this.cache.keys()].pop(); | ||
}; | ||
@@ -82,41 +65,20 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LIFO algorithm. | ||
*/ | ||
class LIFOSet { | ||
constructor(maxNumOfValues) { | ||
_LIFOSet_cache.set(this, void 0); | ||
_LIFOSet_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _LIFOSet_cache, [], "f"); | ||
__classPrivateFieldSet(this, _LIFOSet_capacity, capacity, "f"); | ||
class LIFOSet extends utils_js_1.BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LIFOMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
return __classPrivateFieldGet(this, _LIFOSet_cache, "f").includes(value); | ||
} | ||
add(value) { | ||
if (!__classPrivateFieldGet(this, _LIFOSet_capacity, "f")) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOSet_cache, "f").includes(value)) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LIFOSet_capacity, "f") <= __classPrivateFieldGet(this, _LIFOSet_cache, "f").length) { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").shift(); | ||
} | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").unshift(value); | ||
return this; | ||
} | ||
delete(value) { | ||
const index = __classPrivateFieldGet(this, _LIFOSet_cache, "f").findIndex((el) => el === value); | ||
if (index >= 0) { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").splice(index, 1); | ||
return true; | ||
} | ||
return false; | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LIFOSet_cache, "f").length = 0; | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LIFOSet_cache, "f").length; | ||
} | ||
} | ||
exports.LIFOSet = LIFOSet; | ||
_LIFOSet_cache = new WeakMap(), _LIFOSet_capacity = new WeakMap(); |
@@ -1,2 +0,2 @@ | ||
import type { MapLike, SetLike } from "./types.js"; | ||
import { BaseMap, BaseSet } from "./utils.js"; | ||
/** `Map` with an upper limit, objects like. When the upper limit is reached, replaces the entry with LRU algorithm. | ||
@@ -11,11 +11,10 @@ * @example | ||
*/ | ||
export declare class LRUMap<K, V> implements MapLike<K, V> { | ||
export declare class LRUMap<K, V> extends BaseMap<K, V> { | ||
#private; | ||
constructor(maxNumOfEntries: number); | ||
has(key: K): boolean; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries: number, entries?: Readonly<Iterable<readonly [K, V]>>); | ||
get(key: K): V | undefined; | ||
set(key: K, value: V): this; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
@@ -31,10 +30,8 @@ /** `Set` with an upper limit, objects like. When the upper limit is reached, replaces the value with LRU algorithm. | ||
*/ | ||
export declare class LRUSet<T> implements SetLike<T> { | ||
#private; | ||
constructor(maxNumOfValues: number); | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
export declare class LRUSet<T> extends BaseSet<T> { | ||
protected cache: LRUMap<T, void>; | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues: number, values?: Readonly<Iterable<T>>); | ||
} |
"use strict"; | ||
// Copyright 2023-latest Tomoki Miyauchi. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
@@ -15,3 +9,3 @@ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
}; | ||
var _LRUMap_instances, _LRUMap_cache, _LRUMap_capacity, _LRUMap_oldestKey_get, _LRUMap_rollup, _LRUSet_instances, _LRUSet_cache, _LRUSet_capacity, _LRUSet_rollup, _LRUSet_oldest_get; | ||
var _LRUMap_instances, _LRUMap_oldestKey_get, _LRUMap_rollup; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -29,18 +23,16 @@ exports.LRUSet = exports.LRUMap = void 0; | ||
*/ | ||
class LRUMap { | ||
constructor(maxNumOfEntries) { | ||
class LRUMap extends utils_js_1.BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfEntries} is invalid range. | ||
*/ | ||
constructor(maxNumOfEntries, entries) { | ||
super(maxNumOfEntries); | ||
_LRUMap_instances.add(this); | ||
_LRUMap_cache.set(this, void 0); | ||
_LRUMap_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfEntries); | ||
const capacity = Math.floor(maxNumOfEntries); | ||
__classPrivateFieldSet(this, _LRUMap_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LRUMap_cache, new Map(), "f"); | ||
if (entries) | ||
for (const [key, value] of entries) | ||
this.set(key, value); | ||
} | ||
has(key) { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").has(key); | ||
} | ||
get(key) { | ||
const has = __classPrivateFieldGet(this, _LRUMap_cache, "f").has(key); | ||
const value = __classPrivateFieldGet(this, _LRUMap_cache, "f").get(key); | ||
const has = this.cache.has(key); | ||
const value = this.cache.get(key); | ||
if (has) | ||
@@ -51,28 +43,18 @@ __classPrivateFieldGet(this, _LRUMap_instances, "m", _LRUMap_rollup).call(this, key, value); | ||
set(key, value) { | ||
if (!__classPrivateFieldGet(this, _LRUMap_capacity, "f")) | ||
if (!this.capacity) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LRUMap_cache, "f").has(key)) | ||
if (this.cache.has(key)) | ||
return __classPrivateFieldGet(this, _LRUMap_instances, "m", _LRUMap_rollup).call(this, key, value); | ||
if (__classPrivateFieldGet(this, _LRUMap_capacity, "f") <= __classPrivateFieldGet(this, _LRUMap_cache, "f").size) { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").delete(__classPrivateFieldGet(this, _LRUMap_instances, "a", _LRUMap_oldestKey_get)); | ||
} | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").set(key, value); | ||
if (this.capacity <= this.cache.size) | ||
this.cache.delete(__classPrivateFieldGet(this, _LRUMap_instances, "a", _LRUMap_oldestKey_get)); | ||
this.cache.set(key, value); | ||
return this; | ||
} | ||
delete(key) { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").delete(key); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").size; | ||
} | ||
} | ||
exports.LRUMap = LRUMap; | ||
_LRUMap_cache = new WeakMap(), _LRUMap_capacity = new WeakMap(), _LRUMap_instances = new WeakSet(), _LRUMap_oldestKey_get = function _LRUMap_oldestKey_get() { | ||
return __classPrivateFieldGet(this, _LRUMap_cache, "f").keys().next().value; | ||
_LRUMap_instances = new WeakSet(), _LRUMap_oldestKey_get = function _LRUMap_oldestKey_get() { | ||
return this.cache.keys().next().value; | ||
}, _LRUMap_rollup = function _LRUMap_rollup(key, value) { | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").delete(key); | ||
__classPrivateFieldGet(this, _LRUMap_cache, "f").set(key, value); | ||
this.cache.delete(key); | ||
this.cache.set(key, value); | ||
return this; | ||
@@ -89,45 +71,20 @@ }; | ||
*/ | ||
class LRUSet { | ||
constructor(maxNumOfValues) { | ||
_LRUSet_instances.add(this); | ||
_LRUSet_cache.set(this, void 0); | ||
_LRUSet_capacity.set(this, void 0); | ||
(0, utils_js_1.assertCapacity)(maxNumOfValues); | ||
const capacity = Math.floor(maxNumOfValues); | ||
__classPrivateFieldSet(this, _LRUSet_capacity, capacity, "f"); | ||
__classPrivateFieldSet(this, _LRUSet_cache, new Set(), "f"); | ||
class LRUSet extends utils_js_1.BaseSet { | ||
/** | ||
* @throws {RangeError} If {@link maxNumOfValues} is invalid range. | ||
*/ | ||
constructor(maxNumOfValues, values) { | ||
super(); | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.cache = new LRUMap(maxNumOfValues); | ||
if (values) | ||
for (const el of values) | ||
this.add(el); | ||
} | ||
has(value) { | ||
const has = __classPrivateFieldGet(this, _LRUSet_cache, "f").has(value); | ||
if (has) | ||
__classPrivateFieldGet(this, _LRUSet_instances, "m", _LRUSet_rollup).call(this, value); | ||
return has; | ||
} | ||
add(value) { | ||
if (!__classPrivateFieldGet(this, _LRUSet_capacity, "f")) | ||
return this; | ||
if (__classPrivateFieldGet(this, _LRUSet_cache, "f").has(value)) | ||
return __classPrivateFieldGet(this, _LRUSet_instances, "m", _LRUSet_rollup).call(this, value); | ||
if (__classPrivateFieldGet(this, _LRUSet_capacity, "f") <= __classPrivateFieldGet(this, _LRUSet_cache, "f").size) | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").delete(__classPrivateFieldGet(this, _LRUSet_instances, "a", _LRUSet_oldest_get)); | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").add(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").delete(value); | ||
} | ||
clear() { | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").clear(); | ||
} | ||
get size() { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").size; | ||
} | ||
} | ||
exports.LRUSet = LRUSet; | ||
_LRUSet_cache = new WeakMap(), _LRUSet_capacity = new WeakMap(), _LRUSet_instances = new WeakSet(), _LRUSet_rollup = function _LRUSet_rollup(value) { | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").delete(value); | ||
__classPrivateFieldGet(this, _LRUSet_cache, "f").add(value); | ||
return this; | ||
}, _LRUSet_oldest_get = function _LRUSet_oldest_get() { | ||
return __classPrivateFieldGet(this, _LRUSet_cache, "f").values().next().value; | ||
}; |
@@ -1,12 +0,23 @@ | ||
export interface EmplaceCallbacks<K, V> { | ||
/** Add entry. */ | ||
insert: (key: K) => V; | ||
/** Update the value. */ | ||
update: (existing: V, key: K) => V; | ||
import { MapLike, SetLike } from "./types.js"; | ||
export declare abstract class BaseMap<K, V> implements MapLike<K, V> { | ||
protected readonly cache: Readonly<Map<K, V>>; | ||
protected readonly capacity: number; | ||
/** | ||
* @throws {RangeError} If {@link capacity} is invalid range. | ||
*/ | ||
constructor(capacity: number); | ||
abstract get(key: K): V | undefined; | ||
abstract set(key: K, value: V): this; | ||
has(key: K): boolean; | ||
delete(key: K): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
export declare class EmplaceableMap<K, V> extends Map<K, V> { | ||
/** Add a value to a map if the map does not already have something at {@link key}, and will also update an existing value at {@link key}. */ | ||
emplace(key: K, callbacks: EmplaceCallbacks<K, V>): V; | ||
export declare abstract class BaseSet<T> implements SetLike<T> { | ||
protected abstract cache: MapLike<T, void>; | ||
has(value: T): boolean; | ||
add(value: T): this; | ||
delete(value: T): boolean; | ||
clear(): void; | ||
get size(): number; | ||
} | ||
/** Assert capacity is valid. */ | ||
export declare function assertCapacity(capacity: number): asserts capacity; |
@@ -5,21 +5,59 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.assertCapacity = exports.EmplaceableMap = void 0; | ||
exports.BaseSet = exports.BaseMap = void 0; | ||
const deps_js_1 = require("./deps.js"); | ||
class EmplaceableMap extends Map { | ||
/** Add a value to a map if the map does not already have something at {@link key}, and will also update an existing value at {@link key}. */ | ||
emplace(key, callbacks) { | ||
const value = this.has(key) | ||
? callbacks.update(this.get(key), key) | ||
: callbacks.insert(key); | ||
this.set(key, value); | ||
return value; | ||
const constants_js_1 = require("./constants.js"); | ||
class BaseMap { | ||
/** | ||
* @throws {RangeError} If {@link capacity} is invalid range. | ||
*/ | ||
constructor(capacity) { | ||
Object.defineProperty(this, "cache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "capacity", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
(0, deps_js_1.assertNonNegativeNumber)(capacity, constants_js_1.Msg.InvalidCapacity, RangeError); | ||
capacity = Math.floor(capacity); | ||
this.cache = new Map(); | ||
this.capacity = capacity; | ||
} | ||
has(key) { | ||
return this.cache.has(key); | ||
} | ||
delete(key) { | ||
return this.cache.delete(key); | ||
} | ||
clear() { | ||
return this.cache.clear(); | ||
} | ||
get size() { | ||
return this.cache.size; | ||
} | ||
} | ||
exports.EmplaceableMap = EmplaceableMap; | ||
/** Assert capacity is valid. */ | ||
function assertCapacity(capacity) { | ||
if (!(0, deps_js_1.isNonNegativeNumber)(capacity)) { | ||
throw RangeError("capacity must be non-negative"); | ||
exports.BaseMap = BaseMap; | ||
class BaseSet { | ||
has(value) { | ||
return this.cache.has(value); | ||
} | ||
add(value) { | ||
this.cache.set(value); | ||
return this; | ||
} | ||
delete(value) { | ||
return this.cache.delete(value); | ||
} | ||
clear() { | ||
this.cache.clear(); | ||
} | ||
get size() { | ||
return this.cache.size; | ||
} | ||
} | ||
exports.assertCapacity = assertCapacity; | ||
exports.BaseSet = BaseSet; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41
203
62564
2
1409
+ Added@miyauci/assertion@1.0.0
+ Added@miyauci/upsert@1.1.0
+ Added@miyauci/assertion@1.0.0(transitive)
+ Added@miyauci/isx@1.3.1(transitive)
+ Added@miyauci/upsert@1.1.0(transitive)
- Removed@miyauci/isx@1.4.0
- Removed@miyauci/isx@1.4.0(transitive)