Line data Source code
1 : /* human.c -- print human readable file size
2 :
3 : Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 : 2005, 2006, 2007 Free Software Foundation, Inc.
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : /* Written by Paul Eggert and Larry McVoy. */
20 :
21 : #include <config.h>
22 :
23 : #include "human.h"
24 :
25 : #include <locale.h>
26 : #include <stdio.h>
27 : #include <stdlib.h>
28 : #include <string.h>
29 :
30 : #include <argmatch.h>
31 : #include <error.h>
32 : #include <intprops.h>
33 :
34 : /* The maximum length of a suffix like "KiB". */
35 : #define HUMAN_READABLE_SUFFIX_LENGTH_MAX 3
36 :
37 : static const char power_letter[] =
38 : {
39 : 0, /* not used */
40 : 'K', /* kibi ('k' for kilo is a special case) */
41 : 'M', /* mega or mebi */
42 : 'G', /* giga or gibi */
43 : 'T', /* tera or tebi */
44 : 'P', /* peta or pebi */
45 : 'E', /* exa or exbi */
46 : 'Z', /* zetta or 2**70 */
47 : 'Y' /* yotta or 2**80 */
48 : };
49 :
50 :
51 : /* If INEXACT_STYLE is not human_round_to_nearest, and if easily
52 : possible, adjust VALUE according to the style. */
53 :
54 : static long double
55 200 : adjust_value (int inexact_style, long double value)
56 : {
57 : /* Do not use the floorl or ceill functions, as that would mean
58 : checking for their presence and possibly linking with the
59 : standard math library, which is a porting pain. So leave the
60 : value alone if it is too large to easily round. */
61 200 : if (inexact_style != human_round_to_nearest && value < UINTMAX_MAX)
62 : {
63 180 : uintmax_t u = value;
64 180 : value = u + (inexact_style == human_ceiling && u != value);
65 : }
66 :
67 200 : return value;
68 : }
69 :
70 : /* Group the digits of NUMBER according to the grouping rules of the
71 : current locale. NUMBER contains NUMBERLEN digits. Modify the
72 : bytes pointed to by NUMBER in place, subtracting 1 from NUMBER for
73 : each byte inserted. Return the starting address of the modified
74 : number.
75 :
76 : To group the digits, use GROUPING and THOUSANDS_SEP as in `struct
77 : lconv' from <locale.h>. */
78 :
79 : static char *
80 75 : group_number (char *number, size_t numberlen,
81 : char const *grouping, char const *thousands_sep)
82 : {
83 : register char *d;
84 75 : size_t grouplen = SIZE_MAX;
85 75 : size_t thousands_seplen = strlen (thousands_sep);
86 75 : size_t i = numberlen;
87 :
88 : /* The maximum possible value for NUMBERLEN is the number of digits
89 : in the square of the largest uintmax_t, so double the size needed. */
90 : char buf[2 * INT_STRLEN_BOUND (uintmax_t) + 1];
91 :
92 75 : memcpy (buf, number, numberlen);
93 75 : d = number + numberlen;
94 :
95 : for (;;)
96 0 : {
97 75 : unsigned char g = *grouping;
98 :
99 75 : if (g)
100 : {
101 0 : grouplen = g < CHAR_MAX ? g : i;
102 0 : grouping++;
103 : }
104 :
105 75 : if (i < grouplen)
106 75 : grouplen = i;
107 :
108 75 : d -= grouplen;
109 75 : i -= grouplen;
110 75 : memcpy (d, buf + i, grouplen);
111 75 : if (i == 0)
112 150 : return d;
113 :
114 0 : d -= thousands_seplen;
115 0 : memcpy (d, thousands_sep, thousands_seplen);
116 : }
117 : }
118 :
119 : /* Convert N to a human readable format in BUF, using the options OPTS.
120 :
121 : N is expressed in units of FROM_BLOCK_SIZE. FROM_BLOCK_SIZE must
122 : be nonnegative.
123 :
124 : Use units of TO_BLOCK_SIZE in the output number. TO_BLOCK_SIZE
125 : must be positive.
126 :
127 : Use (OPTS & (human_round_to_nearest | human_floor | human_ceiling))
128 : to determine whether to take the ceiling or floor of any result
129 : that cannot be expressed exactly.
130 :
131 : If (OPTS & human_group_digits), group the thousands digits
132 : according to the locale, e.g., `1,000,000' in an American English
133 : locale.
134 :
135 : If (OPTS & human_autoscale), deduce the output block size
136 : automatically; TO_BLOCK_SIZE must be 1 but it has no effect on the
137 : output. Use powers of 1024 if (OPTS & human_base_1024), and powers
138 : of 1000 otherwise. For example, assuming powers of 1024, 8500
139 : would be converted to 8.3, 133456345 to 127, 56990456345 to 53, and
140 : so on. Numbers smaller than the power aren't modified.
141 : human_autoscale is normally used together with human_SI.
142 :
143 : If (OPTS & human_space_before_unit), use a space to separate the
144 : number from any suffix that is appended as described below.
145 :
146 : If (OPTS & human_SI), append an SI prefix indicating which power is
147 : being used. If in addition (OPTS & human_B), append "B" (if base
148 : 1000) or "iB" (if base 1024) to the SI prefix. When ((OPTS &
149 : human_SI) && ! (OPTS & human_autoscale)), TO_BLOCK_SIZE must be a
150 : power of 1024 or of 1000, depending on (OPTS &
151 : human_base_1024). */
152 :
153 : char *
154 42469 : human_readable (uintmax_t n, char *buf, int opts,
155 : uintmax_t from_block_size, uintmax_t to_block_size)
156 : {
157 42469 : int inexact_style =
158 : opts & (human_round_to_nearest | human_floor | human_ceiling);
159 42469 : unsigned int base = opts & human_base_1024 ? 1024 : 1000;
160 : uintmax_t amt;
161 : int tenths;
162 42469 : int exponent = -1;
163 42469 : int exponent_max = sizeof power_letter - 1;
164 : char *p;
165 : char *psuffix;
166 : char const *integerlim;
167 :
168 : /* 0 means adjusted N == AMT.TENTHS;
169 : 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
170 : 2 means adjusted N == AMT.TENTHS + 0.05;
171 : 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
172 : int rounding;
173 :
174 42469 : char const *decimal_point = ".";
175 42469 : size_t decimal_pointlen = 1;
176 42469 : char const *grouping = "";
177 42469 : char const *thousands_sep = "";
178 42469 : struct lconv const *l = localeconv ();
179 42469 : size_t pointlen = strlen (l->decimal_point);
180 42469 : if (0 < pointlen && pointlen <= MB_LEN_MAX)
181 : {
182 42469 : decimal_point = l->decimal_point;
183 42469 : decimal_pointlen = pointlen;
184 : }
185 42469 : grouping = l->grouping;
186 42469 : if (strlen (l->thousands_sep) <= MB_LEN_MAX)
187 42469 : thousands_sep = l->thousands_sep;
188 :
189 42469 : psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
190 42469 : p = psuffix;
191 :
192 : /* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE
193 : units. If this can be done exactly with integer arithmetic, do
194 : not use floating point operations. */
195 42469 : if (to_block_size <= from_block_size)
196 : {
197 1058 : if (from_block_size % to_block_size == 0)
198 : {
199 903 : uintmax_t multiplier = from_block_size / to_block_size;
200 903 : amt = n * multiplier;
201 903 : if (amt / multiplier == n)
202 : {
203 903 : tenths = 0;
204 903 : rounding = 0;
205 903 : goto use_integer_arithmetic;
206 : }
207 : }
208 : }
209 41411 : else if (from_block_size != 0 && to_block_size % from_block_size == 0)
210 : {
211 41375 : uintmax_t divisor = to_block_size / from_block_size;
212 41375 : uintmax_t r10 = (n % divisor) * 10;
213 41375 : uintmax_t r2 = (r10 % divisor) * 2;
214 41375 : amt = n / divisor;
215 41375 : tenths = r10 / divisor;
216 41375 : rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
217 41375 : goto use_integer_arithmetic;
218 : }
219 :
220 : {
221 : /* Either the result cannot be computed easily using uintmax_t,
222 : or from_block_size is zero. Fall back on floating point.
223 : FIXME: This can yield answers that are slightly off. */
224 :
225 191 : long double dto_block_size = to_block_size;
226 191 : long double damt = n * (from_block_size / dto_block_size);
227 : size_t buflen;
228 : size_t nonintegerlen;
229 :
230 191 : if (! (opts & human_autoscale))
231 : {
232 180 : sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt));
233 180 : buflen = strlen (buf);
234 180 : nonintegerlen = 0;
235 : }
236 : else
237 : {
238 11 : long double e = 1;
239 11 : exponent = 0;
240 :
241 : do
242 : {
243 11 : e *= base;
244 11 : exponent++;
245 : }
246 11 : while (e * base <= damt && exponent < exponent_max);
247 :
248 11 : damt /= e;
249 :
250 11 : sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt));
251 11 : buflen = strlen (buf);
252 11 : nonintegerlen = decimal_pointlen + 1;
253 :
254 11 : if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen
255 2 : || ((opts & human_suppress_point_zero)
256 0 : && buf[buflen - 1] == '0'))
257 : {
258 9 : sprintf (buf, "%.0Lf",
259 9 : adjust_value (inexact_style, damt * 10) / 10);
260 9 : buflen = strlen (buf);
261 9 : nonintegerlen = 0;
262 : }
263 : }
264 :
265 191 : p = psuffix - buflen;
266 191 : memmove (p, buf, buflen);
267 191 : integerlim = p + buflen - nonintegerlen;
268 : }
269 191 : goto do_grouping;
270 :
271 42278 : use_integer_arithmetic:
272 : {
273 : /* The computation can be done exactly, with integer arithmetic.
274 :
275 : Use power of BASE notation if requested and if adjusted AMT is
276 : large enough. */
277 :
278 42278 : if (opts & human_autoscale)
279 : {
280 238 : exponent = 0;
281 :
282 238 : if (base <= amt)
283 : {
284 : do
285 : {
286 478 : unsigned int r10 = (amt % base) * 10 + tenths;
287 478 : unsigned int r2 = (r10 % base) * 2 + (rounding >> 1);
288 478 : amt /= base;
289 478 : tenths = r10 / base;
290 478 : rounding = (r2 < base
291 299 : ? (r2 + rounding) != 0
292 777 : : 2 + (base < r2 + rounding));
293 478 : exponent++;
294 : }
295 478 : while (base <= amt && exponent < exponent_max);
296 :
297 183 : if (amt < 10)
298 : {
299 96 : if (inexact_style == human_round_to_nearest
300 0 : ? 2 < rounding + (tenths & 1)
301 48 : : inexact_style == human_ceiling && 0 < rounding)
302 : {
303 23 : tenths++;
304 23 : rounding = 0;
305 :
306 23 : if (tenths == 10)
307 : {
308 0 : amt++;
309 0 : tenths = 0;
310 : }
311 : }
312 :
313 48 : if (amt < 10
314 48 : && (tenths || ! (opts & human_suppress_point_zero)))
315 : {
316 24 : *--p = '0' + tenths;
317 24 : p -= decimal_pointlen;
318 24 : memcpy (p, decimal_point, decimal_pointlen);
319 24 : tenths = rounding = 0;
320 : }
321 : }
322 : }
323 : }
324 :
325 84556 : if (inexact_style == human_round_to_nearest
326 11 : ? 5 < tenths + (0 < rounding + (amt & 1))
327 42267 : : inexact_style == human_ceiling && 0 < tenths + rounding)
328 : {
329 252 : amt++;
330 :
331 252 : if ((opts & human_autoscale)
332 129 : && amt == base && exponent < exponent_max)
333 : {
334 0 : exponent++;
335 0 : if (! (opts & human_suppress_point_zero))
336 : {
337 0 : *--p = '0';
338 0 : p -= decimal_pointlen;
339 0 : memcpy (p, decimal_point, decimal_pointlen);
340 : }
341 0 : amt = 1;
342 : }
343 : }
344 :
345 42278 : integerlim = p;
346 :
347 : do
348 : {
349 87180 : int digit = amt % 10;
350 87180 : *--p = digit + '0';
351 : }
352 87180 : while ((amt /= 10) != 0);
353 : }
354 :
355 42278 : do_grouping:
356 42469 : if (opts & human_group_digits)
357 75 : p = group_number (p, integerlim - p, grouping, thousands_sep);
358 :
359 42469 : if (opts & human_SI)
360 : {
361 360 : if (exponent < 0)
362 : {
363 : uintmax_t power;
364 111 : exponent = 0;
365 597 : for (power = 1; power < to_block_size; power *= base)
366 486 : if (++exponent == exponent_max)
367 0 : break;
368 : }
369 :
370 360 : if ((exponent | (opts & human_B)) && (opts & human_space_before_unit))
371 22 : *psuffix++ = ' ';
372 :
373 360 : if (exponent)
374 305 : *psuffix++ = (! (opts & human_base_1024) && exponent == 1
375 : ? 'k'
376 : : power_letter[exponent]);
377 :
378 360 : if (opts & human_B)
379 : {
380 104 : if ((opts & human_base_1024) && exponent)
381 0 : *psuffix++ = 'i';
382 104 : *psuffix++ = 'B';
383 : }
384 : }
385 :
386 42469 : *psuffix = '\0';
387 :
388 42469 : return p;
389 : }
390 :
391 :
392 : /* The default block size used for output. This number may change in
393 : the future as disks get larger. */
394 : #ifndef DEFAULT_BLOCK_SIZE
395 : # define DEFAULT_BLOCK_SIZE 1024
396 : #endif
397 :
398 : static char const *const block_size_args[] = { "human-readable", "si", 0 };
399 : static int const block_size_opts[] =
400 : {
401 : human_autoscale + human_SI + human_base_1024,
402 : human_autoscale + human_SI
403 : };
404 :
405 : static uintmax_t
406 113 : default_block_size (void)
407 : {
408 113 : return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE;
409 : }
410 :
411 : static strtol_error
412 135 : humblock (char const *spec, uintmax_t *block_size, int *options)
413 : {
414 : int i;
415 135 : int opts = 0;
416 :
417 135 : if (! spec
418 90 : && ! (spec = getenv ("BLOCK_SIZE"))
419 90 : && ! (spec = getenv ("BLOCKSIZE")))
420 90 : *block_size = default_block_size ();
421 : else
422 : {
423 45 : if (*spec == '\'')
424 : {
425 4 : opts |= human_group_digits;
426 4 : spec++;
427 : }
428 :
429 45 : if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_opts)))
430 : {
431 6 : opts |= block_size_opts[i];
432 6 : *block_size = 1;
433 : }
434 : else
435 : {
436 : char *ptr;
437 39 : strtol_error e = xstrtoumax (spec, &ptr, 0, block_size,
438 : "eEgGkKmMpPtTyYzZ0");
439 39 : if (e != LONGINT_OK)
440 : {
441 22 : *options = 0;
442 22 : return e;
443 : }
444 26 : for (; ! ('0' <= *spec && *spec <= '9'); spec++)
445 13 : if (spec == ptr)
446 : {
447 4 : opts |= human_SI;
448 4 : if (ptr[-1] == 'B')
449 3 : opts |= human_B;
450 4 : if (ptr[-1] != 'B' || ptr[-2] == 'i')
451 1 : opts |= human_base_1024;
452 4 : break;
453 : }
454 : }
455 : }
456 :
457 113 : *options = opts;
458 113 : return LONGINT_OK;
459 : }
460 :
461 : enum strtol_error
462 135 : human_options (char const *spec, int *opts, uintmax_t *block_size)
463 : {
464 135 : strtol_error e = humblock (spec, block_size, opts);
465 135 : if (*block_size == 0)
466 : {
467 23 : *block_size = default_block_size ();
468 23 : e = LONGINT_INVALID;
469 : }
470 135 : return e;
471 : }
|