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