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