diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/xfuncs.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index c72265003..352515af4 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -201,23 +201,71 @@ void xsetenv(const char *key, const char *value) bb_error_msg_and_die(bb_msg_memory_exhausted); } + +// Converts unsigned long long value into compact 4-char +// representation. Examples: "1234", "1.2k", " 27M", "123T" +// Fifth char is always '\0' +void smart_ulltoa5(unsigned long long ul, char buf[5]) +{ + char *fmt; + char c; + unsigned v,idx = 0; + ul *= 10; + if (ul > 9999*10) { // do not scale if 9999 or less + while (ul >= 10000) { + ul /= 1024; + idx++; + } + } + v = ul; // ullong divisions are expensive, avoid them + + fmt = " 123456789"; + if (!idx) { // 9999 or less: use 1234 format + c = buf[0] = " 123456789"[v/10000]; + if (c!=' ') fmt = "0123456789"; + c = buf[1] = fmt[v/1000%10]; + if (c!=' ') fmt = "0123456789"; + buf[2] = fmt[v/100%10]; + buf[3] = "0123456789"[v/10%10]; + } else { + if (v>=10*10) { // scaled value is >=10: use 123M format + c = buf[0] = " 123456789"[v/1000]; + if (c!=' ') fmt = "0123456789"; + buf[1] = fmt[v/100%10]; + buf[2] = "0123456789"[v/10%10]; + } else { // scaled value is <10: use 1.2M format + buf[0] = "0123456789"[v/10]; + buf[1] = '.'; + buf[2] = "0123456789"[v%10]; + } + // see http://en.wikipedia.org/wiki/Tera + buf[3] = " kMGTPEZY"[idx]; + } + buf[4] = '\0'; +} + + // Convert unsigned integer to ascii, writing into supplied buffer. A // truncated result is always null terminated (unless buflen is 0), and // contains the first few digits of the result ala strncpy. +void BUG_sizeof_unsigned_not_4(void); void utoa_to_buf(unsigned n, char *buf, unsigned buflen) { - int i, out = 0; + unsigned i, out, res; + if (sizeof(unsigned) != 4) + BUG_sizeof_unsigned_not_4(); if (buflen) { - for (i=1000000000; i; i/=10) { - int res = n/i; - - if ((res || out || i == 1) && --buflen>0) { + out = 0; + for (i = 1000000000; i; i /= 10) { + res = n / i; + if (res || out || i == 1) { + if (!--buflen) break; out++; n -= res*i; *buf++ = '0' + res; } } - *buf = 0; + *buf = '\0'; } } |