UNPKG

rc-js-util

Version:

A collection of TS and C++ utilities to help writing performant and correct applications, achieved through strict typing and (removable) invariant checking.

107 lines 3.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CircularFIFOStack = exports.ECircularStackOverflowMode = void 0; const circular_buffer_js_1 = require("./circular-buffer.js"); const _production_js_1 = require("../production/_production.js"); /** * @public * Sets the behavior of {@link CircularFIFOStack} when a value is pushed which won't fit. * * @remarks * Does not affect underflow, which is always considered exceptional. */ var ECircularStackOverflowMode; (function (ECircularStackOverflowMode) { /** * Do nothing. */ ECircularStackOverflowMode[ECircularStackOverflowMode["NoOp"] = 1] = "NoOp"; /** * Throw an error if the buffer overflows. */ ECircularStackOverflowMode[ECircularStackOverflowMode["Exception"] = 2] = "Exception"; /** * Overwrite the first value. */ ECircularStackOverflowMode[ECircularStackOverflowMode["Overwrite"] = 3] = "Overwrite"; /** * Doubles the stack size and copies in place, running in O(size). */ ECircularStackOverflowMode[ECircularStackOverflowMode["Grow"] = 4] = "Grow"; })(ECircularStackOverflowMode || (exports.ECircularStackOverflowMode = ECircularStackOverflowMode = {})); /** * @public * Circular first in first out stack. * * @remarks * See {@link ECircularStackOverflowMode} for details of overflow behavior. */ class CircularFIFOStack { constructor(capacity, mode = ECircularStackOverflowMode.Grow) { this.start = 0; this.end = 0; this.capacity = capacity; this.mode = mode; this.buffer = circular_buffer_js_1.CircularBuffer.createEmpty(capacity); } getCapacity() { return this.capacity; } /** * Pushes a value to the top of the stack (depending on `mode`). */ push(value) { if (this.start + this.buffer.size == this.end) { switch (this.mode) { case ECircularStackOverflowMode.NoOp: return; case ECircularStackOverflowMode.Exception: throw _production_js_1._Production.createError("Attempted to push to full stack."); break; case ECircularStackOverflowMode.Overwrite: this.pop(); break; case ECircularStackOverflowMode.Grow: this.growStack(); break; default: _production_js_1._Production.assertValueIsNever(this.mode); } } this.buffer.setValue(this.end++, value); } /** * Remove the bottom element in the stack and return it. * * @remarks * Attempting to pop an empty stack is considered exceptional regardless of `mode`. You can * call `getIsEmpty` or `getRemainingCapacity` to determine if pop is safe to call. */ pop() { if (this.getIsEmpty()) { throw _production_js_1._Production.createError("Attempted to pop empty stack."); } // null out the value to avoid memory leaks return this.buffer.getSetValue(this.start++, null); } getIsEmpty() { return this.start == this.end; } getRemainingCapacity() { return this.start + this.capacity - this.end; } growStack() { const largerCircularStack = new CircularFIFOStack(this.capacity * 2, this.mode); let size = this.capacity; while (size--) { const valueToCopy = this.pop(); largerCircularStack.push(valueToCopy); } this.buffer = largerCircularStack.buffer; this.capacity *= 2; this.start = largerCircularStack.start; this.end = largerCircularStack.end; } } exports.CircularFIFOStack = CircularFIFOStack; //# sourceMappingURL=circular-fifo-stack.js.map