second
[josuexyz/.git] / node_modules / bytes / 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: ((1 << 30) * 1024)
34 };
35
36 var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb)$/i;
37
38 /**
39  * Convert the given value in bytes into a string or parse to string to an integer in bytes.
40  *
41  * @param {string|number} value
42  * @param {{
43  *  case: [string],
44  *  decimalPlaces: [number]
45  *  fixedDecimals: [boolean]
46  *  thousandsSeparator: [string]
47  *  unitSeparator: [string]
48  *  }} [options] bytes options.
49  *
50  * @returns {string|number|null}
51  */
52
53 function bytes(value, options) {
54   if (typeof value === 'string') {
55     return parse(value);
56   }
57
58   if (typeof value === 'number') {
59     return format(value, options);
60   }
61
62   return null;
63 }
64
65 /**
66  * Format the given value in bytes into a string.
67  *
68  * If the value is negative, it is kept as such. If it is a float,
69  * it is rounded.
70  *
71  * @param {number} value
72  * @param {object} [options]
73  * @param {number} [options.decimalPlaces=2]
74  * @param {number} [options.fixedDecimals=false]
75  * @param {string} [options.thousandsSeparator=]
76  * @param {string} [options.unit=]
77  * @param {string} [options.unitSeparator=]
78  *
79  * @returns {string|null}
80  * @public
81  */
82
83 function format(value, options) {
84   if (!Number.isFinite(value)) {
85     return null;
86   }
87
88   var mag = Math.abs(value);
89   var thousandsSeparator = (options && options.thousandsSeparator) || '';
90   var unitSeparator = (options && options.unitSeparator) || '';
91   var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
92   var fixedDecimals = Boolean(options && options.fixedDecimals);
93   var unit = (options && options.unit) || '';
94
95   if (!unit || !map[unit.toLowerCase()]) {
96     if (mag >= map.tb) {
97       unit = 'TB';
98     } else if (mag >= map.gb) {
99       unit = 'GB';
100     } else if (mag >= map.mb) {
101       unit = 'MB';
102     } else if (mag >= map.kb) {
103       unit = 'KB';
104     } else {
105       unit = 'B';
106     }
107   }
108
109   var val = value / map[unit.toLowerCase()];
110   var str = val.toFixed(decimalPlaces);
111
112   if (!fixedDecimals) {
113     str = str.replace(formatDecimalsRegExp, '$1');
114   }
115
116   if (thousandsSeparator) {
117     str = str.replace(formatThousandsRegExp, thousandsSeparator);
118   }
119
120   return str + unitSeparator + unit;
121 }
122
123 /**
124  * Parse the string value into an integer in bytes.
125  *
126  * If no unit is given, it is assumed the value is in bytes.
127  *
128  * @param {number|string} val
129  *
130  * @returns {number|null}
131  * @public
132  */
133
134 function parse(val) {
135   if (typeof val === 'number' && !isNaN(val)) {
136     return val;
137   }
138
139   if (typeof val !== 'string') {
140     return null;
141   }
142
143   // Test if the string passed is valid
144   var results = parseRegExp.exec(val);
145   var floatValue;
146   var unit = 'b';
147
148   if (!results) {
149     // Nothing could be extracted from the given string
150     floatValue = parseInt(val, 10);
151     unit = 'b'
152   } else {
153     // Retrieve the value and the unit
154     floatValue = parseFloat(results[1]);
155     unit = results[4].toLowerCase();
156   }
157
158   return Math.floor(map[unit] * floatValue);
159 }