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