|
1 | 1 | import { |
2 | 2 | ARRAY, |
3 | | - BINARY_POWERS, |
4 | 3 | BIT, |
5 | 4 | BITS, |
6 | 5 | BYTE, |
7 | 6 | BYTES, |
8 | | - DECIMAL_POWERS, |
9 | | - E, |
10 | 7 | EMPTY, |
11 | 8 | EXPONENT, |
12 | 9 | FUNCTION, |
13 | | - IEC, |
14 | 10 | INVALID_NUMBER, |
15 | 11 | INVALID_ROUND, |
16 | | - JEDEC, |
17 | | - LOG_2_1024, |
18 | 12 | LOG_10_1000, |
| 13 | + LOG_2_1024, |
19 | 14 | OBJECT, |
20 | | - PERIOD, |
21 | 15 | ROUND, |
22 | 16 | S, |
23 | | - SI, |
24 | 17 | SI_KBIT, |
25 | 18 | SI_KBYTE, |
26 | 19 | SPACE, |
27 | 20 | STRING, |
28 | 21 | STRINGS, |
29 | | - ZERO |
30 | 22 | } from "./constants.js"; |
31 | | - |
32 | | -// Cached configuration lookup for better performance |
33 | | -const STANDARD_CONFIGS = { |
34 | | - [SI]: { isDecimal: true, ceil: 1000, actualStandard: JEDEC }, |
35 | | - [IEC]: { isDecimal: false, ceil: 1024, actualStandard: IEC }, |
36 | | - [JEDEC]: { isDecimal: false, ceil: 1024, actualStandard: JEDEC } |
37 | | -}; |
| 23 | +import { |
| 24 | + applyNumberFormatting, |
| 25 | + applyPrecisionHandling, |
| 26 | + calculateOptimizedValue, |
| 27 | + getBaseConfiguration, |
| 28 | + handleZeroValue |
| 29 | +} from "./helpers.js"; |
38 | 30 |
|
39 | 31 | /** |
40 | 32 | * Converts a file size in bytes to a human-readable string with appropriate units |
@@ -88,8 +80,7 @@ export function filesize (arg, { |
88 | 80 | u = EMPTY; |
89 | 81 |
|
90 | 82 | // Optimized base & standard configuration lookup |
91 | | - const config = getBaseConfiguration(standard, base); |
92 | | - const { isDecimal, ceil, actualStandard } = config; |
| 83 | + const {isDecimal, ceil, actualStandard} = getBaseConfiguration(standard, base); |
93 | 84 |
|
94 | 85 | const full = fullform === true, |
95 | 86 | neg = num < 0, |
@@ -134,9 +125,9 @@ export function filesize (arg, { |
134 | 125 | } |
135 | 126 |
|
136 | 127 | // Calculate value with optimized lookup and bits handling |
137 | | - const valueResult = calculateOptimizedValue(num, e, isDecimal, bits, ceil); |
138 | | - val = valueResult.val; |
139 | | - e = valueResult.e; |
| 128 | + const {result: valueResult, e: valueExponent} = calculateOptimizedValue(num, e, isDecimal, bits, ceil); |
| 129 | + val = valueResult; |
| 130 | + e = valueExponent; |
140 | 131 |
|
141 | 132 | // Optimize rounding calculation |
142 | 133 | const p = e > 0 && round > 0 ? Math.pow(10, round) : 1; |
@@ -192,156 +183,6 @@ export function filesize (arg, { |
192 | 183 | return spacer === SPACE ? `${result[0]} ${result[1]}` : result.join(spacer); |
193 | 184 | } |
194 | 185 |
|
195 | | -/** |
196 | | - * Optimized base configuration lookup |
197 | | - * @param {string} standard - Standard type |
198 | | - * @param {number} base - Base number |
199 | | - * @returns {Object} Configuration object |
200 | | - */ |
201 | | -export function getBaseConfiguration(standard, base) { |
202 | | - // Use cached lookup table for better performance |
203 | | - if (STANDARD_CONFIGS[standard]) { |
204 | | - return STANDARD_CONFIGS[standard]; |
205 | | - } |
206 | | - |
207 | | - // Base override |
208 | | - if (base === 2) { |
209 | | - return { isDecimal: false, ceil: 1024, actualStandard: IEC }; |
210 | | - } |
211 | | - |
212 | | - // Default |
213 | | - return { isDecimal: true, ceil: 1000, actualStandard: JEDEC }; |
214 | | -} |
215 | | - |
216 | | -/** |
217 | | - * Optimized zero value handling |
218 | | - * @param {number} precision - Precision value |
219 | | - * @param {string} actualStandard - Standard to use |
220 | | - * @param {boolean} bits - Whether to use bits |
221 | | - * @param {Object} symbols - Custom symbols |
222 | | - * @param {boolean} full - Whether to use full form |
223 | | - * @param {Array} fullforms - Custom full forms |
224 | | - * @param {string} output - Output format |
225 | | - * @param {string} spacer - Spacer character |
226 | | - * @returns {string|Array|Object|number} Formatted result |
227 | | - */ |
228 | | -export function handleZeroValue(precision, actualStandard, bits, symbols, full, fullforms, output, spacer) { |
229 | | - const result = []; |
230 | | - result[0] = precision > 0 ? (0).toPrecision(precision) : 0; |
231 | | - const u = result[1] = STRINGS.symbol[actualStandard][bits ? BITS : BYTES][0]; |
232 | | - |
233 | | - if (output === EXPONENT) { |
234 | | - return 0; |
235 | | - } |
236 | | - |
237 | | - // Apply symbol customization |
238 | | - if (symbols[result[1]]) { |
239 | | - result[1] = symbols[result[1]]; |
240 | | - } |
241 | | - |
242 | | - // Apply full form |
243 | | - if (full) { |
244 | | - result[1] = fullforms[0] || STRINGS.fullform[actualStandard][0] + (bits ? BIT : BYTE); |
245 | | - } |
246 | | - |
247 | | - // Return in requested format |
248 | | - return output === ARRAY ? result : output === OBJECT ? { |
249 | | - value: result[0], |
250 | | - symbol: result[1], |
251 | | - exponent: 0, |
252 | | - unit: u |
253 | | - } : result.join(spacer); |
254 | | -} |
255 | | - |
256 | | -/** |
257 | | - * Optimized value calculation with bits handling |
258 | | - * @param {number} num - Input number |
259 | | - * @param {number} e - Exponent |
260 | | - * @param {boolean} isDecimal - Whether to use decimal powers |
261 | | - * @param {boolean} bits - Whether to calculate bits |
262 | | - * @param {number} ceil - Ceiling value for auto-increment |
263 | | - * @returns {Object} Object with val and e properties |
264 | | - */ |
265 | | -export function calculateOptimizedValue(num, e, isDecimal, bits, ceil) { |
266 | | - const d = isDecimal ? DECIMAL_POWERS[e] : BINARY_POWERS[e]; |
267 | | - let val = num / d; |
268 | | - |
269 | | - if (bits) { |
270 | | - val *= 8; |
271 | | - // Handle auto-increment for bits |
272 | | - if (val >= ceil && e < 8) { |
273 | | - val /= ceil; |
274 | | - e++; |
275 | | - } |
276 | | - } |
277 | | - |
278 | | - return { val, e }; |
279 | | -} |
280 | | - |
281 | | -/** |
282 | | - * Optimized precision handling with scientific notation correction |
283 | | - * @param {number} value - Current value |
284 | | - * @param {number} precision - Precision to apply |
285 | | - * @param {number} e - Current exponent |
286 | | - * @param {number} num - Original number |
287 | | - * @param {boolean} isDecimal - Whether using decimal base |
288 | | - * @param {boolean} bits - Whether calculating bits |
289 | | - * @param {number} ceil - Ceiling value |
290 | | - * @param {Function} roundingFunc - Rounding function |
291 | | - * @param {number} round - Round value |
292 | | - * @returns {Object} Object with value and e properties |
293 | | - */ |
294 | | -export function applyPrecisionHandling(value, precision, e, num, isDecimal, bits, ceil, roundingFunc, round) { |
295 | | - let result = value.toPrecision(precision); |
296 | | - |
297 | | - // Handle scientific notation by recalculating with incremented exponent |
298 | | - if (result.includes(E) && e < 8) { |
299 | | - e++; |
300 | | - const valueResult = calculateOptimizedValue(num, e, isDecimal, bits, ceil); |
301 | | - const p = round > 0 ? Math.pow(10, round) : 1; |
302 | | - result = (p === 1 ? roundingFunc(valueResult.val) : roundingFunc(valueResult.val * p) / p).toPrecision(precision); |
303 | | - } |
304 | | - |
305 | | - return { value: result, e }; |
306 | | -} |
307 | | - |
308 | | -/** |
309 | | - * Optimized number formatting with locale, separator, and padding |
310 | | - * @param {number|string} value - Value to format |
311 | | - * @param {string|boolean} locale - Locale setting |
312 | | - * @param {Object} localeOptions - Locale options |
313 | | - * @param {string} separator - Custom separator |
314 | | - * @param {boolean} pad - Whether to pad |
315 | | - * @param {number} round - Round value |
316 | | - * @returns {string|number} Formatted value |
317 | | - */ |
318 | | -export function applyNumberFormatting(value, locale, localeOptions, separator, pad, round) { |
319 | | - let result = value; |
320 | | - |
321 | | - // Apply locale formatting |
322 | | - if (locale === true) { |
323 | | - result = result.toLocaleString(); |
324 | | - } else if (locale.length > 0) { |
325 | | - result = result.toLocaleString(locale, localeOptions); |
326 | | - } else if (separator.length > 0) { |
327 | | - result = result.toString().replace(PERIOD, separator); |
328 | | - } |
329 | | - |
330 | | - // Apply padding |
331 | | - if (pad && round > 0) { |
332 | | - const resultStr = result.toString(); |
333 | | - const x = separator || ((resultStr.match(/(\D)/g) || []).pop() || PERIOD); |
334 | | - const tmp = resultStr.split(x); |
335 | | - const s = tmp[1] || EMPTY; |
336 | | - const l = s.length; |
337 | | - const n = round - l; |
338 | | - |
339 | | - result = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`; |
340 | | - } |
341 | | - |
342 | | - return result; |
343 | | -} |
344 | | - |
345 | 186 | /** |
346 | 187 | * Creates a partially applied version of filesize with preset options |
347 | 188 | * @param {Object} [options={}] - Default options to apply to the returned function |
|
0 commit comments