198038Sache/* human.c -- print human readable file size
298038Sache
3133543Stjr   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4133543Stjr   Free Software Foundation, Inc.
598038Sache
698038Sache   This program is free software; you can redistribute it and/or modify
798038Sache   it under the terms of the GNU General Public License as published by
898038Sache   the Free Software Foundation; either version 2, or (at your option)
998038Sache   any later version.
1098038Sache
1198038Sache   This program is distributed in the hope that it will be useful,
1298038Sache   but WITHOUT ANY WARRANTY; without even the implied warranty of
1398038Sache   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498038Sache   GNU General Public License for more details.
1598038Sache
1698038Sache   You should have received a copy of the GNU General Public License
1798038Sache   along with this program; if not, write to the Free Software Foundation,
1898038Sache   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
1998038Sache
20131447Stjr/* Written by Paul Eggert and Larry McVoy.  */
2198038Sache
2298038Sache#if HAVE_CONFIG_H
2398038Sache# include <config.h>
2498038Sache#endif
2598038Sache
26131447Stjr#include "human.h"
2798038Sache
28131447Stjr#ifndef SIZE_MAX
29131447Stjr# define SIZE_MAX ((size_t) -1)
3098038Sache#endif
31131447Stjr#ifndef UINTMAX_MAX
32131447Stjr# define UINTMAX_MAX ((uintmax_t) -1)
3398038Sache#endif
3498038Sache
35131447Stjr#if HAVE_LOCALE_H && HAVE_LOCALECONV
36131447Stjr# include <locale.h>
3798038Sache#endif
3898038Sache
39131447Stjr#include <stdio.h>
40131447Stjr#include <stdlib.h>
41131447Stjr#include <string.h>
4298038Sache
43131447Stjr#include "gettext.h"
44131447Stjr#define _(msgid) gettext (msgid)
4598038Sache
4698038Sache#include <argmatch.h>
4798038Sache#include <error.h>
4898038Sache#include <xstrtol.h>
4998038Sache
50131447Stjr/* The maximum length of a suffix like "KiB".  */
51131447Stjr#define HUMAN_READABLE_SUFFIX_LENGTH_MAX 3
5298038Sache
53131447Stjrstatic const char power_letter[] =
5498038Sache{
5598038Sache  0,	/* not used */
5698038Sache  'K',	/* kibi ('k' for kilo is a special case) */
5798038Sache  'M',	/* mega or mebi */
5898038Sache  'G',	/* giga or gibi */
5998038Sache  'T',	/* tera or tebi */
6098038Sache  'P',	/* peta or pebi */
6198038Sache  'E',	/* exa or exbi */
6298038Sache  'Z',	/* zetta or 2**70 */
6398038Sache  'Y'	/* yotta or 2**80 */
6498038Sache};
6598038Sache
6698038Sache
67131447Stjr/* If INEXACT_STYLE is not human_round_to_nearest, and if easily
68131447Stjr   possible, adjust VALUE according to the style.  */
6998038Sache
70131447Stjrstatic long double
71131447Stjradjust_value (int inexact_style, long double value)
7298038Sache{
73131447Stjr  /* Do not use the floorl or ceill functions, as that would mean
74131447Stjr     checking for their presence and possibly linking with the
75131447Stjr     standard math library, which is a porting pain.  So leave the
76131447Stjr     value alone if it is too large to easily round.  */
77131447Stjr  if (inexact_style != human_round_to_nearest && value < UINTMAX_MAX)
7898038Sache    {
7998038Sache      uintmax_t u = value;
8098038Sache      value = u + (inexact_style == human_ceiling && u != value);
8198038Sache    }
8298038Sache
8398038Sache  return value;
8498038Sache}
8598038Sache
86131447Stjr/* Group the digits of NUMBER according to the grouping rules of the
87131447Stjr   current locale.  NUMBER contains NUMBERLEN digits.  Modify the
88131447Stjr   bytes pointed to by NUMBER in place, subtracting 1 from NUMBER for
89131447Stjr   each byte inserted.  Return the starting address of the modified
90131447Stjr   number.
91131447Stjr
92131447Stjr   To group the digits, use GROUPING and THOUSANDS_SEP as in `struct
93131447Stjr   lconv' from <locale.h>.  */
94131447Stjr
95131447Stjrstatic char *
96131447Stjrgroup_number (char *number, size_t numberlen,
97131447Stjr	      char const *grouping, char const *thousands_sep)
9898038Sache{
99131447Stjr  register char *d;
100131447Stjr  size_t grouplen = SIZE_MAX;
101131447Stjr  size_t thousands_seplen = strlen (thousands_sep);
102131447Stjr  size_t i = numberlen;
103131447Stjr
104131447Stjr  /* The maximum possible value for NUMBERLEN is the number of digits
105131447Stjr     in the square of the largest uintmax_t, so double the size of
106131447Stjr     uintmax_t before converting to a bound.  302 / 1000 is ceil
107131447Stjr     (log10 (2.0)).  Add 1 for integer division truncation.  */
108131447Stjr  char buf[2 * sizeof (uintmax_t) * CHAR_BIT * 302 / 1000 + 1];
109131447Stjr
110131447Stjr  memcpy (buf, number, numberlen);
111131447Stjr  d = number + numberlen;
112131447Stjr
113131447Stjr  for (;;)
114131447Stjr    {
115131447Stjr      unsigned char g = *grouping;
116131447Stjr
117131447Stjr      if (g)
118131447Stjr	{
119131447Stjr	  grouplen = g < CHAR_MAX ? g : i;
120131447Stjr	  grouping++;
121131447Stjr	}
122131447Stjr
123131447Stjr      if (i < grouplen)
124131447Stjr	grouplen = i;
125131447Stjr
126131447Stjr      d -= grouplen;
127131447Stjr      i -= grouplen;
128131447Stjr      memcpy (d, buf + i, grouplen);
129131447Stjr      if (i == 0)
130131447Stjr	return d;
131131447Stjr
132131447Stjr      d -= thousands_seplen;
133131447Stjr      memcpy (d, thousands_sep, thousands_seplen);
134131447Stjr    }
13598038Sache}
13698038Sache
137131447Stjr/* Convert N to a human readable format in BUF, using the options OPTS.
13898038Sache
13998038Sache   N is expressed in units of FROM_BLOCK_SIZE.  FROM_BLOCK_SIZE must
14098038Sache   be nonnegative.
14198038Sache
142131447Stjr   Use units of TO_BLOCK_SIZE in the output number.  TO_BLOCK_SIZE
143131447Stjr   must be positive.
14498038Sache
145131447Stjr   Use (OPTS & (human_round_to_nearest | human_floor | human_ceiling))
146131447Stjr   to determine whether to take the ceiling or floor of any result
147131447Stjr   that cannot be expressed exactly.
14898038Sache
149131447Stjr   If (OPTS & human_group_digits), group the thousands digits
150131447Stjr   according to the locale, e.g., `1,000,000' in an American English
151131447Stjr   locale.
15298038Sache
153131447Stjr   If (OPTS & human_autoscale), deduce the output block size
154131447Stjr   automatically; TO_BLOCK_SIZE must be 1 but it has no effect on the
155131447Stjr   output.  Use powers of 1024 if (OPTS & human_base_1024), and powers
156131447Stjr   of 1000 otherwise.  For example, assuming powers of 1024, 8500
157131447Stjr   would be converted to 8.3, 133456345 to 127, 56990456345 to 53, and
158131447Stjr   so on.  Numbers smaller than the power aren't modified.
159131447Stjr   human_autoscale is normally used together with human_SI.
160131447Stjr
161131447Stjr   If (OPTS & human_SI), append an SI prefix indicating which power is
162131447Stjr   being used.  If in addition (OPTS & human_B), append "B" (if base
163131447Stjr   1000) or "iB" (if base 1024) to the SI prefix.  When ((OPTS &
164131447Stjr   human_SI) && ! (OPTS & human_autoscale)), TO_BLOCK_SIZE must be a
165131447Stjr   power of 1024 or of 1000, depending on (OPTS &
166131447Stjr   human_base_1024).  */
167131447Stjr
16898038Sachechar *
169131447Stjrhuman_readable (uintmax_t n, char *buf, int opts,
170131447Stjr		uintmax_t from_block_size, uintmax_t to_block_size)
17198038Sache{
172131447Stjr  int inexact_style =
173131447Stjr    opts & (human_round_to_nearest | human_floor | human_ceiling);
174131447Stjr  unsigned int base = opts & human_base_1024 ? 1024 : 1000;
17598038Sache  uintmax_t amt;
176131447Stjr  int tenths;
177131447Stjr  int exponent = -1;
178131447Stjr  int exponent_max = sizeof power_letter - 1;
17998038Sache  char *p;
180131447Stjr  char *psuffix;
181131447Stjr  char const *integerlim;
18298038Sache
18398038Sache  /* 0 means adjusted N == AMT.TENTHS;
18498038Sache     1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
18598038Sache     2 means adjusted N == AMT.TENTHS + 0.05;
18698038Sache     3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1.  */
187131447Stjr  int rounding;
18898038Sache
189131447Stjr  char const *decimal_point = ".";
190131447Stjr  size_t decimal_pointlen = 1;
191131447Stjr  char const *grouping = "";
192131447Stjr  char const *thousands_sep = "";
193131447Stjr#if HAVE_LOCALE_H && HAVE_LOCALECONV
194131447Stjr  struct lconv const *l = localeconv ();
195131447Stjr  size_t pointlen = strlen (l->decimal_point);
196131447Stjr  if (0 < pointlen && pointlen <= MB_LEN_MAX)
19798038Sache    {
198131447Stjr      decimal_point = l->decimal_point;
199131447Stjr      decimal_pointlen = pointlen;
20098038Sache    }
201131447Stjr  grouping = l->grouping;
202131447Stjr  if (strlen (l->thousands_sep) <= MB_LEN_MAX)
203131447Stjr    thousands_sep = l->thousands_sep;
204131447Stjr#endif
205131447Stjr
206131447Stjr  psuffix = buf + LONGEST_HUMAN_READABLE - HUMAN_READABLE_SUFFIX_LENGTH_MAX;
207131447Stjr  p = psuffix;
208131447Stjr
209131447Stjr  /* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE
210131447Stjr     units.  If this can be done exactly with integer arithmetic, do
211131447Stjr     not use floating point operations.  */
212131447Stjr  if (to_block_size <= from_block_size)
21398038Sache    {
214131447Stjr      if (from_block_size % to_block_size == 0)
215131447Stjr	{
216131447Stjr	  uintmax_t multiplier = from_block_size / to_block_size;
217131447Stjr	  amt = n * multiplier;
218131447Stjr	  if (amt / multiplier == n)
219131447Stjr	    {
220131447Stjr	      tenths = 0;
221131447Stjr	      rounding = 0;
222131447Stjr	      goto use_integer_arithmetic;
223131447Stjr	    }
224131447Stjr	}
22598038Sache    }
226131447Stjr  else if (from_block_size != 0 && to_block_size % from_block_size == 0)
227131447Stjr    {
228131447Stjr      uintmax_t divisor = to_block_size / from_block_size;
229131447Stjr      uintmax_t r10 = (n % divisor) * 10;
230131447Stjr      uintmax_t r2 = (r10 % divisor) * 2;
231131447Stjr      amt = n / divisor;
232131447Stjr      tenths = r10 / divisor;
233131447Stjr      rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
234131447Stjr      goto use_integer_arithmetic;
235131447Stjr    }
23698038Sache
237131447Stjr  {
238131447Stjr    /* Either the result cannot be computed easily using uintmax_t,
239131447Stjr       or from_block_size is zero.  Fall back on floating point.
240131447Stjr       FIXME: This can yield answers that are slightly off.  */
24198038Sache
242131447Stjr    long double dto_block_size = to_block_size;
243131447Stjr    long double damt = n * (from_block_size / dto_block_size);
244131447Stjr    size_t buflen;
245131447Stjr    size_t nonintegerlen;
24698038Sache
247131447Stjr    if (! (opts & human_autoscale))
248131447Stjr      {
249131447Stjr	sprintf (buf, "%.0Lf", adjust_value (inexact_style, damt));
250131447Stjr	buflen = strlen (buf);
251131447Stjr	nonintegerlen = 0;
252131447Stjr      }
253131447Stjr    else
254131447Stjr      {
255131447Stjr	long double e = 1;
256131447Stjr	exponent = 0;
25798038Sache
258131447Stjr	do
259131447Stjr	  {
260131447Stjr	    e *= base;
261131447Stjr	    exponent++;
262131447Stjr	  }
263131447Stjr	while (e * base <= damt && exponent < exponent_max);
264131447Stjr
265131447Stjr	damt /= e;
266131447Stjr
267131447Stjr	sprintf (buf, "%.1Lf", adjust_value (inexact_style, damt));
268131447Stjr	buflen = strlen (buf);
269131447Stjr	nonintegerlen = decimal_pointlen + 1;
270131447Stjr
271131447Stjr	if (1 + nonintegerlen + ! (opts & human_base_1024) < buflen
272131447Stjr	    || ((opts & human_suppress_point_zero)
273131447Stjr		&& buf[buflen - 1] == '0'))
274131447Stjr	  {
275131447Stjr	    sprintf (buf, "%.0Lf",
276131447Stjr		     adjust_value (inexact_style, damt * 10) / 10);
277131447Stjr	    buflen = strlen (buf);
278131447Stjr	    nonintegerlen = 0;
279131447Stjr	  }
280131447Stjr      }
281131447Stjr
282131447Stjr    p = psuffix - buflen;
283131447Stjr    memmove (p, buf, buflen);
284131447Stjr    integerlim = p + buflen - nonintegerlen;
285131447Stjr  }
286131447Stjr  goto do_grouping;
287131447Stjr
288131447Stjr use_integer_arithmetic:
28998038Sache  {
290131447Stjr    /* The computation can be done exactly, with integer arithmetic.
291131447Stjr
292131447Stjr       Use power of BASE notation if requested and if adjusted AMT is
293131447Stjr       large enough.  */
294131447Stjr
295131447Stjr    if (opts & human_autoscale)
29698038Sache      {
297131447Stjr	exponent = 0;
29898038Sache
299131447Stjr	if (base <= amt)
30098038Sache	  {
30198038Sache	    do
30298038Sache	      {
303133543Stjr		unsigned int r10 = (amt % base) * 10 + tenths;
304133543Stjr		unsigned int r2 = (r10 % base) * 2 + (rounding >> 1);
305131447Stjr		amt /= base;
306131447Stjr		tenths = r10 / base;
307131447Stjr		rounding = (r2 < base
308131447Stjr			    ? (r2 + rounding) != 0
309131447Stjr			    : 2 + (base < r2 + rounding));
310131447Stjr		exponent++;
31198038Sache	      }
312131447Stjr	    while (base <= amt && exponent < exponent_max);
31398038Sache
314131447Stjr	    if (amt < 10)
315131447Stjr	      {
316131447Stjr		if (inexact_style == human_round_to_nearest
317131447Stjr		    ? 2 < rounding + (tenths & 1)
318131447Stjr		    : inexact_style == human_ceiling && 0 < rounding)
319131447Stjr		  {
320131447Stjr		    tenths++;
321131447Stjr		    rounding = 0;
32298038Sache
323131447Stjr		    if (tenths == 10)
324131447Stjr		      {
325131447Stjr			amt++;
326131447Stjr			tenths = 0;
327131447Stjr		      }
328131447Stjr		  }
329131447Stjr
330131447Stjr		if (amt < 10
331131447Stjr		    && (tenths || ! (opts & human_suppress_point_zero)))
332131447Stjr		  {
333131447Stjr		    *--p = '0' + tenths;
334131447Stjr		    p -= decimal_pointlen;
335131447Stjr		    memcpy (p, decimal_point, decimal_pointlen);
336131447Stjr		    tenths = rounding = 0;
337131447Stjr		  }
338131447Stjr	      }
33998038Sache	  }
340131447Stjr      }
34198038Sache
342131447Stjr    if (inexact_style == human_round_to_nearest
343131447Stjr	? 5 < tenths + (0 < rounding + (amt & 1))
344131447Stjr	: inexact_style == human_ceiling && 0 < tenths + rounding)
345131447Stjr      {
346131447Stjr	amt++;
347131447Stjr
348131447Stjr	if ((opts & human_autoscale)
349131447Stjr	    && amt == base && exponent < exponent_max)
350131447Stjr	  {
351131447Stjr	    exponent++;
352131447Stjr	    if (! (opts & human_suppress_point_zero))
353131447Stjr	      {
354131447Stjr		*--p = '0';
355131447Stjr		p -= decimal_pointlen;
356131447Stjr		memcpy (p, decimal_point, decimal_pointlen);
357131447Stjr	      }
358131447Stjr	    amt = 1;
359131447Stjr	  }
36098038Sache      }
361131447Stjr
362131447Stjr    integerlim = p;
363131447Stjr
364131447Stjr    do
365131447Stjr      {
366131447Stjr	int digit = amt % 10;
367131447Stjr	*--p = digit + '0';
368131447Stjr      }
369131447Stjr    while ((amt /= 10) != 0);
37098038Sache  }
37198038Sache
372131447Stjr do_grouping:
373131447Stjr  if (opts & human_group_digits)
374131447Stjr    p = group_number (p, integerlim - p, grouping, thousands_sep);
37598038Sache
376131447Stjr  if (opts & human_SI)
37798038Sache    {
378131447Stjr      if (exponent < 0)
37998038Sache	{
380131447Stjr	  uintmax_t power;
381131447Stjr	  exponent = 0;
382131447Stjr	  for (power = 1; power < to_block_size; power *= base)
383131447Stjr	    if (++exponent == exponent_max)
384131447Stjr	      break;
38598038Sache	}
38698038Sache
387131447Stjr      if (exponent)
388131447Stjr	*psuffix++ = (! (opts & human_base_1024) && exponent == 1
389131447Stjr		      ? 'k'
390131447Stjr		      : power_letter[exponent]);
39198038Sache
392131447Stjr      if (opts & human_B)
39398038Sache	{
394131447Stjr	  if ((opts & human_base_1024) && exponent)
395131447Stjr	    *psuffix++ = 'i';
396131447Stjr	  *psuffix++ = 'B';
39798038Sache	}
39898038Sache    }
39998038Sache
400131447Stjr  *psuffix = '\0';
40198038Sache
40298038Sache  return p;
40398038Sache}
40498038Sache
40598038Sache
40698038Sache/* The default block size used for output.  This number may change in
40798038Sache   the future as disks get larger.  */
40898038Sache#ifndef DEFAULT_BLOCK_SIZE
40998038Sache# define DEFAULT_BLOCK_SIZE 1024
41098038Sache#endif
41198038Sache
41298038Sachestatic char const *const block_size_args[] = { "human-readable", "si", 0 };
413131447Stjrstatic int const block_size_opts[] =
414131447Stjr  {
415131447Stjr    human_autoscale + human_SI + human_base_1024,
416131447Stjr    human_autoscale + human_SI
417131447Stjr  };
41898038Sache
419131447Stjrstatic uintmax_t
42098038Sachedefault_block_size (void)
42198038Sache{
42298038Sache  return getenv ("POSIXLY_CORRECT") ? 512 : DEFAULT_BLOCK_SIZE;
42398038Sache}
42498038Sache
42598038Sachestatic strtol_error
426131447Stjrhumblock (char const *spec, uintmax_t *block_size, int *options)
42798038Sache{
42898038Sache  int i;
429131447Stjr  int opts = 0;
43098038Sache
431133543Stjr  if (! spec
432133543Stjr      && ! (spec = getenv ("BLOCK_SIZE"))
433133543Stjr      && ! (spec = getenv ("BLOCKSIZE")))
43498038Sache    *block_size = default_block_size ();
43598038Sache  else
43698038Sache    {
437131447Stjr      if (*spec == '\'')
438131447Stjr	{
439131447Stjr	  opts |= human_group_digits;
440131447Stjr	  spec++;
441131447Stjr	}
442131447Stjr
443131447Stjr      if (0 <= (i = ARGMATCH (spec, block_size_args, block_size_opts)))
444131447Stjr	{
445131447Stjr	  opts |= block_size_opts[i];
446131447Stjr	  *block_size = 1;
447131447Stjr	}
448131447Stjr      else
449131447Stjr	{
450131447Stjr	  char *ptr;
451131447Stjr	  strtol_error e = xstrtoumax (spec, &ptr, 0, block_size,
452131447Stjr				       "eEgGkKmMpPtTyYzZ0");
453131447Stjr	  if (e != LONGINT_OK)
454131447Stjr	    return e;
455131447Stjr	  for (; ! ('0' <= *spec && *spec <= '9'); spec++)
456131447Stjr	    if (spec == ptr)
457131447Stjr	      {
458131447Stjr		opts |= human_SI;
459131447Stjr		if (ptr[-1] == 'B')
460131447Stjr		  opts |= human_B;
461131447Stjr		if (ptr[-1] != 'B' || ptr[-2] == 'i')
462131447Stjr		  opts |= human_base_1024;
463131447Stjr		break;
464131447Stjr	      }
465131447Stjr	}
46698038Sache    }
46798038Sache
468131447Stjr  *options = opts;
46998038Sache  return LONGINT_OK;
47098038Sache}
47198038Sache
472131447Stjrint
473131447Stjrhuman_options (char const *spec, bool report_errors, uintmax_t *block_size)
47498038Sache{
475131447Stjr  int opts;
476131447Stjr  strtol_error e = humblock (spec, block_size, &opts);
47798038Sache  if (*block_size == 0)
47898038Sache    {
47998038Sache      *block_size = default_block_size ();
48098038Sache      e = LONGINT_INVALID;
48198038Sache    }
48298038Sache  if (e != LONGINT_OK && report_errors)
48398038Sache    STRTOL_FATAL_ERROR (spec, _("block size"), e);
484131447Stjr  return opts;
48598038Sache}
486