From e01c24cef73d2cb70088af1381b90924129a112f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 19 Oct 2019 18:20:00 +0100 Subject: improve human_friendly_bytesize to cope with sizes up to 16 exibytes --- utils/string.h | 2 +- utils/utils.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 16 deletions(-) (limited to 'utils') diff --git a/utils/string.h b/utils/string.h index 03d891700..abb343154 100644 --- a/utils/string.h +++ b/utils/string.h @@ -64,7 +64,7 @@ char *cnv_space2nbsp(const char *s); * @param bytesize The size in bytes. * @return A human readable string representing the size. */ -char *human_friendly_bytesize(unsigned long bytesize); +char *human_friendly_bytesize(unsigned long long int bytesize); /** diff --git a/utils/utils.c b/utils/utils.c index aec0116a0..c5c1529a3 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -192,26 +192,43 @@ nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...) /** * The size of buffers within human_friendly_bytesize. * - * We can have a fairly good estimate of how long the buffer needs to - * be. The unsigned long can store a value representing a maximum - * size of around 4 GB. Therefore the greatest space required is to - * represent 1023MB. Currently that would be represented as "1023MB" - * so 12 including a null terminator. Ideally we would be able to - * know this value for sure, in the mean time the following should - * suffice. + * We can have a fairly good estimate of the output buffers maximum length. + * + * The unsigned long long int can store a value representing a maximum + * size of 16 EiB (exibytes). Therefore the greatest space required is to + * represent 1023 PiB. + * Currently that would be represented as "1023.00PiBytes" in english + * giving a 15 byte length including a null terminator. + * Ideally we would be able to accurately know this length for other + * languages, in the mean time a largeish buffer size is selected + * and should suffice. */ -#define BYTESIZE_BUFFER_SIZE 20 +#define BYTESIZE_BUFFER_SIZE 32 /* exported interface documented in utils/string.h */ -char *human_friendly_bytesize(unsigned long bsize) { +char *human_friendly_bytesize(unsigned long long int bsize) { static char buffer1[BYTESIZE_BUFFER_SIZE]; static char buffer2[BYTESIZE_BUFFER_SIZE]; static char buffer3[BYTESIZE_BUFFER_SIZE]; static char *curbuffer = buffer3; - enum {bytes, kilobytes, megabytes, gigabytes} unit = bytes; - static char units[][7] = {"Bytes", "kBytes", "MBytes", "GBytes"}; - - float bytesize = (float)bsize; + enum { + bytes, + kilobytes, + megabytes, + gibibytes, + tebibytes, + pebibytes, + exbibytes } unit = bytes; + static const char *const units[] = { + "Bytes", + "KiBytes", + "MiBytes", + "GiBytes", + "TiBytes", + "PiBytes", + "EiBytes" }; + double bytesize = (double)bsize; + const char *fmt; if (curbuffer == buffer1) curbuffer = buffer2; @@ -232,10 +249,35 @@ char *human_friendly_bytesize(unsigned long bsize) { if (bytesize > 1024) { bytesize /= 1024; - unit = gigabytes; + unit = gibibytes; + } + + if (bytesize > 1024) { + bytesize /= 1024; + unit = tebibytes; + } + + if (bytesize > 1024) { + bytesize /= 1024; + unit = pebibytes; + } + + if (bytesize > 1024) { + bytesize /= 1024; + unit = exbibytes; + } + + if (unit == bytes) { + fmt = "%.0f%s"; + } else { + fmt = "%3.2f%s"; } - snprintf(curbuffer, BYTESIZE_BUFFER_SIZE, "%3.2f%s", bytesize, messages_get(units[unit])); + snprintf(curbuffer, + BYTESIZE_BUFFER_SIZE, + fmt, + bytesize, + messages_get(units[unit])); return curbuffer; } -- cgit v1.2.3