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