@@ -60,6 +60,35 @@ const STRINGS = {
60
60
}
61
61
} ;
62
62
63
+ // Pre-computed lookup tables for performance optimization
64
+ const BINARY_POWERS = [
65
+ 1 , // 2^0
66
+ 1024 , // 2^10
67
+ 1048576 , // 2^20
68
+ 1073741824 , // 2^30
69
+ 1099511627776 , // 2^40
70
+ 1125899906842624 , // 2^50
71
+ 1152921504606846976 , // 2^60
72
+ 1180591620717411303424 , // 2^70
73
+ 1208925819614629174706176 // 2^80
74
+ ] ;
75
+
76
+ const DECIMAL_POWERS = [
77
+ 1 , // 10^0
78
+ 1000 , // 10^3
79
+ 1000000 , // 10^6
80
+ 1000000000 , // 10^9
81
+ 1000000000000 , // 10^12
82
+ 1000000000000000 , // 10^15
83
+ 1000000000000000000 , // 10^18
84
+ 1000000000000000000000 , // 10^21
85
+ 1000000000000000000000000 // 10^24
86
+ ] ;
87
+
88
+ // Pre-computed log values for faster exponent calculation
89
+ const LOG_2_1024 = Math . log ( 1024 ) ;
90
+ const LOG_10_1000 = Math . log ( 1000 ) ;
91
+
63
92
/**
64
93
* Converts a file size in bytes to a human-readable string with appropriate units
65
94
* @param {number|string|bigint } arg - The file size in bytes to convert
@@ -111,21 +140,31 @@ function filesize (arg, {
111
140
val = 0 ,
112
141
u = EMPTY ;
113
142
114
- // Sync base & standard
143
+ // Optimized base & standard synchronization with early returns
144
+ let isDecimal , ceil , actualStandard ;
115
145
if ( standard === SI ) {
116
- base = 10 ;
117
- standard = JEDEC ;
118
- } else if ( standard === IEC || standard === JEDEC ) {
119
- base = 2 ;
146
+ isDecimal = true ;
147
+ ceil = 1000 ;
148
+ actualStandard = JEDEC ;
149
+ } else if ( standard === IEC ) {
150
+ isDecimal = false ;
151
+ ceil = 1024 ;
152
+ actualStandard = IEC ;
153
+ } else if ( standard === JEDEC ) {
154
+ isDecimal = false ; // JEDEC uses binary (1024) by default
155
+ ceil = 1024 ;
156
+ actualStandard = JEDEC ;
120
157
} else if ( base === 2 ) {
121
- standard = IEC ;
158
+ isDecimal = false ;
159
+ ceil = 1024 ;
160
+ actualStandard = IEC ;
122
161
} else {
123
- base = 10 ;
124
- standard = JEDEC ;
162
+ isDecimal = true ;
163
+ ceil = 1000 ;
164
+ actualStandard = JEDEC ;
125
165
}
126
166
127
- const ceil = base === 10 ? 1000 : 1024 ,
128
- full = fullform === true ,
167
+ const full = fullform === true ,
129
168
neg = num < 0 ,
130
169
roundingFunc = Math [ roundingMethod ] ;
131
170
@@ -142,9 +181,39 @@ function filesize (arg, {
142
181
num = - num ;
143
182
}
144
183
145
- // Determining the exponent
184
+ // Fast path for zero
185
+ if ( num === 0 ) {
186
+ result [ 0 ] = precision > 0 ? ( 0 ) . toPrecision ( precision ) : 0 ;
187
+ u = result [ 1 ] = STRINGS . symbol [ actualStandard ] [ bits ? BITS : BYTES ] [ 0 ] ;
188
+
189
+ if ( output === EXPONENT ) {
190
+ return 0 ;
191
+ }
192
+
193
+ // Skip most processing for zero case
194
+ if ( symbols [ result [ 1 ] ] ) {
195
+ result [ 1 ] = symbols [ result [ 1 ] ] ;
196
+ }
197
+
198
+ if ( full ) {
199
+ result [ 1 ] = fullforms [ 0 ] || STRINGS . fullform [ actualStandard ] [ 0 ] + ( bits ? BIT : BYTE ) ;
200
+ }
201
+
202
+ return output === ARRAY ? result : output === OBJECT ? {
203
+ value : result [ 0 ] ,
204
+ symbol : result [ 1 ] ,
205
+ exponent : 0 ,
206
+ unit : u
207
+ } : result . join ( spacer ) ;
208
+ }
209
+
210
+ // Optimized exponent calculation using pre-computed log values
146
211
if ( e === - 1 || isNaN ( e ) ) {
147
- e = Math . floor ( Math . log ( num ) / Math . log ( ceil ) ) ;
212
+ if ( isDecimal ) {
213
+ e = Math . floor ( Math . log ( num ) / LOG_10_1000 ) ;
214
+ } else {
215
+ e = Math . floor ( Math . log ( num ) / LOG_2_1024 ) ;
216
+ }
148
217
149
218
if ( e < 0 ) {
150
219
e = 0 ;
@@ -156,67 +225,73 @@ function filesize (arg, {
156
225
if ( precision > 0 ) {
157
226
precision += 8 - e ;
158
227
}
159
-
160
228
e = 8 ;
161
229
}
162
230
163
231
if ( output === EXPONENT ) {
164
232
return e ;
165
233
}
166
234
167
- // Zero is now a special case because bytes divide by 1
168
- if ( num === 0 ) {
169
- result [ 0 ] = 0 ;
170
-
171
- if ( precision > 0 ) {
172
- result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
173
- }
174
-
175
- u = result [ 1 ] = STRINGS . symbol [ standard ] [ bits ? BITS : BYTES ] [ e ] ;
235
+ // Use pre-computed lookup tables (e is always <= 8, arrays have 9 elements)
236
+ let d ;
237
+ if ( isDecimal ) {
238
+ d = DECIMAL_POWERS [ e ] ;
176
239
} else {
177
- let d = base === 2 ? Math . pow ( 2 , e * 10 ) : Math . pow ( 1000 , e ) ;
178
- val = num / d ;
240
+ d = BINARY_POWERS [ e ] ;
241
+ }
242
+
243
+ val = num / d ;
179
244
180
- if ( bits ) {
181
- val = val * 8 ;
245
+ if ( bits ) {
246
+ val = val * 8 ;
182
247
183
- if ( val >= ceil && e < 8 ) {
184
- val = val / ceil ;
185
- e ++ ;
186
- }
248
+ if ( val >= ceil && e < 8 ) {
249
+ val = val / ceil ;
250
+ e ++ ;
187
251
}
252
+ }
188
253
189
- let p = Math . pow ( 10 , e > 0 ? round : 0 ) ;
190
- result [ 0 ] = roundingFunc ( val * p ) / p ;
254
+ // Optimize rounding calculation
255
+ const p = e > 0 && round > 0 ? Math . pow ( 10 , round ) : 1 ;
256
+ result [ 0 ] = p === 1 ? roundingFunc ( val ) : roundingFunc ( val * p ) / p ;
191
257
192
- if ( result [ 0 ] === ceil && e < 8 && exponent === - 1 ) {
193
- result [ 0 ] = 1 ;
194
- e ++ ;
195
- }
258
+ if ( result [ 0 ] === ceil && e < 8 && exponent === - 1 ) {
259
+ result [ 0 ] = 1 ;
260
+ e ++ ;
261
+ }
196
262
197
- // Setting optional precision
198
- if ( precision > 0 ) {
199
- result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
263
+ // Setting optional precision
264
+ if ( precision > 0 ) {
265
+ result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
200
266
201
- if ( result [ 0 ] . includes ( E ) && e < 8 ) {
202
- e ++ ;
203
- d = base === 2 ? Math . pow ( 2 , e * 10 ) : Math . pow ( 1000 , e ) ;
204
- val = num / d ;
205
- result [ 0 ] = ( roundingFunc ( val * p ) / p ) . toPrecision ( precision ) ;
267
+ if ( result [ 0 ] . includes ( E ) && e < 8 ) {
268
+ e ++ ;
269
+ // Recalculate with new exponent (e is always <= 8)
270
+ if ( isDecimal ) {
271
+ d = DECIMAL_POWERS [ e ] ;
272
+ } else {
273
+ d = BINARY_POWERS [ e ] ;
206
274
}
275
+ val = num / d ;
276
+ result [ 0 ] = ( p === 1 ? roundingFunc ( val ) : roundingFunc ( val * p ) / p ) . toPrecision ( precision ) ;
207
277
}
208
-
209
- u = result [ 1 ] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS . symbol [ standard ] [ bits ? BITS : BYTES ] [ e ] ;
210
278
}
211
279
280
+ // Cache symbol lookup
281
+ const symbolTable = STRINGS . symbol [ actualStandard ] [ bits ? BITS : BYTES ] ;
282
+ u = result [ 1 ] = ( isDecimal && e === 1 ) ? ( bits ? SI_KBIT : SI_KBYTE ) : symbolTable [ e ] ;
283
+
212
284
// Decorating a 'diff'
213
285
if ( neg ) {
214
286
result [ 0 ] = - result [ 0 ] ;
215
287
}
216
288
217
289
// Applying custom symbol
218
- result [ 1 ] = symbols [ result [ 1 ] ] || result [ 1 ] ;
290
+ if ( symbols [ result [ 1 ] ] ) {
291
+ result [ 1 ] = symbols [ result [ 1 ] ] ;
292
+ }
219
293
294
+ // Optimized locale/separator handling
220
295
if ( locale === true ) {
221
296
result [ 0 ] = result [ 0 ] . toLocaleString ( ) ;
222
297
} else if ( locale . length > 0 ) {
@@ -226,9 +301,9 @@ function filesize (arg, {
226
301
}
227
302
228
303
if ( pad && round > 0 ) {
229
- const i = result [ 0 ] . toString ( ) ,
230
- x = separator || ( ( i . match ( / ( \D ) / g) || [ ] ) . pop ( ) || PERIOD ) ,
231
- tmp = i . toString ( ) . split ( x ) ,
304
+ const resultStr = result [ 0 ] . toString ( ) ,
305
+ x = separator || ( ( resultStr . match ( / ( \D ) / g) || [ ] ) . pop ( ) || PERIOD ) ,
306
+ tmp = resultStr . split ( x ) ,
232
307
s = tmp [ 1 ] || EMPTY ,
233
308
l = s . length ,
234
309
n = round - l ;
@@ -237,16 +312,24 @@ function filesize (arg, {
237
312
}
238
313
239
314
if ( full ) {
240
- result [ 1 ] = fullforms [ e ] ? fullforms [ e ] : STRINGS . fullform [ standard ] [ e ] + ( bits ? BIT : BYTE ) + ( result [ 0 ] === 1 ? EMPTY : S ) ;
315
+ result [ 1 ] = fullforms [ e ] || STRINGS . fullform [ actualStandard ] [ e ] + ( bits ? BIT : BYTE ) + ( result [ 0 ] === 1 ? EMPTY : S ) ;
241
316
}
242
317
243
- // Returning Array, Object, or String (default)
244
- return output === ARRAY ? result : output === OBJECT ? {
245
- value : result [ 0 ] ,
246
- symbol : result [ 1 ] ,
247
- exponent : e ,
248
- unit : u
249
- } : result . join ( spacer ) ;
318
+ // Optimized return logic
319
+ if ( output === ARRAY ) {
320
+ return result ;
321
+ }
322
+
323
+ if ( output === OBJECT ) {
324
+ return {
325
+ value : result [ 0 ] ,
326
+ symbol : result [ 1 ] ,
327
+ exponent : e ,
328
+ unit : u
329
+ } ;
330
+ }
331
+
332
+ return spacer === SPACE ? `${ result [ 0 ] } ${ result [ 1 ] } ` : result . join ( spacer ) ;
250
333
}
251
334
252
335
/**
0 commit comments