From 4f03bc5d9fd06f0c3f58e674356b75e2830414b7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 17 Dec 2012 16:48:25 +0100 Subject: lib: update size_human_readable to latest version Copy over the latest version from u-boot which handles bigger sizes now and does arithmetic with shifts instead of divisions. Signed-off-by: Wolfram Sang Signed-off-by: Sascha Hauer --- lib/display_options.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/display_options.c b/lib/display_options.c index a6050cbf4..0871552aa 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -21,35 +21,50 @@ /* * return a pointer to a string containing the size - * as "xxx kB", "xxx.y kB", "xxx MB" or "xxx.y MB" as needed; + *"as xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", + * xxx GiB, xxx.y GiB, etc as needed; */ -char *size_human_readable(ulong size) +char *size_human_readable(unsigned long long size) { static char buf[20]; - ulong m, n; - ulong d = 1 << 20; /* 1 MB */ - char c = 'M'; + unsigned long m = 0, n; + unsigned long long f; + static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'}; + unsigned long d = 10 * ARRAY_SIZE(names); + char c = 0; + unsigned int i; char *ptr = buf; - if (size < d) { /* print in kB */ - c = 'k'; - d = 1 << 10; + for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { + if (size >> d) { + c = names[i]; + break; + } } - n = size / d; + if (!c) { + sprintf(buf, "%llu Bytes", size); + return buf; + } + + n = size >> d; + f = size & ((1ULL << d) - 1); - m = (10 * (size - (n * d)) + (d / 2) ) / d; + /* If there's a remainder, deal with it */ + if (f) { + m = (10ULL * f + (1ULL << (d - 1))) >> d; - if (m >= 10) { - m -= 10; - n += 1; + if (m >= 10) { + m -= 10; + n += 1; + } } - ptr += sprintf(buf, "%2ld", n); + ptr += sprintf(buf, "%lu", n); if (m) { - ptr += sprintf (ptr,".%ld", m); + ptr += sprintf(ptr, ".%ld", m); } - sprintf(ptr, " %cB", c); + sprintf(ptr, " %ciB", c); return buf; } -- cgit v1.2.3