feat: fully implement circular buffer semantic
[poolifier.git] / src / circular-buffer.ts
CommitLineData
f12182ad 1/**
db89e3bc 2 * Default buffer size.
f12182ad
JB
3 */
4export const defaultBufferSize = 2048
5
6/**
c9c71898 7 * Circular buffer.
db89e3bc
JB
8 *
9 * @typeParam T - Type of buffer data.
10 * @internal
f12182ad
JB
11 */
12export class CircularBuffer<T> {
cf42a4cf 13 private readIdx: number
f12182ad
JB
14 private writeIdx: number
15 private items: Array<T | undefined>
16 private readonly maxArrayIdx: number
cf42a4cf 17 public size: number
f12182ad
JB
18
19 /**
db89e3bc
JB
20 * @param size - Buffer size. @defaultValue defaultBufferSize
21 * @returns CircularBuffer.
f12182ad
JB
22 */
23 constructor (size: number = defaultBufferSize) {
24 this.checkSize(size)
25 this.readIdx = 0
26 this.writeIdx = 0
27 this.maxArrayIdx = size - 1
cf42a4cf 28 this.size = 0
f12182ad
JB
29 this.items = new Array<T | undefined>(size)
30 }
31
cf42a4cf
JB
32 /**
33 * Checks whether the buffer is empty.
34 *
35 * @returns Whether the buffer is empty.
36 */
37 public empty (): boolean {
38 return this.size === 0
39 }
40
41 /**
42 * Checks whether the buffer is full.
43 *
44 * @returns Whether the buffer is full.
45 */
46 public full (): boolean {
47 return this.size === this.items.length
48 }
49
f12182ad 50 /**
db89e3bc 51 * Puts data into buffer.
f12182ad 52 *
db89e3bc 53 * @param data - Data to put into buffer.
f12182ad
JB
54 */
55 public put (data: T): void {
56 this.items[this.writeIdx] = data
57 this.writeIdx = this.writeIdx === this.maxArrayIdx ? 0 : this.writeIdx + 1
cf42a4cf
JB
58 if (this.size < this.items.length) {
59 ++this.size
60 }
61 }
62
63 /**
64 * Gets data from buffer.
65 *
66 * @returns Data from buffer.
67 */
68 public get (): T | undefined {
69 const data = this.items[this.readIdx]
70 if (data == null) {
71 return
72 }
73 this.items[this.readIdx] = undefined
74 this.readIdx = this.readIdx === this.maxArrayIdx ? 0 : this.readIdx + 1
75 --this.size
76 return data
f12182ad
JB
77 }
78
79 /**
db89e3bc 80 * Returns buffer as array.
f12182ad 81 *
db89e3bc 82 * @returns Array of buffer data.
f12182ad
JB
83 */
84 public toArray (): T[] {
85 return this.items.filter(item => item != null) as T[]
86 }
87
88 private checkSize (size: number): void {
89 if (!Number.isSafeInteger(size)) {
90 throw new TypeError(
91 `Invalid circular buffer size: ${size} is not an integer`
92 )
93 }
94 if (size < 0) {
95 throw new RangeError(`Invalid circular buffer size: ${size} < 0`)
96 }
97 }
98}