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