diff options
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/xfuncs.c | 60 | ||||
-rw-r--r-- | miscutils/nmeter.c | 36 |
3 files changed, 56 insertions, 41 deletions
diff --git a/include/libbb.h b/include/libbb.h index 6074331..8c1d784 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -278,6 +278,7 @@ extern FILE *fopen_or_warn(const char *filename, const char *mode); extern FILE *fopen_or_warn_stdin(const char *filename); +extern void smart_ulltoa5(unsigned long long ul, char buf[5]); extern void utoa_to_buf(unsigned n, char *buf, unsigned buflen); extern char *utoa(unsigned n); extern void itoa_to_buf(int n, char *buf, unsigned buflen); diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index c722650..352515a 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'; } } diff --git a/miscutils/nmeter.c b/miscutils/nmeter.c index d71bd6a..326d7b8 100644 --- a/miscutils/nmeter.c +++ b/miscutils/nmeter.c @@ -214,42 +214,8 @@ static int rdval_diskstats(const char* p, ullong *vec) static void scale(ullong ul) { - char *fmt; char buf[5]; - 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'; + smart_ulltoa5(ul, buf); put(buf); } |