| export class CircularBuffer<T> { | |
| private buf: T[] | |
| private head = 0 | |
| private len = 0 | |
| constructor(private capacity: number) { | |
| if (!Number.isInteger(capacity) || capacity <= 0) { | |
| throw new RangeError(`CircularBuffer capacity must be a positive integer, got ${capacity}`) | |
| } | |
| this.buf = new Array<T>(capacity) | |
| } | |
| push(item: T) { | |
| this.buf[this.head] = item | |
| this.head = (this.head + 1) % this.capacity | |
| if (this.len < this.capacity) { | |
| this.len++ | |
| } | |
| } | |
| tail(n = this.len): T[] { | |
| const take = Math.min(Math.max(0, n), this.len) | |
| const start = this.len < this.capacity ? 0 : this.head | |
| const out: T[] = new Array<T>(take) | |
| for (let i = 0; i < take; i++) { | |
| out[i] = this.buf[(start + this.len - take + i) % this.capacity]! | |
| } | |
| return out | |
| } | |
| drain(): T[] { | |
| const out = this.tail() | |
| this.clear() | |
| return out | |
| } | |
| clear() { | |
| this.buf = new Array<T>(this.capacity) | |
| this.head = 0 | |
| this.len = 0 | |
| } | |
| } | |