diff --git a/shared/utility/index.mjs b/shared/utility/index.mjs index a39de4e..9f7a1ea 100644 --- a/shared/utility/index.mjs +++ b/shared/utility/index.mjs @@ -1 +1,2 @@ export { areArrayBuffersEqual } from './buffer.mjs'; +export { Queue, QueueEmptyError } from './queue.mjs'; diff --git a/shared/utility/queue.mjs b/shared/utility/queue.mjs new file mode 100644 index 0000000..cbe4d72 --- /dev/null +++ b/shared/utility/queue.mjs @@ -0,0 +1,127 @@ +/** + * Represents a queue data structure. + * @class + */ +export class Queue { + /** + * Creates an instance of Queue. + * @constructor + */ + constructor() { + /** + * The data array to store elements. + * @type {Array} + * @private + */ + this.data = []; + /** + * The index of the front element in the queue. + * @type {number} + * @private + */ + this.head = 0; + } + + /** + * Retrieves the front element of the queue. + * @returns {*} The front element of the queue. + */ + front() { + return this.data[this.head]; + } + + /** + * Retrieves the back element of the queue. + * @returns {*} The back element of the queue. + */ + back() { + return this.data[this.data.length - 1]; + } + + /** + * Removes the back element from the queue. + * @throws {QueueEmptyError} Throws an error if the queue is empty. + */ + popBack() { + if (this.data.length == this.head) { + throw new QueueEmptyError(); + } + this.data.length -= 1; + } + + /** + * Checks if the queue is empty. + * @returns {boolean} True if the queue is empty, otherwise false. + */ + empty() { + return this.data.length == this.head; + } + + /** + * Returns the size of the queue. + * @returns {number} The size of the queue. + */ + size() { + return this.data.length - this.head; + } + + /** + * Alias for the size() method. + * @type {number} + */ + get length() { + return this.size(); + } + + /** + * Pushes elements into the queue. + * @param {...*} elements The elements to push into the queue. + */ + push() { + this.data.push.apply(this.data, arguments); + } + + /** + * Removes the front element from the queue. + * @throws {QueueEmptyError} Throws an error if the queue is empty. + */ + popFront() { + if (this.empty()) { throw new QueueEmptyError();} + + this.head += 1; + if (this.head == this.data.length) { + this.data = []; + this.head = 0; + return; + } + if (this.head >= this.data.length >> 1 && this.head >= 16) { + this.data = this.data.slice(this.head); + this.head = 0; + } + } + + /** + * Returns an iterator that allows iterating through the elements of the queue. + * @returns {*} elements of the queue. + * @generator + */ + *[Symbol.iterator]() { + for (let i = this.head; i < this.data.length; i += 1) { + yield this.data[i]; + } + } +} + +/** + * Represents an error thrown when attempting operations on an empty queue. + * @class + */ +export class QueueEmptyError extends Error { + /** + * Creates an instance of QueueEmptyError. + * @constructor + */ + constructor() { + super('Queue is empty'); + } +}