refactor: factor out fixed queue common code in an abstract class
[poolifier.git] / src / abstract-fixed-queue.ts
CommitLineData
840270a0
JB
1import {
2 defaultQueueSize,
3 type FixedQueueNode,
4 type IFixedQueue,
5} from './utility-types.js'
6
7/**
8 * Base fixed queue class
9 * @typeParam T - Type of fixed queue data.
10 * @internal
11 */
12export abstract class AbstractFixedQueue<T> implements IFixedQueue<T> {
13 protected start!: number
14 /** @inheritdoc */
15 public readonly capacity: number
16 /** @inheritdoc */
17 public size!: number
18 /** @inheritdoc */
19 public nodeArray: FixedQueueNode<T>[]
20
21 /**
22 * Constructs a fixed queue.
23 * @param size - Fixed queue size. @defaultValue defaultQueueSize
24 * @returns IFixedQueue.
25 */
26 constructor (size: number = defaultQueueSize) {
27 this.checkSize(size)
28 this.capacity = size
29 this.nodeArray = new Array<FixedQueueNode<T>>(this.capacity)
30 this.clear()
31 }
32
33 /** @inheritdoc */
34 public empty (): boolean {
35 return this.size === 0
36 }
37
38 /** @inheritdoc */
39 public full (): boolean {
40 return this.size === this.capacity
41 }
42
43 /** @inheritdoc */
44 public abstract enqueue (data: T, priority?: number): number
45
46 /** @inheritdoc */
47 public get (index: number): T | undefined {
48 if (this.empty() || index >= this.size) {
49 return undefined
50 }
51 index += this.start
52 if (index >= this.capacity) {
53 index -= this.capacity
54 }
55 return this.nodeArray[index].data
56 }
57
58 /** @inheritdoc */
59 public dequeue (): T | undefined {
60 if (this.empty()) {
61 return undefined
62 }
63 const index = this.start
64 --this.size
65 ++this.start
66 if (this.start === this.capacity) {
67 this.start = 0
68 }
69 return this.nodeArray[index].data
70 }
71
72 /** @inheritdoc */
73 public clear (): void {
74 this.start = 0
75 this.size = 0
76 }
77
78 /** @inheritdoc */
79 public [Symbol.iterator] (): Iterator<T> {
80 let index = this.start
81 let i = 0
82 return {
83 next: () => {
84 if (i >= this.size) {
85 return {
86 value: undefined,
87 done: true,
88 }
89 }
90 const value = this.nodeArray[index].data
91 ++index
92 ++i
93 if (index === this.capacity) {
94 index = 0
95 }
96 return {
97 value,
98 done: false,
99 }
100 },
101 }
102 }
103
104 /**
105 * Checks the fixed queue size.
106 * @param size - Queue size.
107 */
108 private checkSize (size: number): void {
109 if (!Number.isSafeInteger(size)) {
110 throw new TypeError(
111 `Invalid fixed queue size: '${size.toString()}' is not an integer`
112 )
113 }
114 if (size < 0) {
115 throw new RangeError(`Invalid fixed queue size: ${size.toString()} < 0`)
116 }
117 }
118}