1 /* human.c -- print human readable file size
2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Originally contributed by lm@sgi.com;
19 --si and large file support added by eggert@twinsun.com. */
24 # include <inttypes.h>
27 #include <sys/types.h>
40 static const char suffixes[] =
53 /* Convert N to a human readable format in BUF.
55 N is expressed in units of FROM_UNITS; use units of TO_UNITS in the
56 output number. FROM_UNITS and TO_UNITS must be positive, and one must
57 be a multiple of the other.
59 If BASE is nonzero, use a format like "127k" if possible,
60 using powers of BASE; otherwise, use ordinary decimal format.
61 Normally BASE is either 1000 or 1024; it must be at least 2.
62 Most people visually process strings of 3-4 digits effectively,
63 but longer strings of digits are more prone to misinterpretation.
64 Hence, converting to an abbreviated form usually improves readability.
65 Use a suffix indicating which power is being used.
66 For example, assuming BASE is 1024, 8500 would be converted to 8.3k,
67 133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
68 than BASE aren't modified. */
71 human_readable (n, buf, from_units, to_units, base)
83 /* 0 means adjusted N == AMT.TENTHS;
84 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
85 2 means adjusted N == AMT.TENTHS + 0.05;
86 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
89 p = buf + LONGEST_HUMAN_READABLE;
93 /* Adjust AMT out of FROM_UNITS units and into TO_UNITS units. */
95 if (to_units <= from_units)
97 int multiplier = from_units / to_units;
99 tenths = rounding = 0;
101 if (amt / multiplier != n)
103 /* Overflow occurred during multiplication. We should use
104 multiple precision arithmetic here, but we'll be lazy and
105 resort to floating point. This can yield answers that
106 are slightly off. In practice it is quite rare to
107 overflow uintmax_t, so this is good enough for now. */
109 double damt = n * (double) multiplier;
112 sprintf (buf, "%.0f", damt);
123 while (e * base <= amt && power < sizeof suffixes - 1);
127 sprintf (buf, "%.1f%c", damt, suffixes[power]);
128 if (4 < strlen (buf))
129 sprintf (buf, "%.0f%c", damt, suffixes[power]);
137 int divisor = to_units / from_units;
138 int r10 = (n % divisor) * 10;
139 int r2 = (r10 % divisor) * 2;
141 tenths = r10 / divisor;
142 rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
146 /* Use power of BASE notation if adjusted AMT is large enough. */
148 if (base && base <= amt)
154 int r10 = (amt % base) * 10 + tenths;
155 int r2 = (r10 % base) * 2 + (rounding >> 1);
158 rounding = (r2 < base
160 : 2 + (base < r2 + rounding));
163 while (base <= amt && power < sizeof suffixes - 1);
165 *--p = suffixes[power];
169 tenths += 2 < rounding + (tenths & 1);
186 if (5 < tenths + (2 < rounding + (amt & 1)))
190 if (amt == base && power < sizeof suffixes - 1)
192 *p = suffixes[power + 1];
200 *--p = '0' + (int) (amt % 10);
201 while ((amt /= 10) != 0);