| 
									
										
										
										
											2021-02-02 08:22:19 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class ArrayQueue { | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {Iterable<T>=} items The initial elements. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	constructor(items) { | 
					
						
							|  |  |  | 		/** @private @type {T[]} */ | 
					
						
							|  |  |  | 		this._list = items ? Array.from(items) : []; | 
					
						
							|  |  |  | 		/** @private @type {T[]} */ | 
					
						
							|  |  |  | 		this._listReversed = []; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * Returns the number of elements in this queue. | 
					
						
							|  |  |  | 	 * @returns {number} The number of elements in this queue. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	get length() { | 
					
						
							|  |  |  | 		return this._list.length + this._listReversed.length; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:09:48 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * Empties the queue. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	clear() { | 
					
						
							|  |  |  | 		this._list.length = 0; | 
					
						
							|  |  |  | 		this._listReversed.length = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-02 08:22:19 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * Appends the specified element to this queue. | 
					
						
							|  |  |  | 	 * @param {T} item The element to add. | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	enqueue(item) { | 
					
						
							|  |  |  | 		this._list.push(item); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * Retrieves and removes the head of this queue. | 
					
						
							|  |  |  | 	 * @returns {T | undefined} The head of the queue of `undefined` if this queue is empty. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	dequeue() { | 
					
						
							|  |  |  | 		if (this._listReversed.length === 0) { | 
					
						
							|  |  |  | 			if (this._list.length === 0) return undefined; | 
					
						
							|  |  |  | 			if (this._list.length === 1) return this._list.pop(); | 
					
						
							|  |  |  | 			if (this._list.length < 16) return this._list.shift(); | 
					
						
							|  |  |  | 			const temp = this._listReversed; | 
					
						
							|  |  |  | 			this._listReversed = this._list; | 
					
						
							|  |  |  | 			this._listReversed.reverse(); | 
					
						
							|  |  |  | 			this._list = temp; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return this._listReversed.pop(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * Finds and removes an item | 
					
						
							|  |  |  | 	 * @param {T} item the item | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	delete(item) { | 
					
						
							|  |  |  | 		const i = this._list.indexOf(item); | 
					
						
							|  |  |  | 		if (i >= 0) { | 
					
						
							|  |  |  | 			this._list.splice(i, 1); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			const i = this._listReversed.indexOf(item); | 
					
						
							|  |  |  | 			if (i >= 0) this._listReversed.splice(i, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	[Symbol.iterator]() { | 
					
						
							|  |  |  | 		let i = -1; | 
					
						
							|  |  |  | 		let reversed = false; | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			next: () => { | 
					
						
							|  |  |  | 				if (!reversed) { | 
					
						
							|  |  |  | 					i++; | 
					
						
							|  |  |  | 					if (i < this._list.length) { | 
					
						
							|  |  |  | 						return { | 
					
						
							|  |  |  | 							done: false, | 
					
						
							|  |  |  | 							value: this._list[i] | 
					
						
							|  |  |  | 						}; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					reversed = true; | 
					
						
							|  |  |  | 					i = this._listReversed.length; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				i--; | 
					
						
							|  |  |  | 				if (i < 0) { | 
					
						
							|  |  |  | 					return { | 
					
						
							|  |  |  | 						done: true, | 
					
						
							|  |  |  | 						value: undefined | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return { | 
					
						
							|  |  |  | 					done: false, | 
					
						
							|  |  |  | 					value: this._listReversed[i] | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = ArrayQueue; |