time-to-botec

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

main.js (8327B)


      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 
     29 
     30 // MAIN //
     31 
     32 /**
     33 * Stack constructor.
     34 *
     35 * @constructor
     36 * @returns {Stack} stack instance
     37 *
     38 * @example
     39 * var s = new Stack();
     40 *
     41 * // Add values to the stack:
     42 * s.push( 'foo' ).push( 'bar' );
     43 *
     44 * // Remove the top value:
     45 * var v = s.pop();
     46 * // returns 'bar'
     47 *
     48 * // Add a new value to the stack:
     49 * s.push( 'beep' );
     50 *
     51 * // Remove the top value:
     52 * v = s.pop();
     53 * // returns 'beep'
     54 */
     55 function Stack() {
     56 	if ( !(this instanceof Stack) ) {
     57 		return new Stack();
     58 	}
     59 	// Use a dynamic array as insertion and deletion is O(1) amortized:
     60 	this._buffer = [];
     61 	return this;
     62 }
     63 
     64 /**
     65 * Clears the stack.
     66 *
     67 * @name clear
     68 * @memberof Stack.prototype
     69 * @type {Function}
     70 * @returns {Stack} stack instance
     71 *
     72 * @example
     73 * var s = new Stack();
     74 *
     75 * // Add values to the stack:
     76 * s.push( 'foo' ).push( 'bar' );
     77 *
     78 * // Peek at the top value:
     79 * var v = s.first();
     80 * // returns 'bar'
     81 *
     82 * // Examine the stack length:
     83 * var len = s.length;
     84 * // returns 2
     85 *
     86 * // Clear all stack items:
     87 * s.clear();
     88 *
     89 * // Peek at the top value:
     90 * v = s.first();
     91 * // returns undefined
     92 *
     93 * // Examine the stack length:
     94 * len = s.length;
     95 * // returns 0
     96 */
     97 setReadOnly( Stack.prototype, 'clear', function clear() {
     98 	this._buffer.length = 0;
     99 	return this;
    100 });
    101 
    102 /**
    103 * Returns the top value (i.e., the value which is "first-out").
    104 *
    105 * @name first
    106 * @memberof Stack.prototype
    107 * @type {Function}
    108 * @returns {(*|void)} top value
    109 *
    110 * @example
    111 * var s = new Stack();
    112 *
    113 * // Add values to the stack:
    114 * s.push( 'foo' ).push( 'bar' );
    115 *
    116 * // Peek at the top value:
    117 * var v = s.first();
    118 * // returns 'bar'
    119 */
    120 setReadOnly( Stack.prototype, 'first', function first() {
    121 	if ( this._buffer.length ) {
    122 		return this._buffer[ this._buffer.length-1 ];
    123 	}
    124 });
    125 
    126 /**
    127 * Returns an iterator for iterating over a stack.
    128 *
    129 * ## Notes
    130 *
    131 * -   In order to prevent confusion arising from stack mutation during iteration, a returned iterator **always** iterates over a stack "snapshot", which is defined as the list of stack elements at the time of this method's invocation.
    132 *
    133 * @name iterator
    134 * @memberof Stack.prototype
    135 * @type {Function}
    136 * @returns {Iterator} iterator
    137 *
    138 * @example
    139 * var s = new Stack();
    140 *
    141 * // Add values to the stack:
    142 * s.push( 'foo' ).push( 'bar' );
    143 *
    144 * // Create an iterator:
    145 * var it = s.iterator();
    146 *
    147 * // Iterate over the stack...
    148 * var v = it.next().value;
    149 * // returns 'bar'
    150 *
    151 * v = it.next().value;
    152 * // returns 'foo'
    153 *
    154 * var bool = it.next().done;
    155 * // returns true
    156 */
    157 setReadOnly( Stack.prototype, 'iterator', function iterator() {
    158 	var values;
    159 	var iter;
    160 	var self;
    161 	var FLG;
    162 	var i;
    163 
    164 	self = this;
    165 
    166 	// Initialize the iteration index:
    167 	i = this._buffer.length;
    168 
    169 	// Create a copy of stack values (necessary in order to "snapshot" the stack; otherwise, values could come and go between calls to `next`):
    170 	values = this._buffer.slice();
    171 
    172 	// Create an iterator protocol-compliant object:
    173 	iter = {};
    174 	setReadOnly( iter, 'next', next );
    175 	setReadOnly( iter, 'return', end );
    176 	if ( iteratorSymbol ) {
    177 		setReadOnly( iter, iteratorSymbol, factory );
    178 	}
    179 	return iter;
    180 
    181 	/**
    182 	* Returns an iterator protocol-compliant object containing the next iterated value.
    183 	*
    184 	* @private
    185 	* @returns {Object} iterator protocol-compliant object
    186 	*/
    187 	function next() {
    188 		i -= 1;
    189 		if ( FLG || i < 0 ) {
    190 			return {
    191 				'done': true
    192 			};
    193 		}
    194 		return {
    195 			'value': values[ i ],
    196 			'done': false
    197 		};
    198 	}
    199 
    200 	/**
    201 	* Finishes an iterator.
    202 	*
    203 	* @private
    204 	* @param {*} [value] - value to return
    205 	* @returns {Object} iterator protocol-compliant object
    206 	*/
    207 	function end( value ) {
    208 		FLG = true;
    209 		if ( arguments.length ) {
    210 			return {
    211 				'value': value,
    212 				'done': true
    213 			};
    214 		}
    215 		return {
    216 			'done': true
    217 		};
    218 	}
    219 
    220 	/**
    221 	* Returns a new iterator.
    222 	*
    223 	* @private
    224 	* @returns {Iterator} iterator
    225 	*/
    226 	function factory() {
    227 		return self.iterator();
    228 	}
    229 });
    230 
    231 /**
    232 * Returns the bottom stack value (i.e., the value which is currently "last-out").
    233 *
    234 * @name last
    235 * @memberof Stack.prototype
    236 * @type {Function}
    237 * @returns {(*|void)} bottom stack value
    238 *
    239 * @example
    240 * var s = new Stack();
    241 *
    242 * // Add values to the stack:
    243 * s.push( 'foo' ).push( 'bar' );
    244 *
    245 * // Peek at the bottom value:
    246 * var v = s.last();
    247 * // returns 'foo'
    248 */
    249 setReadOnly( Stack.prototype, 'last', function last() {
    250 	if ( this._buffer.length ) {
    251 		return this._buffer[ 0 ];
    252 	}
    253 });
    254 
    255 /**
    256 * Stack length.
    257 *
    258 * @name length
    259 * @memberof Stack.prototype
    260 * @type {NonNegativeInteger}
    261 *
    262 * @example
    263 * var s = new Stack();
    264 *
    265 * // Examine the initial stack length:
    266 * var len = s.length;
    267 * // returns 0
    268 *
    269 * // Add values to the stack:
    270 * s.push( 'foo' ).push( 'bar' );
    271 *
    272 * // Retrieve the current stack length:
    273 * len = s.length;
    274 * // returns 2
    275 */
    276 setReadOnlyAccessor( Stack.prototype, 'length', function get() {
    277 	return this._buffer.length;
    278 });
    279 
    280 /**
    281 * Removes a value from the stack.
    282 *
    283 * @name pop
    284 * @memberof Stack.prototype
    285 * @type {Function}
    286 * @returns {(*|void)} removed value
    287 *
    288 * @example
    289 * var s = new Stack();
    290 *
    291 * // Add values to the stack:
    292 * s.push( 'foo' ).push( 'bar' );
    293 *
    294 * // Remove the top value:
    295 * var v = s.pop();
    296 * // returns 'bar'
    297 *
    298 * // Add a new value to the stack:
    299 * s.push( 'beep' );
    300 *
    301 * // Remove the top value:
    302 * v = s.pop();
    303 * // returns 'beep'
    304 */
    305 setReadOnly( Stack.prototype, 'pop', function pop() {
    306 	if ( this._buffer.length ) {
    307 		return this._buffer.pop();
    308 	}
    309 });
    310 
    311 /**
    312 * Adds a value to the stack.
    313 *
    314 * @name push
    315 * @memberof Stack.prototype
    316 * @type {Function}
    317 * @returns {Stack} stack instance
    318 *
    319 * @example
    320 * var s = new Stack();
    321 *
    322 * // Add values to the stack:
    323 * s.push( 'foo' ).push( 'bar' );
    324 *
    325 * // Remove the top value:
    326 * var v = s.pop();
    327 * // returns 'bar'
    328 *
    329 * // Add a new value to the stack:
    330 * s.push( 'beep' );
    331 *
    332 * // Remove the top value:
    333 * v = s.pop();
    334 * // returns 'beep'
    335 */
    336 setReadOnly( Stack.prototype, 'push', function push( value ) {
    337 	this._buffer.push( value );
    338 	return this;
    339 });
    340 
    341 /**
    342 * Returns an array of stack values.
    343 *
    344 * ## Notes
    345 *
    346 * -   Why reverse insertion order? Pros and cons to either order, but reverse insertion order mirrors iterator order. For example, we can use the ES6/ES2015+ spread operator along with the iterator to return stack values.
    347 *
    348 *     ```text
    349 *     arr = [...s.iterator()]
    350 *     ```
    351 *
    352 *     One might (as is the opinion here) consider parity of array serialization and iterator order to be a reasonable design goal.
    353 *
    354 * @name toArray
    355 * @memberof Stack.prototype
    356 * @type {Function}
    357 * @returns {Array} stack values
    358 *
    359 * @example
    360 * var s = new Stack();
    361 *
    362 * // Add values to the stack:
    363 * s.push( 'foo' ).push( 'bar' );
    364 *
    365 * // Get an array of stack values:
    366 * var vals = s.toArray();
    367 * // returns [ 'bar', 'foo' ]
    368 */
    369 setReadOnly( Stack.prototype, 'toArray', function toArray() {
    370 	var out;
    371 	var i;
    372 	out = [];
    373 	for ( i = this._buffer.length-1; i >= 0; i-- ) {
    374 		out.push( this._buffer[ i ] );
    375 	}
    376 	return out;
    377 });
    378 
    379 /**
    380 * Serializes a stack as JSON.
    381 *
    382 * ## Notes
    383 *
    384 * -   `JSON.stringify()` implicitly calls this method when stringifying a `Stack` instance.
    385 *
    386 * @name toJSON
    387 * @memberof Stack.prototype
    388 * @type {Function}
    389 * @returns {Object} serialized stack
    390 *
    391 * @example
    392 * var s = new Stack();
    393 *
    394 * // Add values to the stack:
    395 * s.push( 'foo' ).push( 'bar' );
    396 *
    397 * // Serialize to JSON:
    398 * var o = s.toJSON();
    399 * // returns { 'type': 'stack', 'data': [ 'bar', 'foo' ] }
    400 */
    401 setReadOnly( Stack.prototype, 'toJSON', function toJSON() {
    402 	var out = {};
    403 	out.type = 'stack';
    404 	out.data = this.toArray();
    405 	return out;
    406 });
    407 
    408 
    409 // EXPORTS //
    410 
    411 module.exports = Stack;