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