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