improve human_friendly_bytesize to cope with sizes up to 16 exibytes

This commit is contained in:
Vincent Sanders 2019-10-19 18:20:00 +01:00
parent a54cbb5aea
commit e01c24cef7
4 changed files with 87 additions and 29 deletions

View File

@ -119,6 +119,7 @@ nl.all.FrameDrag:frames aan het aanpassen
# Units
# =====
#
# Decimal prefix
en.all.Bytes: B
de.all.Bytes: B
fr.all.Bytes: octets
@ -139,7 +140,13 @@ de.all.GBytes: GB
fr.all.GBytes: Go
it.all.GBytes: GB
nl.all.GBytes: GB
# Binary prefix
en.all.KiBytes: KiB
en.all.MiBytes: MiB
en.all.GiBytes: GiB
en.all.TiBytes: TiB
en.all.PiBytes: PiB
en.all.EiBytes: EiB
# Content Forms
# =============

View File

@ -37,22 +37,31 @@
#define SLEN(x) (sizeof((x)) - 1)
struct test_pairs {
const unsigned long test;
const unsigned long long int test;
const char* res;
};
static const struct test_pairs human_friendly_bytesize_test_vec[] = {
{ 0, "0.00Bytes" },
{ 1024, "1024.00Bytes" },
{ 1025, "1.00kBytes" },
{ 1048576, "1024.00kBytes" },
{ 1048577, "1.00MBytes" },
{ 1073741824, "1024.00MBytes" },
{ 1073741888, "1024.00MBytes" }, /* spot the rounding error */
{ 1073741889, "1.00GBytes" },
{ 2147483648, "2.00GBytes" },
{ 3221225472, "3.00GBytes" },
{ 4294967295, "4.00GBytes" },
{ 0ULL, "0Bytes" },
{ 0x2AULL, "42Bytes" },
{ 0x400ULL, "1024Bytes" },
{ 0x401ULL, "1.00KiBytes" },
{ 0xA9AEULL, "42.42KiBytes" },
{ 0x100000ULL, "1024.00KiBytes" },
{ 0x100001ULL, "1.00MiBytes" },
{ 0x2A6B852ULL, "42.42MiBytes" },
{ 0x40000000ULL, "1024.00MiBytes" },
{ 0x40000001ULL, "1.00GiBytes" },
{ 0x80000000ULL, "2.00GiBytes" },
{ 0xC0000000ULL, "3.00GiBytes" },
{ 0x100000000ULL, "4.00GiBytes" },
{ 0x10000000000ULL, "1024.00GiBytes" },
{ 0x10000000001ULL, "1.00TiBytes" },
{ 0x4000000000000ULL, "1024.00TiBytes" },
{ 0x4000000000001ULL, "1.00PiBytes" },
{ 0x1000000000000000ULL, "1024.00PiBytes" },
{ 0x1000000000000100ULL, "1.00EiBytes" }, /* precision loss */
{ 0xFFFFFFFFFFFFFFFFULL, "16.00EiBytes" },
};
/**

View File

@ -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);
/**

View File

@ -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;
}
snprintf(curbuffer, BYTESIZE_BUFFER_SIZE, "%3.2f%s", bytesize, messages_get(units[unit]));
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,
fmt,
bytesize,
messages_get(units[unit]));
return curbuffer;
}