Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/libbb/human_readable.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/libbb/human_readable.c
r1765 r2725 25 25 * Some code to omit the decimal point and tenths digit is sketched out 26 26 * and "#if 0"'d below. 27 * 28 * Licensed under GPLv2, see file LICENSE in this source tree. 27 29 */ 28 30 29 31 #include "libbb.h" 30 32 31 const char *make_human_readable_str(unsigned long long size,33 const char* FAST_FUNC make_human_readable_str(unsigned long long val, 32 34 unsigned long block_size, unsigned long display_unit) 33 35 { 34 /* The code will adjust for additional (appended) units */ 35 static const char zero_and_units[] ALIGN1 = { '0', 0, 'k', 'M', 'G', 'T' }; 36 static const char fmt[] ALIGN1 = "%llu"; 37 static const char fmt_tenths[] ALIGN1 = "%llu.%d%c"; 36 static const char unit_chars[] ALIGN1 = { 37 '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' 38 }; 38 39 39 static char str[21] ALIGN1; /* Sufficient for 64 bit unsigned integers */40 static char *str; 40 41 41 unsigned long long val; 42 int frac; 42 unsigned frac; /* 0..9 - the fractional digit */ 43 43 const char *u; 44 const char *f ;44 const char *fmt; 45 45 46 u = zero_and_units; 47 f = fmt; 46 if (val == 0) 47 return "0"; 48 49 fmt = "%llu"; 50 if (block_size > 1) 51 val *= block_size; 48 52 frac = 0; 49 50 val = size * block_size; 51 if (val == 0) { 52 return u; 53 } 53 u = unit_chars; 54 54 55 55 if (display_unit) { 56 val += display_unit/2; /* Deal with rounding */ 57 val /= display_unit; /* Don't combine with the line above!!! */ 56 val += display_unit/2; /* Deal with rounding */ 57 val /= display_unit; /* Don't combine with the line above! */ 58 /* will just print it as ulonglong (below) */ 58 59 } else { 59 ++u;60 60 while ((val >= 1024) 61 && (u < zero_and_units + sizeof(zero_and_units) - 1)61 /* && (u < unit_chars + sizeof(unit_chars) - 1) - always true */ 62 62 ) { 63 f = fmt_tenths;64 ++u;65 frac = ((( int)(val % 1024)) * 10 + 1024/2) / 1024;63 fmt = "%llu.%u%c"; 64 u++; 65 frac = (((unsigned)val % 1024) * 10 + 1024/2) / 1024; 66 66 val /= 1024; 67 67 } 68 if (frac >= 10) { /* We need to round up here.*/68 if (frac >= 10) { /* we need to round up here */ 69 69 ++val; 70 70 frac = 0; 71 71 } 72 #if 073 /* Sample code to omit decimal point and tenths digit.*/74 if ( /* no_tenths */ 1) {72 #if 1 73 /* If block_size is 0, dont print fractional part */ 74 if (block_size == 0) { 75 75 if (frac >= 5) { 76 76 ++val; 77 77 } 78 f = "%llu%*c" /* fmt_no_tenths */;78 fmt = "%llu%*c"; 79 79 frac = 1; 80 80 } … … 82 82 } 83 83 84 /* If f==fmt then 'frac' and 'u' are ignored. */ 85 snprintf(str, sizeof(str), f, val, frac, *u); 86 84 if (!str) { 85 /* sufficient for any width of val */ 86 str = xmalloc(sizeof(val)*3 + 2 + 3); 87 } 88 sprintf(str, fmt, val, frac, *u); 87 89 return str; 88 90 } 91 92 93 /* vda's implementations of the similar idea */ 94 95 /* Convert unsigned long long value into compact 5-char representation. 96 * String is not terminated (buf[5] is untouched) */ 97 void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) 98 { 99 const char *fmt; 100 char c; 101 unsigned v, u, idx = 0; 102 103 if (ul > 99999) { // do not scale if 99999 or less 104 ul *= 10; 105 do { 106 ul /= 1024; 107 idx++; 108 } while (ul >= 100000); 109 } 110 v = ul; // ullong divisions are expensive, avoid them 111 112 fmt = " 123456789"; 113 u = v / 10; 114 v = v % 10; 115 if (!idx) { 116 // 99999 or less: use "12345" format 117 // u is value/10, v is last digit 118 c = buf[0] = " 123456789"[u/1000]; 119 if (c != ' ') fmt = "0123456789"; 120 c = buf[1] = fmt[u/100%10]; 121 if (c != ' ') fmt = "0123456789"; 122 c = buf[2] = fmt[u/10%10]; 123 if (c != ' ') fmt = "0123456789"; 124 buf[3] = fmt[u%10]; 125 buf[4] = "0123456789"[v]; 126 } else { 127 // value has been scaled into 0..9999.9 range 128 // u is value, v is 1/10ths (allows for 92.1M format) 129 if (u >= 100) { 130 // value is >= 100: use "1234M', " 123M" formats 131 c = buf[0] = " 123456789"[u/1000]; 132 if (c != ' ') fmt = "0123456789"; 133 c = buf[1] = fmt[u/100%10]; 134 if (c != ' ') fmt = "0123456789"; 135 v = u % 10; 136 u = u / 10; 137 buf[2] = fmt[u%10]; 138 } else { 139 // value is < 100: use "92.1M" format 140 c = buf[0] = " 123456789"[u/10]; 141 if (c != ' ') fmt = "0123456789"; 142 buf[1] = fmt[u%10]; 143 buf[2] = '.'; 144 } 145 buf[3] = "0123456789"[v]; 146 buf[4] = scale[idx]; /* typically scale = " kmgt..." */ 147 } 148 } 149 150 /* Convert unsigned long long value into compact 4-char 151 * representation. Examples: "1234", "1.2k", " 27M", "123T" 152 * String is not terminated (buf[4] is untouched) */ 153 void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[4], const char *scale) 154 { 155 const char *fmt; 156 char c; 157 unsigned v, u, idx = 0; 158 159 if (ul > 9999) { // do not scale if 9999 or less 160 ul *= 10; 161 do { 162 ul /= 1024; 163 idx++; 164 } while (ul >= 10000); 165 } 166 v = ul; // ullong divisions are expensive, avoid them 167 168 fmt = " 123456789"; 169 u = v / 10; 170 v = v % 10; 171 if (!idx) { 172 // 9999 or less: use "1234" format 173 // u is value/10, v is last digit 174 c = buf[0] = " 123456789"[u/100]; 175 if (c != ' ') fmt = "0123456789"; 176 c = buf[1] = fmt[u/10%10]; 177 if (c != ' ') fmt = "0123456789"; 178 buf[2] = fmt[u%10]; 179 buf[3] = "0123456789"[v]; 180 } else { 181 // u is value, v is 1/10ths (allows for 9.2M format) 182 if (u >= 10) { 183 // value is >= 10: use "123M', " 12M" formats 184 c = buf[0] = " 123456789"[u/100]; 185 if (c != ' ') fmt = "0123456789"; 186 v = u % 10; 187 u = u / 10; 188 buf[1] = fmt[u%10]; 189 } else { 190 // value is < 10: use "9.2M" format 191 buf[0] = "0123456789"[u]; 192 buf[1] = '.'; 193 } 194 buf[2] = "0123456789"[v]; 195 buf[3] = scale[idx]; /* typically scale = " kmgt..." */ 196 } 197 }
Note:
See TracChangeset
for help on using the changeset viewer.