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