index.js (3469B)
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.replace(formatThousandsRegExp, thousandsSeparator); 121 } 122 123 return str + unitSeparator + unit; 124 } 125 126 /** 127 * Parse the string value into an integer in bytes. 128 * 129 * If no unit is given, it is assumed the value is in bytes. 130 * 131 * @param {number|string} val 132 * 133 * @returns {number|null} 134 * @public 135 */ 136 137 function parse(val) { 138 if (typeof val === 'number' && !isNaN(val)) { 139 return val; 140 } 141 142 if (typeof val !== 'string') { 143 return null; 144 } 145 146 // Test if the string passed is valid 147 var results = parseRegExp.exec(val); 148 var floatValue; 149 var unit = 'b'; 150 151 if (!results) { 152 // Nothing could be extracted from the given string 153 floatValue = parseInt(val, 10); 154 unit = 'b' 155 } else { 156 // Retrieve the value and the unit 157 floatValue = parseFloat(results[1]); 158 unit = results[4].toLowerCase(); 159 } 160 161 return Math.floor(map[unit] * floatValue); 162 }