/ node_modules / bytes / index.js
index.js
  1  /*!
  2   * bytes
  3   * Copyright(c) 2012-2014 TJ Holowaychuk
  4   * Copyright(c) 2015 Jed Watson
  5   * MIT Licensed
  6   */
  7  
  8  'use strict';
  9  
 10  /**
 11   * Module exports.
 12   * @public
 13   */
 14  
 15  module.exports = bytes;
 16  module.exports.format = format;
 17  module.exports.parse = parse;
 18  
 19  /**
 20   * Module variables.
 21   * @private
 22   */
 23  
 24  var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
 25  
 26  var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
 27  
 28  var map = {
 29    b:  1,
 30    kb: 1 << 10,
 31    mb: 1 << 20,
 32    gb: 1 << 30,
 33    tb: Math.pow(1024, 4),
 34    pb: Math.pow(1024, 5),
 35  };
 36  
 37  var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
 38  
 39  /**
 40   * Convert the given value in bytes into a string or parse to string to an integer in bytes.
 41   *
 42   * @param {string|number} value
 43   * @param {{
 44   *  case: [string],
 45   *  decimalPlaces: [number]
 46   *  fixedDecimals: [boolean]
 47   *  thousandsSeparator: [string]
 48   *  unitSeparator: [string]
 49   *  }} [options] bytes options.
 50   *
 51   * @returns {string|number|null}
 52   */
 53  
 54  function bytes(value, options) {
 55    if (typeof value === 'string') {
 56      return parse(value);
 57    }
 58  
 59    if (typeof value === 'number') {
 60      return format(value, options);
 61    }
 62  
 63    return null;
 64  }
 65  
 66  /**
 67   * Format the given value in bytes into a string.
 68   *
 69   * If the value is negative, it is kept as such. If it is a float,
 70   * it is rounded.
 71   *
 72   * @param {number} value
 73   * @param {object} [options]
 74   * @param {number} [options.decimalPlaces=2]
 75   * @param {number} [options.fixedDecimals=false]
 76   * @param {string} [options.thousandsSeparator=]
 77   * @param {string} [options.unit=]
 78   * @param {string} [options.unitSeparator=]
 79   *
 80   * @returns {string|null}
 81   * @public
 82   */
 83  
 84  function format(value, options) {
 85    if (!Number.isFinite(value)) {
 86      return null;
 87    }
 88  
 89    var mag = Math.abs(value);
 90    var thousandsSeparator = (options && options.thousandsSeparator) || '';
 91    var unitSeparator = (options && options.unitSeparator) || '';
 92    var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
 93    var fixedDecimals = Boolean(options && options.fixedDecimals);
 94    var unit = (options && options.unit) || '';
 95  
 96    if (!unit || !map[unit.toLowerCase()]) {
 97      if (mag >= map.pb) {
 98        unit = 'PB';
 99      } else if (mag >= map.tb) {
100        unit = 'TB';
101      } else if (mag >= map.gb) {
102        unit = 'GB';
103      } else if (mag >= map.mb) {
104        unit = 'MB';
105      } else if (mag >= map.kb) {
106        unit = 'KB';
107      } else {
108        unit = 'B';
109      }
110    }
111  
112    var val = value / map[unit.toLowerCase()];
113    var str = val.toFixed(decimalPlaces);
114  
115    if (!fixedDecimals) {
116      str = str.replace(formatDecimalsRegExp, '$1');
117    }
118  
119    if (thousandsSeparator) {
120      str = str.split('.').map(function (s, i) {
121        return i === 0
122          ? s.replace(formatThousandsRegExp, thousandsSeparator)
123          : s
124      }).join('.');
125    }
126  
127    return str + unitSeparator + unit;
128  }
129  
130  /**
131   * Parse the string value into an integer in bytes.
132   *
133   * If no unit is given, it is assumed the value is in bytes.
134   *
135   * @param {number|string} val
136   *
137   * @returns {number|null}
138   * @public
139   */
140  
141  function parse(val) {
142    if (typeof val === 'number' && !isNaN(val)) {
143      return val;
144    }
145  
146    if (typeof val !== 'string') {
147      return null;
148    }
149  
150    // Test if the string passed is valid
151    var results = parseRegExp.exec(val);
152    var floatValue;
153    var unit = 'b';
154  
155    if (!results) {
156      // Nothing could be extracted from the given string
157      floatValue = parseInt(val, 10);
158      unit = 'b'
159    } else {
160      // Retrieve the value and the unit
161      floatValue = parseFloat(results[1]);
162      unit = results[4].toLowerCase();
163    }
164  
165    if (isNaN(floatValue)) {
166      return null;
167    }
168  
169    return Math.floor(map[unit] * floatValue);
170  }