Annotation of /tags/mkinitrd-6_1_11/busybox/libbb/human_readable.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/libbb/human_readable.c
File MIME type: text/plain
File size: 2593 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/libbb/human_readable.c
File MIME type: text/plain
File size: 2593 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * June 30, 2001 Manuel Novoa III | ||
4 | * | ||
5 | * All-integer version (hey, not everyone has floating point) of | ||
6 | * make_human_readable_str, modified from similar code I had written | ||
7 | * for busybox several months ago. | ||
8 | * | ||
9 | * Notes: | ||
10 | * 1) I'm using an unsigned long long to hold the product size * block_size, | ||
11 | * as df (which calls this routine) could request a representation of a | ||
12 | * partition size in bytes > max of unsigned long. If long longs aren't | ||
13 | * available, it would be possible to do what's needed using polynomial | ||
14 | * representations (say, powers of 1024) and manipulating coefficients. | ||
15 | * The base ten "bytes" output could be handled similarly. | ||
16 | * | ||
17 | * 2) This routine always outputs a decimal point and a tenths digit when | ||
18 | * display_unit != 0. Hence, it isn't uncommon for the returned string | ||
19 | * to have a length of 5 or 6. | ||
20 | * | ||
21 | * It might be nice to add a flag to indicate no decimal digits in | ||
22 | * that case. This could be either an additional parameter, or a | ||
23 | * special value of display_unit. Such a flag would also be nice for du. | ||
24 | * | ||
25 | * Some code to omit the decimal point and tenths digit is sketched out | ||
26 | * and "#if 0"'d below. | ||
27 | */ | ||
28 | |||
29 | #include <stdio.h> | ||
30 | #include "libbb.h" | ||
31 | |||
32 | const char *make_human_readable_str(unsigned long long size, | ||
33 | unsigned long block_size, unsigned long display_unit) | ||
34 | { | ||
35 | /* The code will adjust for additional (appended) units. */ | ||
36 | static const char zero_and_units[] = { '0', 0, 'k', 'M', 'G', 'T' }; | ||
37 | static const char fmt[] = "%llu"; | ||
38 | static const char fmt_tenths[] = "%llu.%d%c"; | ||
39 | |||
40 | static char str[21]; /* Sufficient for 64 bit unsigned integers. */ | ||
41 | |||
42 | unsigned long long val; | ||
43 | int frac; | ||
44 | const char *u; | ||
45 | const char *f; | ||
46 | |||
47 | u = zero_and_units; | ||
48 | f = fmt; | ||
49 | frac = 0; | ||
50 | |||
51 | val = size * block_size; | ||
52 | if (val == 0) { | ||
53 | return u; | ||
54 | } | ||
55 | |||
56 | if (display_unit) { | ||
57 | val += display_unit/2; /* Deal with rounding. */ | ||
58 | val /= display_unit; /* Don't combine with the line above!!! */ | ||
59 | } else { | ||
60 | ++u; | ||
61 | while ((val >= 1024) | ||
62 | && (u < zero_and_units + sizeof(zero_and_units) - 1) | ||
63 | ) { | ||
64 | f = fmt_tenths; | ||
65 | ++u; | ||
66 | frac = (((int)(val % 1024)) * 10 + 1024/2) / 1024; | ||
67 | val /= 1024; | ||
68 | } | ||
69 | if (frac >= 10) { /* We need to round up here. */ | ||
70 | ++val; | ||
71 | frac = 0; | ||
72 | } | ||
73 | #if 0 | ||
74 | /* Sample code to omit decimal point and tenths digit. */ | ||
75 | if ( /* no_tenths */ 1 ) { | ||
76 | if ( frac >= 5 ) { | ||
77 | ++val; | ||
78 | } | ||
79 | f = "%llu%*c" /* fmt_no_tenths */ ; | ||
80 | frac = 1; | ||
81 | } | ||
82 | #endif | ||
83 | } | ||
84 | |||
85 | /* If f==fmt then 'frac' and 'u' are ignored. */ | ||
86 | snprintf(str, sizeof(str), f, val, frac, *u); | ||
87 | |||
88 | return str; | ||
89 | } |