3 * Copyright(c) 2012-2014 TJ Holowaychuk
4 * Copyright(c) 2015 Jed Watson
15 module.exports = bytes;
16 module.exports.format = format;
17 module.exports.parse = parse;
24 var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
26 var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
33 tb: Math.pow(1024, 4),
34 pb: Math.pow(1024, 5),
37 var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;
40 * Convert the given value in bytes into a string or parse to string to an integer in bytes.
42 * @param {string|number} value
45 * decimalPlaces: [number]
46 * fixedDecimals: [boolean]
47 * thousandsSeparator: [string]
48 * unitSeparator: [string]
49 * }} [options] bytes options.
51 * @returns {string|number|null}
54 function bytes(value, options) {
55 if (typeof value === 'string') {
59 if (typeof value === 'number') {
60 return format(value, options);
67 * Format the given value in bytes into a string.
69 * If the value is negative, it is kept as such. If it is a float,
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=]
80 * @returns {string|null}
84 function format(value, options) {
85 if (!Number.isFinite(value)) {
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) || '';
96 if (!unit || !map[unit.toLowerCase()]) {
99 } else if (mag >= map.tb) {
101 } else if (mag >= map.gb) {
103 } else if (mag >= map.mb) {
105 } else if (mag >= map.kb) {
112 var val = value / map[unit.toLowerCase()];
113 var str = val.toFixed(decimalPlaces);
115 if (!fixedDecimals) {
116 str = str.replace(formatDecimalsRegExp, '$1');
119 if (thousandsSeparator) {
120 str = str.replace(formatThousandsRegExp, thousandsSeparator);
123 return str + unitSeparator + unit;
127 * Parse the string value into an integer in bytes.
129 * If no unit is given, it is assumed the value is in bytes.
131 * @param {number|string} val
133 * @returns {number|null}
137 function parse(val) {
138 if (typeof val === 'number' && !isNaN(val)) {
142 if (typeof val !== 'string') {
146 // Test if the string passed is valid
147 var results = parseRegExp.exec(val);
152 // Nothing could be extracted from the given string
153 floatValue = parseInt(val, 10);
156 // Retrieve the value and the unit
157 floatValue = parseFloat(results[1]);
158 unit = results[4].toLowerCase();
161 return Math.floor(map[unit] * floatValue);