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 (uintmax_t n
, char *buf
, int from_units
, int to_units
, int base
)
78 /* 0 means adjusted N == AMT.TENTHS;
79 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
80 2 means adjusted N == AMT.TENTHS + 0.05;
81 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
84 p
= buf
+ LONGEST_HUMAN_READABLE
;
88 /* Suppress `used before initialized' warning. */
92 /* Adjust AMT out of FROM_UNITS units and into TO_UNITS units. */
94 if (to_units
<= from_units
)
96 int multiplier
= from_units
/ to_units
;
98 tenths
= rounding
= 0;
100 if (amt
/ multiplier
!= n
)
102 /* Overflow occurred during multiplication. We should use
103 multiple precision arithmetic here, but we'll be lazy and
104 resort to floating point. This can yield answers that
105 are slightly off. In practice it is quite rare to
106 overflow uintmax_t, so this is good enough for now. */
108 double damt
= n
* (double) multiplier
;
111 sprintf (buf
, "%.0f", damt
);
122 while (e
* base
<= amt
&& power
< sizeof suffixes
- 1);
126 sprintf (buf
, "%.1f%c", damt
, suffixes
[power
]);
127 if (4 < strlen (buf
))
128 sprintf (buf
, "%.0f%c", damt
, suffixes
[power
]);
136 int divisor
= to_units
/ from_units
;
137 int r10
= (n
% divisor
) * 10;
138 int r2
= (r10
% divisor
) * 2;
140 tenths
= r10
/ divisor
;
141 rounding
= r2
< divisor
? 0 < r2
: 2 + (divisor
< r2
);
145 /* Use power of BASE notation if adjusted AMT is large enough. */
147 if (base
&& base
<= amt
)
153 int r10
= (amt
% base
) * 10 + tenths
;
154 int r2
= (r10
% base
) * 2 + (rounding
>> 1);
157 rounding
= (r2
< base
159 : 2 + (base
< r2
+ rounding
));
162 while (base
<= amt
&& power
< sizeof suffixes
- 1);
164 *--p
= suffixes
[power
];
168 tenths
+= 2 < rounding
+ (tenths
& 1);
185 if (5 < tenths
+ (2 < rounding
+ (amt
& 1)))
189 if (amt
== base
&& power
< sizeof suffixes
- 1)
191 *p
= suffixes
[power
+ 1];
199 *--p
= '0' + (int) (amt
% 10);
200 while ((amt
/= 10) != 0);