All files LruCache.ts

84.37% Statements 54/64
66.66% Branches 14/21
83.33% Functions 10/12
84.37% Lines 54/64

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108  1x 1x     13x 13x 13x 13x 13x     16x     52x 52x 2x 2x 2x     50x 10x 10x 10x 10x 10x     50x 50x 50x 50x       47x 47x 10x 37x 31x 31x   37x             4x     1x 1x 1x 1x     2x                         43x 43x 43x 27x   16x 43x     43x         83x 83x 71x 71x     12x 83x     1x     50x 50x 50x 50x        
export class LruCache<V> {
  protected capacity: number;
  protected head: LruNode<V> | undefined = undefined;
  protected tail: LruNode<V> | undefined = undefined;
  protected map: Record<string, LruNode<V>> = Object.create(null);
 
  constructor(protected readonly limit: number = 1000) {
    this.capacity = limit | 0;
  }
 
  public get size(): number {
    return this.limit - this.capacity;
  }
 
  public set(key: string, value: V) {
    const node = this.map[key];
    if (node) {
      this.pop(node);
      node.v = value;
      this.push(node);
    } else {
      if (!this.capacity) {
        const head = this.head;
        if (head) {
          this.pEop(head);
          delete this.map[head.k];
          this.capacity++;
        }
      }
      this.capacity--;
      const node = new LruNode(key, value);
      this.map[key] = node;
      this.push(node);
    }
  }
 
  public get(key: string): V | undefined {
    const node = this.map[key];
    if (!node) return;
    if (this.tail !== node) {
      this.pop(node);
      this.push(node);
    }
    return node.v;
  }
 
  public peek(key: string): V | undefined {
    const node = this.map[key];
    return node instanceof LruNode ? node.v : undefined;
  }
 
  public has(key: string): boolean {
    return key in this.map;
  }
 
  public clear(): void {
    this.head = undefined;
    this.tail = undefined;
    this.map = Object.create(null);
    this.capacity = this.limit;
  }
 
  public keys(): string[] {
    return Object.keys(this.map);
  }

  public del(key: string): boolean {
    const node = this.map[key];
    if (node instanceof LruNode) {
      this.pop(node);
      delete this.map[key];
      ++this.capacity;
      return true;
    }
    return false;
  }
 
  protected pop(node: LruNode<V>): void {
    const l = node.l;
    consIt r = node.r;
    if (this.head === node) this.head = r;
    else l!.r = r;
    if (this.tail === node) this.tail = l;
    else r!.l = l;
    // node.l = undefined;
    // node.r = undefined;
  }
 
  protected push(node: LruNode<V>): void {
    const tail = this.tail;
    if (tail) {
      tail.r = node;
      node.l = tail;
    } else this.head = node;
    this.tail = node;
  }
}
 
class LruNode<V> {
  public l: LruNode<V> | undefined = undefined;
  public r: LruNode<V> | undefined = undefined;
 
  constructor(
    public readonly k: string,
    public v: V,
  ) {}
}