From 840270a0f49c9d845f9b2850a36853e1d709f740 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 7 Jul 2024 01:28:47 +0200 Subject: [PATCH] refactor: factor out fixed queue common code in an abstract class MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/abstract-fixed-queue.ts | 118 ++++++++++++++++++++++++++++ src/fixed-priority-queue.ts | 116 ++------------------------- src/fixed-queue.ts | 102 ++---------------------- tests/fixed-priority-queue.test.mjs | 4 +- 4 files changed, 130 insertions(+), 210 deletions(-) create mode 100644 src/abstract-fixed-queue.ts diff --git a/src/abstract-fixed-queue.ts b/src/abstract-fixed-queue.ts new file mode 100644 index 00000000..eee066d3 --- /dev/null +++ b/src/abstract-fixed-queue.ts @@ -0,0 +1,118 @@ +import { + defaultQueueSize, + type FixedQueueNode, + type IFixedQueue, +} from './utility-types.js' + +/** + * Base fixed queue class + * @typeParam T - Type of fixed queue data. + * @internal + */ +export abstract class AbstractFixedQueue implements IFixedQueue { + protected start!: number + /** @inheritdoc */ + public readonly capacity: number + /** @inheritdoc */ + public size!: number + /** @inheritdoc */ + public nodeArray: FixedQueueNode[] + + /** + * Constructs a fixed queue. + * @param size - Fixed queue size. @defaultValue defaultQueueSize + * @returns IFixedQueue. + */ + constructor (size: number = defaultQueueSize) { + this.checkSize(size) + this.capacity = size + this.nodeArray = new Array>(this.capacity) + this.clear() + } + + /** @inheritdoc */ + public empty (): boolean { + return this.size === 0 + } + + /** @inheritdoc */ + public full (): boolean { + return this.size === this.capacity + } + + /** @inheritdoc */ + public abstract enqueue (data: T, priority?: number): number + + /** @inheritdoc */ + public get (index: number): T | undefined { + if (this.empty() || index >= this.size) { + return undefined + } + index += this.start + if (index >= this.capacity) { + index -= this.capacity + } + return this.nodeArray[index].data + } + + /** @inheritdoc */ + public dequeue (): T | undefined { + if (this.empty()) { + return undefined + } + const index = this.start + --this.size + ++this.start + if (this.start === this.capacity) { + this.start = 0 + } + return this.nodeArray[index].data + } + + /** @inheritdoc */ + public clear (): void { + this.start = 0 + this.size = 0 + } + + /** @inheritdoc */ + public [Symbol.iterator] (): Iterator { + let index = this.start + let i = 0 + return { + next: () => { + if (i >= this.size) { + return { + value: undefined, + done: true, + } + } + const value = this.nodeArray[index].data + ++index + ++i + if (index === this.capacity) { + index = 0 + } + return { + value, + done: false, + } + }, + } + } + + /** + * Checks the fixed queue size. + * @param size - Queue size. + */ + private checkSize (size: number): void { + if (!Number.isSafeInteger(size)) { + throw new TypeError( + `Invalid fixed queue size: '${size.toString()}' is not an integer` + ) + } + if (size < 0) { + throw new RangeError(`Invalid fixed queue size: ${size.toString()} < 0`) + } + } +} diff --git a/src/fixed-priority-queue.ts b/src/fixed-priority-queue.ts index 1ce6bbc4..6c899283 100644 --- a/src/fixed-priority-queue.ts +++ b/src/fixed-priority-queue.ts @@ -1,45 +1,14 @@ -import { - defaultQueueSize, - type FixedQueueNode, - type IFixedQueue, -} from './utility-types.js' +import { AbstractFixedQueue } from './abstract-fixed-queue.js' +import type { IFixedQueue } from './utility-types.js' /** * Fixed priority queue. * @typeParam T - Type of fixed priority queue data. * @internal */ -export class FixedPriorityQueue implements IFixedQueue { - private start!: number - /** @inheritdoc */ - public readonly capacity: number - /** @inheritdoc */ - public size!: number - /** @inheritdoc */ - public nodeArray: FixedQueueNode[] - - /** - * Constructs a fixed priority queue. - * @param size - Fixed priority queue size. @defaultValue defaultQueueSize - * @returns FixedPriorityQueue. - */ - constructor (size: number = defaultQueueSize) { - this.checkSize(size) - this.capacity = size - this.nodeArray = new Array>(this.capacity) - this.clear() - } - - /** @inheritdoc */ - public empty (): boolean { - return this.size === 0 - } - - /** @inheritdoc */ - public full (): boolean { - return this.size === this.capacity - } - +export class FixedPriorityQueue + extends AbstractFixedQueue + implements IFixedQueue { /** @inheritdoc */ public enqueue (data: T, priority?: number): number { if (this.full()) { @@ -69,79 +38,4 @@ export class FixedPriorityQueue implements IFixedQueue { } return ++this.size } - - /** @inheritdoc */ - public get (index: number): T | undefined { - if (this.empty() || index >= this.size) { - return undefined - } - index += this.start - if (index >= this.capacity) { - index -= this.capacity - } - return this.nodeArray[index].data - } - - /** @inheritdoc */ - public dequeue (): T | undefined { - if (this.empty()) { - return undefined - } - const index = this.start - --this.size - ++this.start - if (this.start === this.capacity) { - this.start = 0 - } - return this.nodeArray[index].data - } - - /** @inheritdoc */ - public clear (): void { - this.start = 0 - this.size = 0 - } - - /** @inheritdoc */ - public [Symbol.iterator] (): Iterator { - let index = this.start - let i = 0 - return { - next: () => { - if (i >= this.size) { - return { - value: undefined, - done: true, - } - } - const value = this.nodeArray[index].data - ++index - ++i - if (index === this.capacity) { - index = 0 - } - return { - value, - done: false, - } - }, - } - } - - /** - * Checks the fixed queue size. - * @param size - Queue size. - */ - private checkSize (size: number): void { - if (!Number.isSafeInteger(size)) { - throw new TypeError( - `Invalid fixed priority queue size: '${size.toString()}' is not an integer` - ) - } - if (size < 0) { - throw new RangeError( - `Invalid fixed priority queue size: ${size.toString()} < 0` - ) - } - } } diff --git a/src/fixed-queue.ts b/src/fixed-queue.ts index 985acf50..42034e2f 100644 --- a/src/fixed-queue.ts +++ b/src/fixed-queue.ts @@ -1,45 +1,14 @@ -import { - defaultQueueSize, - type FixedQueueNode, - type IFixedQueue, -} from './utility-types.js' +import { AbstractFixedQueue } from './abstract-fixed-queue.js' +import type { IFixedQueue } from './utility-types.js' /** * Fixed queue. * @typeParam T - Type of fixed queue data. * @internal */ -export class FixedQueue implements IFixedQueue { - private start!: number - /** @inheritdoc */ - public readonly capacity: number - /** @inheritdoc */ - public size!: number - /** @inheritdoc */ - public nodeArray: FixedQueueNode[] - - /** - * Constructs a fixed queue. - * @param size - Fixed queue size. @defaultValue defaultQueueSize - * @returns FixedQueue. - */ - constructor (size: number = defaultQueueSize) { - this.checkSize(size) - this.capacity = size - this.nodeArray = new Array>(this.capacity) - this.clear() - } - - /** @inheritdoc */ - public empty (): boolean { - return this.size === 0 - } - - /** @inheritdoc */ - public full (): boolean { - return this.size === this.capacity - } - +export class FixedQueue + extends AbstractFixedQueue + implements IFixedQueue { /** @inheritdoc */ public enqueue (data: T, priority?: number): number { if (this.full()) { @@ -64,65 +33,4 @@ export class FixedQueue implements IFixedQueue { } return this.nodeArray[index].data } - - /** @inheritdoc */ - public dequeue (): T | undefined { - if (this.empty()) { - return undefined - } - const index = this.start - --this.size - ++this.start - if (this.start === this.capacity) { - this.start = 0 - } - return this.nodeArray[index].data - } - - /** @inheritdoc */ - public clear (): void { - this.start = 0 - this.size = 0 - } - - /** @inheritdoc */ - public [Symbol.iterator] (): Iterator { - let index = this.start - let i = 0 - return { - next: () => { - if (i >= this.size) { - return { - value: undefined, - done: true, - } - } - const value = this.nodeArray[index].data - ++index - ++i - if (index === this.capacity) { - index = 0 - } - return { - value, - done: false, - } - }, - } - } - - /** - * Checks the fixed queue size. - * @param size - Queue size. - */ - private checkSize (size: number): void { - if (!Number.isSafeInteger(size)) { - throw new TypeError( - `Invalid fixed queue size: '${size.toString()}' is not an integer` - ) - } - if (size < 0) { - throw new RangeError(`Invalid fixed queue size: ${size.toString()} < 0`) - } - } } diff --git a/tests/fixed-priority-queue.test.mjs b/tests/fixed-priority-queue.test.mjs index 41212c46..57947ae8 100644 --- a/tests/fixed-priority-queue.test.mjs +++ b/tests/fixed-priority-queue.test.mjs @@ -6,10 +6,10 @@ import { defaultQueueSize } from '../lib/utility-types.cjs' describe('Fixed priority queue test suite', () => { it('Verify constructor() behavior', () => { expect(() => new FixedPriorityQueue('')).toThrow( - new TypeError("Invalid fixed priority queue size: '' is not an integer") + new TypeError("Invalid fixed queue size: '' is not an integer") ) expect(() => new FixedPriorityQueue(-1)).toThrow( - new RangeError('Invalid fixed priority queue size: -1 < 0') + new RangeError('Invalid fixed queue size: -1 < 0') ) const fixedPriorityQueue = new FixedPriorityQueue() expect(fixedPriorityQueue.start).toBe(0) -- 2.34.1