packageDocumentation module import { OrderedComparator } from "./Compare" ; import { Dictionary } from "./Dictionary" ; /**
 * Derived from:
 * Licensed under MIT. Copyright (c) 2010 Rasmus Andersson <http://hunch.se/>
 * See README.md at https://github.com/rsms/js-lru for details.
 */ public export class Entry < K , V > { public newer ? : Entry < K , V > ; public older ? : Entry < K , V > ; constructor ( public key , public value ) { } } class EntryIterator < K , V > implements Iterator < [ K , V ] | undefined > { private _entry : Entry < K , V > | undefined ; constructor ( oldestEntry ) { this . _entry = oldestEntry ; } public next ( ) { const ent = this . _entry ; if ( ! ent ) return { done : true , value : undefined } ; this . _entry = ent . newer ; const val = [ ent . key , ent . value ] ; return { done : false , value : val } ; } } class KeyIterator < K , V > implements Iterator < K | undefined > { private _entry : Entry < K , V > | undefined ; constructor ( oldestEntry ) { this . _entry = oldestEntry ; } public next ( ) { const ent = this . _entry ; if ( ! ent ) return { done : true , value : undefined } ; this . _entry = ent . newer ; return { done : false , value : ent . key } ; } } class ValueIterator < K , V > implements Iterator < V | undefined > { private _entry : Entry < K , V > | undefined ; constructor ( oldestEntry ) { this . _entry = oldestEntry ; } public next ( ) { const ent = this . _entry ; if ( ! ent ) return { done : true , value : undefined } ; this . _entry = ent . newer ; return { done : false , value : ent . value } ; } } public export interface EntryContainer < K , V > { readonly size : number ; clear ( ) : void ; get ( key ) : Entry < K , V > | undefined ; set ( key , value ) : void ; has ( key ) : boolean ; delete ( key ) : void ; } public export class LRUCache < K , V > { private _container : EntryContainer < K , V > ; /** Current number of items */ public size : number ; /** Maximum number of items this cache can hold */ public limit : number ; /** Least recently-used entry. Invalidated when cache is modified. */ public oldest ? : Entry < K , V > ; /** Most recently-used entry. Invalidated when cache is modified. */ public newest ? : Entry < K , V > ; /**
     * Construct a new LRUCache to hold up to `limit` entries.
     */ public constructor ( limit , container ) { this . size = 0 ; this . limit = limit ; this . oldest = this . newest = undefined ; this . _container = container ; } private markEntryAsUsed ( entry ) { if ( entry === this . newest ) return ; if ( entry . newer ) { if ( entry === this . oldest ) { this . oldest = entry . newer ; } entry . newer . older = entry . older ; } if ( entry . older ) { entry . older . newer = entry . newer ; } entry . newer = undefined ; entry . older = this . newest ; if ( this . newest ) { this . newest . newer = entry ; } this . newest = entry ; } /**  Replace all values in this cache with key-value pairs (2-element Arrays) from provided iterable. */ public assign ( entries ) { let entry ; let limit = this . limit || Number . MAX_VALUE ; this . _container . clear ( ) ; const it = entries [ Symbol . iterator ] ( ) ; for ( let itv = it . next ( ) ; ! itv . done ; itv = it . next ( ) ) { const e = new Entry ( itv . value [ 0 ] , itv . value [ 1 ] ) ; this . _container . set ( e . key , e ) ; if ( ! entry ) { this . oldest = e ; } else { entry . newer = e ; e . older = entry ; } entry = e ; if ( limit -- === 0 ) { throw new Error ( "overflow" ) ; } } this . newest = entry ; this . size = this . _container . size ; } /** Get and register recent use of <key>.
     *  Returns the value associated with <key> or undefined if not in cache.
     */ public get ( key ) { const entry = this . _container . get ( key ) ; if ( ! entry ) return ; this . markEntryAsUsed ( entry ) ; return entry . value ; } returns public set ( key , value ) { let entry = this . _container . get ( key ) ; if ( entry ) { entry . value = value ; this . markEntryAsUsed ( entry ) ; return this ; } this . _container . set ( key , ( entry = new Entry ( key , value ) ) ) ; if ( this . newest ) { this . newest . newer = entry ; entry . older = this . newest ; } else { this . oldest = entry ; } this . newest = entry ; ++ this . size ; if ( this . size > this . limit ) { this . shift ( ) ; } return this ; } returns public shift ( ) { const entry = this . oldest ; if ( entry ) { if ( entry . newer ) { this . oldest = entry . newer ; this . oldest . older = undefined ; } else { this . oldest = undefined ; this . newest = undefined ; } entry . newer = entry . older = undefined ; this . _container . delete ( entry . key ) ; -- this . size ; return [ entry . key , entry . value ] ; } return undefined ; } returns public find ( key ) { const e = this . _container . get ( key ) ; return e ? e . value : undefined ; } /** Check if there's a value for key in the cache without registering recent use. */ public has ( key ) { return this . _container . has ( key ) ; } returns public delete ( key ) { const entry = this . _container . get ( key ) ; if ( ! entry ) return ; this . _container . delete ( entry . key ) ; if ( entry . newer && entry . older ) { entry . older . newer = entry . newer ; entry . newer . older = entry . older ; } else if ( entry . newer ) { entry . newer . older = undefined ; this . oldest = entry . newer ; } else if ( entry . older ) { entry . older . newer = undefined ; this . newest = entry . older ; } else { this . oldest = this . newest = undefined ; } this . size -- ; return entry . value ; } /**  Removes all entries */ public clear ( ) { this . oldest = this . newest = undefined ; this . size = 0 ; this . _container . clear ( ) ; } /** Returns an iterator over all keys, starting with the oldest. */ public keys ( ) { return this . oldest ? new KeyIterator ( this . oldest ) : undefined ; } /** Returns an iterator over all values, starting with the oldest. */ public values ( ) { return this . oldest ? new ValueIterator ( this . oldest ) : undefined ; } /** Returns an iterator over all entries, starting with the oldest. */ public entries ( ) { return this . oldest ? new EntryIterator ( this . oldest ) : undefined ; } /**  Call `fun` for each entry, starting with the oldest entry. */ public forEach ( fun , thisObj ? ) { if ( typeof thisObj !== "object" ) { thisObj = this ; } let entry = this . oldest ; while ( entry ) { fun . call ( thisObj , entry . value , entry . key , this ) ; entry = entry . newer ; } } /** Returns a JSON (array) representation */ public toJSON ( ) { const s = new Array ( this . size ) ; let i = 0 ; let entry = this . oldest ; while ( entry ) { s [ i ++ ] = { key : entry . key , value : entry . value } ; entry = entry . newer ; } return s ; } /** Returns a String representation */ public toString ( ) { let s = "" ; let entry = this . oldest ; while ( entry ) { s += `${ String ( entry . key ) }:${ entry . value }` ; entry = entry . newer ; if ( entry ) { s += " < " ; } } return s ; } } public export class LRUMap < K , V > extends LRUCache < K , V > { /**
     * Construct a new LRUMap to hold up to `limit` entries.
     */ constructor ( limit ) { super ( limit , new Map < K , Entry < K , V > > ( ) ) ; } } public export class LRUDictionary < K , V > extends LRUCache < K , V > { param limit param compareKeys constructor ( limit , compareKeys ) { super ( limit , new Dictionary < K , Entry < K , V > > ( compareKeys ) ) ; } }