[ccan] [PATCH 3/3] opt: functions to show integer values with kMGTPE suffixes

Douglas Bagnall douglas at paradise.net.nz
Wed Aug 3 21:44:17 EST 2011


As with the set_ functions, there are twelve permutations of integer size,
base, and signedness.  The supported sizes are int, long, and long long.

For example, this:

 char buf1[OPT_SHOW_LEN];
 char buf2[OPT_SHOW_LEN];
 unsigned i = 1024000;
 opt_show_uintval_bi(buf1, &i);
 opt_show_uintval_si(buf2, &i);

will put "1000k" in buf1, and "1024k" in buf2.

Unlike the opt_set_ functions, these use unsigned arithmetic for unsigned values.

---
 ccan/opt/helpers.c          |  113 +++++++++++++++
 ccan/opt/opt.h              |   18 +++
 ccan/opt/test/run-helpers.c |  328 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 456 insertions(+), 3 deletions(-)

diff --git a/ccan/opt/helpers.c b/ccan/opt/helpers.c
index 2410cea..be6bd18 100644
--- a/ccan/opt/helpers.c
+++ b/ccan/opt/helpers.c
@@ -370,3 +370,116 @@ char * opt_set_uintval_si(const char *arg, unsigned int *u)
 {
 	return set_uint_with_suffix(arg, u, 1000);
 }
+
+/*static helpers for showing values with kMGTPE suffixes.  In this case there
+  are separate but essentially identical functions for signed and unsigned
+  values, so that unsigned values greater than LLONG_MAX get suffixes.
+ */
+static void show_llong_with_suffix(char buf[OPT_SHOW_LEN], long long ll,
+				    const long long base)
+{
+	const char *suffixes = "kMGTPE";
+	int i;
+	if (ll == 0){
+		/*zero is special because everything divides it (you'd get "0E")*/
+		snprintf(buf, OPT_SHOW_LEN, "0");
+		return;
+	}
+	for (i = 0; i < sizeof(suffixes); i++){
+		long long tmp = ll / base;
+		if (tmp * base != ll)
+			break;
+		ll = tmp;
+	}
+	if (i == 0)
+		snprintf(buf, OPT_SHOW_LEN, "%lld", ll);
+	else
+		snprintf(buf, OPT_SHOW_LEN, "%lld%c", ll, suffixes[i - 1]);
+}
+
+static void show_ullong_with_suffix(char buf[OPT_SHOW_LEN], unsigned long long ull,
+				    const unsigned base)
+{
+	const char *suffixes = "kMGTPE";
+	int i;
+	if (ull == 0){
+		/*zero is special because everything divides it (you'd get "0E")*/
+		snprintf(buf, OPT_SHOW_LEN, "0");
+		return;
+	}
+	for (i = 0; i < sizeof(suffixes); i++){
+		unsigned long long tmp = ull / base;
+		if (tmp * base != ull)
+			break;
+		ull = tmp;
+	}
+	if (i == 0)
+		snprintf(buf, OPT_SHOW_LEN, "%llu", ull);
+	else
+		snprintf(buf, OPT_SHOW_LEN, "%llu%c", ull, suffixes[i - 1]);
+}
+
+/* _bi, signed */
+void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x)
+{
+	show_llong_with_suffix(buf, *x, 1024);
+}
+
+void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x)
+{
+	show_llong_with_suffix(buf, *x, 1024);
+}
+
+void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x)
+{
+	show_llong_with_suffix(buf, *x, 1024);
+}
+
+/* _bi, unsigned */
+void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
+}
+
+void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
+}
+
+void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1024);
+}
+
+/* _si, signed */
+void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x)
+{
+	show_llong_with_suffix(buf, (long long) *x, 1000);
+}
+
+void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x)
+{
+	show_llong_with_suffix(buf, (long long) *x, 1000);
+}
+
+void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x)
+{
+	show_llong_with_suffix(buf, *x, 1000);
+}
+
+/* _si, unsigned */
+void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
+}
+
+void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
+}
+
+void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x)
+{
+	show_ullong_with_suffix(buf, (unsigned long long) *x, 1000);
+}
+
diff --git a/ccan/opt/opt.h b/ccan/opt/opt.h
index 7049fff..550c342 100644
--- a/ccan/opt/opt.h
+++ b/ccan/opt/opt.h
@@ -297,6 +297,24 @@ char *opt_set_longlongval_si(const char *arg, long long *ll);
 char *opt_set_ulonglongval_bi(const char *arg, unsigned long long *ll);
 char *opt_set_ulonglongval_si(const char *arg, unsigned long long *ll);
 
+
+void opt_show_intval_bi(char buf[OPT_SHOW_LEN], const int *x);
+void opt_show_longval_bi(char buf[OPT_SHOW_LEN], const long *x);
+void opt_show_longlongval_bi(char buf[OPT_SHOW_LEN], const long long *x);
+void opt_show_uintval_bi(char buf[OPT_SHOW_LEN], const unsigned int *x);
+void opt_show_ulongval_bi(char buf[OPT_SHOW_LEN], const unsigned long *x);
+void opt_show_ulonglongval_bi(char buf[OPT_SHOW_LEN], const unsigned long long *x);
+
+void opt_show_intval_si(char buf[OPT_SHOW_LEN], const int *x);
+void opt_show_longval_si(char buf[OPT_SHOW_LEN], const long *x);
+void opt_show_longlongval_si(char buf[OPT_SHOW_LEN], const long long *x);
+void opt_show_uintval_si(char buf[OPT_SHOW_LEN], const unsigned int *x);
+void opt_show_ulongval_si(char buf[OPT_SHOW_LEN], const unsigned long *x);
+void opt_show_ulonglongval_si(char buf[OPT_SHOW_LEN], const unsigned long long *x);
+
+
+
+
 /* Increment. */
 char *opt_inc_intval(int *i);
 
diff --git a/ccan/opt/test/run-helpers.c b/ccan/opt/test/run-helpers.c
index d5cafdf..785ddae 100644
--- a/ccan/opt/test/run-helpers.c
+++ b/ccan/opt/test/run-helpers.c
@@ -59,7 +59,7 @@ static int saved_printf(const char *fmt, ...)
 	ret = saved_vprintf(fmt, ap);
 	va_end(ap);
 	return ret;
-}	
+}
 
 static int saved_fprintf(FILE *ignored, const char *fmt, ...)
 {
@@ -70,7 +70,7 @@ static int saved_fprintf(FILE *ignored, const char *fmt, ...)
 	ret = saved_vprintf(fmt, ap);
 	va_end(ap);
 	return ret;
-}	
+}
 
 #undef malloc
 static void *last_allocation;
@@ -82,7 +82,7 @@ static void *saved_malloc(size_t size)
 /* Test helpers. */
 int main(int argc, char *argv[])
 {
-	plan_tests(334);
+	plan_tests(452);
 
 	/* opt_set_bool */
 	{
@@ -421,6 +421,167 @@ int main(int argc, char *argv[])
 			ok1(parse_args(&argc, &argv, "-a", "8191P", NULL));
 			ok1(arg == 8191 * P);
 		}
+
+		/* opt_show_intval_bi */
+		{
+			int i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -77;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "-77") == 0);
+			i = 0;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 77;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -1234 * k;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "-1234k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * M;
+			opt_show_intval_bi(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_longval_bi */
+		{
+			long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -77;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "-77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 77;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -1 * k;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "-1k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * M;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 0;
+			opt_show_longval_bi(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_llongval_bi */
+		{
+			long long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -7777;
+			opt_show_longlongval_bi(buf, &i);
+			ok1(strcmp(buf, "-7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 7777;
+			opt_show_longlongval_bi(buf, &i);
+			ok1(strcmp(buf, "7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -10240000 * k;
+			opt_show_longlongval_bi(buf, &i);
+			ok1(strcmp(buf, "-10000M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 5 * P;
+			opt_show_longlongval_bi(buf, &i);
+			ok1(strcmp(buf, "5P") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * P;
+			opt_show_longlongval_bi(buf, &i);
+			ok1(strcmp(buf, "1E") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_uintval_bi */
+		{
+			unsigned int i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 77;
+			opt_show_uintval_bi(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1234 * k;
+			opt_show_uintval_bi(buf, &i);
+			ok1(strcmp(buf, "1234k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_uintval_bi(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * M;
+			opt_show_uintval_bi(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_ulongval_bi */
+		{
+			unsigned long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 77;
+			opt_show_ulongval_bi(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = k;
+			opt_show_ulongval_bi(buf, &i);
+			ok1(strcmp(buf, "1k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_ulongval_bi(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * M;
+			opt_show_ulongval_bi(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 0;
+			opt_show_ulongval_bi(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_ullongval_bi */
+		{
+			long long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 7777;
+			opt_show_ulonglongval_bi(buf, &i);
+			ok1(strcmp(buf, "7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 10240000 * k;
+			opt_show_ulonglongval_bi(buf, &i);
+			ok1(strcmp(buf, "10000M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 5 * P;
+			opt_show_ulonglongval_bi(buf, &i);
+			ok1(strcmp(buf, "5P") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * P;
+			opt_show_ulonglongval_bi(buf, &i);
+			ok1(strcmp(buf, "1E") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
 	}
 
 	{
@@ -645,6 +806,167 @@ int main(int argc, char *argv[])
 			ok1(!parse_args(&argc, &argv, "-a", "-100G", NULL));
 			ok1(parse_args(&argc, &argv, "-a", "8E", NULL));
 		}
+		/* opt_show_intval_si */
+		{
+			int i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -77;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "-77") == 0);
+			i = 0;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 77;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -1234 * k;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "-1234k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1000 * M;
+			opt_show_intval_si(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_longval_si */
+		{
+			long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -77;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "-77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 77;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -1 * k;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "-1k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1000 * M;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 0;
+			opt_show_longval_si(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_llongval_si */
+		{
+			long long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = -7777;
+			opt_show_longlongval_si(buf, &i);
+			ok1(strcmp(buf, "-7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 7777;
+			opt_show_longlongval_si(buf, &i);
+			ok1(strcmp(buf, "7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = -10240000 * k;
+			opt_show_longlongval_si(buf, &i);
+			ok1(strcmp(buf, "-10240M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 5 * P;
+			opt_show_longlongval_si(buf, &i);
+			ok1(strcmp(buf, "5P") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 2000 * P;
+			opt_show_longlongval_si(buf, &i);
+			ok1(strcmp(buf, "2E") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_uintval_si */
+		{
+			unsigned int i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 77;
+			opt_show_uintval_si(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1234 * k;
+			opt_show_uintval_si(buf, &i);
+			ok1(strcmp(buf, "1234k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_uintval_si(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1000 * M;
+			opt_show_uintval_si(buf, &i);
+			ok1(strcmp(buf, "1G") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_ulongval_si */
+		{
+			unsigned long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 77;
+			opt_show_ulongval_si(buf, &i);
+			ok1(strcmp(buf, "77") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = k;
+			opt_show_ulongval_si(buf, &i);
+			ok1(strcmp(buf, "1k") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 500 * M;
+			opt_show_ulongval_si(buf, &i);
+			ok1(strcmp(buf, "500M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1024 * M;
+			opt_show_ulongval_si(buf, &i);
+			ok1(strcmp(buf, "1024M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 0;
+			opt_show_ulongval_si(buf, &i);
+			ok1(strcmp(buf, "0") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
+		/* opt_show_ullongval_si */
+		{
+			long long i;
+			char buf[OPT_SHOW_LEN+2] = { 0 };
+			buf[OPT_SHOW_LEN] = '!';
+			i = 7777;
+			opt_show_ulonglongval_si(buf, &i);
+			ok1(strcmp(buf, "7777") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 10240000 * k;
+			opt_show_ulonglongval_si(buf, &i);
+			ok1(strcmp(buf, "10240M") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 5 * P;
+			opt_show_ulonglongval_si(buf, &i);
+			ok1(strcmp(buf, "5P") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+			i = 1000 * P;
+			opt_show_ulonglongval_si(buf, &i);
+			ok1(strcmp(buf, "1E") == 0);
+			ok1(buf[OPT_SHOW_LEN] == '!');
+		}
+
 	}
 
 
-- 
1.7.4.1



More information about the ccan mailing list