diff options
-rw-r--r-- | lib/lib.c | 16 | ||||
-rw-r--r-- | lib/lib.h | 1 | ||||
-rwxr-xr-x | tests/demo_number.test | 2 | ||||
-rw-r--r-- | toys/example/demo_number.c | 9 |
4 files changed, 21 insertions, 7 deletions
@@ -1136,17 +1136,17 @@ match: closedir(dp); } -// display first few digits of number with power of two units -int human_readable(char *buf, unsigned long long num, int style) +// display first "dgt" many digits of number plus unit (kilo-exabytes) +int human_readable_long(char *buf, unsigned long long num, int dgt, int style) { unsigned long long snap = 0; int len, unit, divisor = (style&HR_1000) ? 1000 : 1024; // Divide rounding up until we have 3 or fewer digits. Since the part we // print is decimal, the test is 999 even when we divide by 1024. - // We can't run out of units because 2<<64 is 18 exabytes. - // test 5675 is 5.5k not 5.6k. - for (unit = 0; num > 999; unit++) num = ((snap = num)+(divisor/2))/divisor; + // We can't run out of units because 1<<64 is 18 exabytes. + for (unit = 0; snprintf(0, 0, "%llu", num)>dgt; unit++) + num = ((snap = num)+(divisor/2))/divisor; len = sprintf(buf, "%llu", num); if (unit && len == 1) { // Redo rounding for 1.2M case, this works with and without HR_1000. @@ -1168,6 +1168,12 @@ int human_readable(char *buf, unsigned long long num, int style) return len; } +// Give 3 digit estimate + units ala 999M or 1.7T +int human_readable(char *buf, unsigned long long num, int style) +{ + return human_readable_long(buf, num, 3, style); +} + // The qsort man page says you can use alphasort, the posix committee // disagreed, and doubled down: http://austingroupbugs.net/view.php?id=142 // So just do our own. (The const is entirely to humor the stupid compiler.) @@ -269,6 +269,7 @@ void loggit(int priority, char *format, ...); #define HR_SPACE 1 // Space between number and units #define HR_B 2 // Use "B" for single byte units #define HR_1000 4 // Use decimal instead of binary units +int human_readable_long(char *buf, unsigned long long num, int dgt, int style); int human_readable(char *buf, unsigned long long num, int style); // env.c diff --git a/tests/demo_number.test b/tests/demo_number.test index 0d86476f..7ce5d68f 100755 --- a/tests/demo_number.test +++ b/tests/demo_number.test @@ -25,3 +25,5 @@ testcmd "units" "-b 1c 1b 1k 1kd 1m 1md 1g 1gd 1t 1td 1e 1ed" \ testcmd "decimal units" "-d 1c 1b 1k 1kd 1m 1md 1g 1gd 1t 1td 1e 1ed" \ "1\n512\n1.0k\n1.0k\n1.0M\n1.0M\n1.0G\n1.0G\n1.1T\n1.0T\n1.1E\n1.0E\n" \ "" "" + +testcmd "longer output" "-D6 123 1234567 1234567890" "123\n1206K\n1177M\n" "" "" diff --git a/toys/example/demo_number.c b/toys/example/demo_number.c index fce18f11..010320cf 100644 --- a/toys/example/demo_number.c +++ b/toys/example/demo_number.c @@ -2,7 +2,7 @@ * * Copyright 2015 Rob Landley <rob@landley.net> -USE_DEMO_NUMBER(NEWTOY(demo_number, "hdbs", TOYFLAG_BIN)) +USE_DEMO_NUMBER(NEWTOY(demo_number, "D#=3<3hdbs", TOYFLAG_BIN)) config DEMO_NUMBER bool "demo_number" @@ -16,8 +16,13 @@ config DEMO_NUMBER -s Space between number and units (HR_SPACE) */ +#define FOR_demo_number #include "toys.h" +GLOBALS( + long D; +) + void demo_number_main(void) { char **arg; @@ -26,7 +31,7 @@ void demo_number_main(void) long long ll = atolx(*arg); if (toys.optflags) { - human_readable(toybuf, ll, toys.optflags); + human_readable_long(toybuf, ll, TT.D, toys.optflags); xputs(toybuf); } else printf("%lld\n", ll); } |