/* * (C) Copyright 2000-2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include /* * return a pointer to a string containing the size *"as xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB", * xxx GiB, xxx.y GiB, etc as needed; */ char *size_human_readable(unsigned long long size) { static char buf[20]; 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; for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) { if (size >> d) { c = names[i]; break; } } if (!c) { sprintf(buf, "%llu Bytes", size); return buf; } n = size >> d; f = size & ((1ULL << d) - 1); /* If there's a remainder, deal with it */ if (f) { m = (10ULL * f + (1ULL << (d - 1))) >> d; if (m >= 10) { m -= 10; n += 1; } } ptr += sprintf(buf, "%lu", n); if (m) { ptr += sprintf(ptr, ".%lu", m); } sprintf(ptr, " %ciB", c); return buf; } EXPORT_SYMBOL(size_human_readable);