summaryrefslogtreecommitdiffstats
path: root/lib/display_options.c
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2012-12-17 16:48:25 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2012-12-19 10:30:56 +0100
commit4f03bc5d9fd06f0c3f58e674356b75e2830414b7 (patch)
tree4e2a6d0cad229c58e28f703abc21b21544467085 /lib/display_options.c
parent904adb80d40eed1d6b527290714b233e8c37cb35 (diff)
downloadbarebox-4f03bc5d9fd06f0c3f58e674356b75e2830414b7.tar.gz
barebox-4f03bc5d9fd06f0c3f58e674356b75e2830414b7.tar.xz
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 <w.sang@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib/display_options.c')
-rw-r--r--lib/display_options.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/lib/display_options.c b/lib/display_options.c
index a6050cbf4f..0871552aaa 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;
}