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