time-to-botec

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

main.js (3558B)


      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 'use strict';
     20 
     21 // MODULES //
     22 
     23 var isFunction = require( '@stdlib/assert/is-function' );
     24 var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
     25 var Buffer = require( '@stdlib/buffer/ctor' );
     26 var string2buffer = require( '@stdlib/buffer/from-string' );
     27 var stream = require( '@stdlib/streams/node/stdin' );
     28 var nextTick = require( '@stdlib/utils/next-tick' );
     29 
     30 
     31 // MAIN //
     32 
     33 /**
     34 * Reads data from `stdin`.
     35 *
     36 * @param {(string|null)} [encoding] - string encoding. If set, data will be returned as an encoded `string`.
     37 * @param {Function} clbk - callback to be invoked upon reading all data from `stdin`
     38 * @throws {TypeError} `encoding` argument must be a string
     39 * @throws {TypeError} callback argument must be a function
     40 * @returns {void}
     41 *
     42 * @example
     43 * function onRead( error, data ) {
     44 *     if ( error ) {
     45 *         throw error;
     46 *     }
     47 *     console.log( data.toString() );
     48 *     // => '...'
     49 * }
     50 *
     51 * stdin( onRead );
     52 *
     53 * @example
     54 * function onRead( error, data ) {
     55 *     if ( error ) {
     56 *         throw error;
     57 *     }
     58 *     console.log( data );
     59 *     // => '...'
     60 * }
     61 *
     62 * stdin( 'utf8', onRead );
     63 */
     64 function stdin() {
     65 	var clbk;
     66 	var data;
     67 	var enc;
     68 	var len;
     69 
     70 	if ( arguments.length === 1 ) {
     71 		clbk = arguments[ 0 ];
     72 	} else {
     73 		enc = arguments[ 0 ];
     74 		if ( !isString( enc ) ) {
     75 			throw new TypeError( 'invalid argument. Encoding argument must be a string. Value: `' + enc + '`.' );
     76 		}
     77 		clbk = arguments[ 1 ];
     78 	}
     79 	if ( !isFunction( clbk ) ) {
     80 		throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + clbk + '`.' );
     81 	}
     82 	if ( enc ) {
     83 		stream.setEncoding( enc );
     84 	}
     85 	// If the calling file is being run as a script and not as part of a pipeline, we should not expect to receive anything on `stdin`.
     86 	if ( stream.isTTY ) {
     87 		return nextTick( onTick );
     88 	}
     89 	data = [];
     90 	len = 0;
     91 
     92 	stream.on( 'readable', onReadable );
     93 	stream.on( 'error', onError );
     94 	stream.on( 'end', onEnd );
     95 
     96 	/**
     97 	* Callback invoked after the next tick.
     98 	*
     99 	* @private
    100 	* @returns {void}
    101 	*/
    102 	function onTick() {
    103 		if ( enc ) {
    104 			return clbk( null, '' );
    105 		}
    106 		clbk( null, string2buffer( '' ) );
    107 	}
    108 
    109 	/**
    110 	* Callback invoked once the stream has data to consume.
    111 	*
    112 	* @private
    113 	*/
    114 	function onReadable() {
    115 		var chunk;
    116 		while ( true ) {
    117 			chunk = stream.read();
    118 			if ( chunk === null ) {
    119 				break;
    120 			}
    121 			if ( typeof chunk === 'string' ) {
    122 				chunk = string2buffer( chunk );
    123 			}
    124 			data.push( chunk );
    125 			len += chunk.length;
    126 		}
    127 	}
    128 
    129 	/**
    130 	* Callback invoked upon encountering a stream error.
    131 	*
    132 	* @private
    133 	* @param {Error} error - error object
    134 	*/
    135 	function onError( error ) {
    136 		clbk( error );
    137 	}
    138 
    139 	/**
    140 	* Callback invoked after all data has been consumed.
    141 	*
    142 	* @private
    143 	* @returns {void}
    144 	*/
    145 	function onEnd() {
    146 		if ( enc ) {
    147 			// Return a string...
    148 			return clbk( null, data.join( '' ) );
    149 		}
    150 		// Return a buffer...
    151 		clbk( null, Buffer.concat( data, len ) );
    152 	}
    153 }
    154 
    155 
    156 // EXPORTS //
    157 
    158 module.exports = stdin;