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