time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (9113B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 /* eslint-disable no-restricted-syntax, no-invalid-this */
     20 
     21 'use strict';
     22 
     23 // MODULES //
     24 
     25 var setReadOnly = require( './../../define-nonenumerable-read-only-property' );
     26 var setReadOnlyAccessor = require( './../../define-nonenumerable-read-only-accessor' );
     27 var iteratorSymbol = require( '@stdlib/symbol/iterator' );
     28 var Node = require( './node.js' ); // eslint-disable-line stdlib/no-redeclare
     29 
     30 
     31 // MAIN //
     32 
     33 /**
     34 * First-in-first-out queue constructor.
     35 *
     36 * @constructor
     37 * @returns {FIFO} FIFO queue instance
     38 *
     39 * @example
     40 * var queue = new FIFO();
     41 *
     42 * // Add values to the queue:
     43 * queue.push( 'foo' ).push( 'bar' );
     44 *
     45 * // Remove the first value:
     46 * var v = queue.pop();
     47 * // returns 'foo'
     48 *
     49 * // Add a new value to the queue:
     50 * queue.push( 'beep' );
     51 *
     52 * // Remove the "oldest" queue value:
     53 * v = queue.pop();
     54 * // returns 'bar'
     55 */
     56 function FIFO() {
     57 	if ( !(this instanceof FIFO) ) {
     58 		return new FIFO();
     59 	}
     60 	this._length = 0;
     61 	this._first = null;
     62 	this._last = null;
     63 	return this;
     64 }
     65 
     66 /**
     67 * Clears the queue.
     68 *
     69 * @name clear
     70 * @memberof FIFO.prototype
     71 * @type {Function}
     72 * @returns {FIFO} queue instance
     73 *
     74 * @example
     75 * var queue = new FIFO();
     76 *
     77 * // Add values to the queue:
     78 * queue.push( 'foo' ).push( 'bar' );
     79 *
     80 * // Peek at the first value:
     81 * var v = queue.first();
     82 * // returns 'foo'
     83 *
     84 * // Examine the queue length:
     85 * var len = queue.length;
     86 * // returns 2
     87 *
     88 * // Clear all queue items:
     89 * queue.clear();
     90 *
     91 * // Peek at the first value:
     92 * v = queue.first();
     93 * // returns undefined
     94 *
     95 * // Examine the queue length:
     96 * len = queue.length;
     97 * // returns 0
     98 */
     99 setReadOnly( FIFO.prototype, 'clear', function clear() {
    100 	this._length = 0;
    101 	this._first = null;
    102 	this._last = null;
    103 	return this;
    104 });
    105 
    106 /**
    107 * Returns the "oldest" queue value (i.e., the value which is "first-out").
    108 *
    109 * @name first
    110 * @memberof FIFO.prototype
    111 * @type {Function}
    112 * @returns {(*|void)} "oldest" queue value
    113 *
    114 * @example
    115 * var queue = new FIFO();
    116 *
    117 * // Add values to the queue:
    118 * queue.push( 'foo' ).push( 'bar' );
    119 *
    120 * // Peek at the first value:
    121 * var v = queue.first();
    122 * // returns 'foo'
    123 */
    124 setReadOnly( FIFO.prototype, 'first', function first() {
    125 	if ( this._length ) {
    126 		return this._first.value;
    127 	}
    128 });
    129 
    130 /**
    131 * Returns an iterator for iterating over a queue.
    132 *
    133 * ## Notes
    134 *
    135 * -   In order to prevent confusion arising from queue mutation during iteration, a returned iterator **always** iterates over a queue "snapshot", which is defined as the list of queue elements at the time of this method's invocation.
    136 *
    137 * @name iterator
    138 * @memberof FIFO.prototype
    139 * @type {Function}
    140 * @returns {Iterator} iterator
    141 *
    142 * @example
    143 * var queue = new FIFO();
    144 *
    145 * // Add values to the queue:
    146 * queue.push( 'foo' ).push( 'bar' );
    147 *
    148 * // Create an iterator:
    149 * var it = queue.iterator();
    150 *
    151 * // Iterate over the queue...
    152 * var v = it.next().value;
    153 * // returns 'foo'
    154 *
    155 * v = it.next().value;
    156 * // returns 'bar'
    157 *
    158 * var bool = it.next().done;
    159 * // returns true
    160 */
    161 setReadOnly( FIFO.prototype, 'iterator', function iterator() {
    162 	var values;
    163 	var iter;
    164 	var self;
    165 	var FLG;
    166 	var i;
    167 
    168 	self = this;
    169 
    170 	// Initialize the iteration index:
    171 	i = -1;
    172 
    173 	// Create a copy of queue values (necessary in order to "snapshot" the queue; otherwise, values could come and go between calls to `next`):
    174 	values = this.toArray();
    175 
    176 	// Create an iterator protocol-compliant object:
    177 	iter = {};
    178 	setReadOnly( iter, 'next', next );
    179 	setReadOnly( iter, 'return', end );
    180 	if ( iteratorSymbol ) {
    181 		setReadOnly( iter, iteratorSymbol, factory );
    182 	}
    183 	return iter;
    184 
    185 	/**
    186 	* Returns an iterator protocol-compliant object containing the next iterated value.
    187 	*
    188 	* @private
    189 	* @returns {Object} iterator protocol-compliant object
    190 	*/
    191 	function next() {
    192 		i += 1;
    193 		if ( FLG || i >= values.length ) {
    194 			return {
    195 				'done': true
    196 			};
    197 		}
    198 		return {
    199 			'value': values[ i ],
    200 			'done': false
    201 		};
    202 	}
    203 
    204 	/**
    205 	* Finishes an iterator.
    206 	*
    207 	* @private
    208 	* @param {*} [value] - value to return
    209 	* @returns {Object} iterator protocol-compliant object
    210 	*/
    211 	function end( value ) {
    212 		FLG = true;
    213 		if ( arguments.length ) {
    214 			return {
    215 				'value': value,
    216 				'done': true
    217 			};
    218 		}
    219 		return {
    220 			'done': true
    221 		};
    222 	}
    223 
    224 	/**
    225 	* Returns a new iterator.
    226 	*
    227 	* @private
    228 	* @returns {Iterator} iterator
    229 	*/
    230 	function factory() {
    231 		return self.iterator();
    232 	}
    233 });
    234 
    235 /**
    236 * Returns the "newest" queue value (i.e., the value which is currently "last-out").
    237 *
    238 * @name last
    239 * @memberof FIFO.prototype
    240 * @type {Function}
    241 * @returns {(*|void)} "newest" queue value
    242 *
    243 * @example
    244 * var queue = new FIFO();
    245 *
    246 * // Add values to the queue:
    247 * queue.push( 'foo' ).push( 'bar' );
    248 *
    249 * // Peek at the last value:
    250 * var v = queue.last();
    251 * // returns 'bar'
    252 */
    253 setReadOnly( FIFO.prototype, 'last', function last() {
    254 	if ( this._length ) {
    255 		return this._last.value;
    256 	}
    257 });
    258 
    259 /**
    260 * Queue length.
    261 *
    262 * @name length
    263 * @memberof FIFO.prototype
    264 * @type {NonNegativeInteger}
    265 *
    266 * @example
    267 * var queue = new FIFO();
    268 *
    269 * // Examine the initial queue length:
    270 * var len = queue.length;
    271 * // returns 0
    272 *
    273 * // Add values to the queue:
    274 * queue.push( 'foo' ).push( 'bar' );
    275 *
    276 * // Retrieve the current queue length:
    277 * len = queue.length;
    278 * // returns 2
    279 */
    280 setReadOnlyAccessor( FIFO.prototype, 'length', function get() {
    281 	return this._length;
    282 });
    283 
    284 /**
    285 * Removes a value from the queue.
    286 *
    287 * @name pop
    288 * @memberof FIFO.prototype
    289 * @type {Function}
    290 * @returns {(*|void)} removed value
    291 *
    292 * @example
    293 * var queue = new FIFO();
    294 *
    295 * // Add values to the queue:
    296 * queue.push( 'foo' ).push( 'bar' );
    297 *
    298 * // Remove the first value:
    299 * var v = queue.pop();
    300 * // returns 'foo'
    301 *
    302 * // Add a new value to the queue:
    303 * queue.push( 'beep' );
    304 *
    305 * // Remove the "oldest" queue value:
    306 * v = queue.pop();
    307 * // returns 'bar'
    308 */
    309 setReadOnly( FIFO.prototype, 'pop', function pop() {
    310 	var value;
    311 	if ( this._length ) {
    312 		// Retrieve the "first-out" value:
    313 		value = this._first.value;
    314 
    315 		// Check whether we have a new "first-out" or whether we have drained the queue...
    316 		if ( this._first.next ) {
    317 			this._first = this._first.next;
    318 			this._first.prev = null;
    319 		} else {
    320 			// Queue is empty:
    321 			this._first = null;
    322 			this._last = null;
    323 		}
    324 		// Decrement the queue length:
    325 		this._length -= 1;
    326 	}
    327 	return value;
    328 });
    329 
    330 /**
    331 * Adds a value to the queue.
    332 *
    333 * @name push
    334 * @memberof FIFO.prototype
    335 * @type {Function}
    336 * @returns {FIFO} queue instance
    337 *
    338 * @example
    339 * var queue = new FIFO();
    340 *
    341 * // Add values to the queue:
    342 * queue.push( 'foo' ).push( 'bar' );
    343 *
    344 * // Remove the first value:
    345 * var v = queue.pop();
    346 * // returns 'foo'
    347 *
    348 * // Add a new value to the queue:
    349 * queue.push( 'beep' );
    350 *
    351 * // Remove the "oldest" queue value:
    352 * v = queue.pop();
    353 * // returns 'bar'
    354 */
    355 setReadOnly( FIFO.prototype, 'push', function push( value ) {
    356 	var node;
    357 
    358 	// Create a new queue node:
    359 	node = new Node( value );
    360 
    361 	// Check whether the queue is currently empty...
    362 	if ( this._length === 0 ) {
    363 		// This is the only queued node, making it both the first and last node:
    364 		this._first = node;
    365 		this._last = node;
    366 	} else {
    367 		// Link the node to the previous most "recent" node:
    368 		node.prev = this._last;
    369 
    370 		// Link the previous most "recent" node to the new node:
    371 		this._last.next = node;
    372 
    373 		// Update the queue pointer for the "last" node to the new node:
    374 		this._last = node;
    375 	}
    376 	// Increment the queue length:
    377 	this._length += 1;
    378 
    379 	return this;
    380 });
    381 
    382 /**
    383 * Returns an array of queue values.
    384 *
    385 * @name toArray
    386 * @memberof FIFO.prototype
    387 * @type {Function}
    388 * @returns {Array} queue values
    389 *
    390 * @example
    391 * var queue = new FIFO();
    392 *
    393 * // Add values to the queue:
    394 * queue.push( 'foo' ).push( 'bar' );
    395 *
    396 * // Get an array of queue values:
    397 * var vals = queue.toArray();
    398 * // returns [ 'foo', 'bar' ]
    399 */
    400 setReadOnly( FIFO.prototype, 'toArray', function toArray() {
    401 	var node;
    402 	var out;
    403 	var i;
    404 
    405 	out = [];
    406 	node = this._first;
    407 	for ( i = 0; i < this._length; i++ ) {
    408 		out.push( node.value );
    409 		node = node.next;
    410 	}
    411 	return out;
    412 });
    413 
    414 /**
    415 * Serializes a queue as JSON.
    416 *
    417 * ## Notes
    418 *
    419 * -   `JSON.stringify()` implicitly calls this method when stringifying a `FIFO` instance.
    420 *
    421 * @name toJSON
    422 * @memberof FIFO.prototype
    423 * @type {Function}
    424 * @returns {Object} serialized queue
    425 *
    426 * @example
    427 * var queue = new FIFO();
    428 *
    429 * // Add values to the queue:
    430 * queue.push( 'foo' ).push( 'bar' );
    431 *
    432 * // Serialize to JSON:
    433 * var o = queue.toJSON();
    434 * // returns { 'type': 'fifo', 'data': [ 'foo', 'bar' ] }
    435 */
    436 setReadOnly( FIFO.prototype, 'toJSON', function toJSON() {
    437 	var out = {};
    438 	out.type = 'fifo';
    439 	out.data = this.toArray();
    440 	return out;
    441 });
    442 
    443 
    444 // EXPORTS //
    445 
    446 module.exports = FIFO;