Let k/M/G/T be 10-based suffixes and introduce 2-based Ki/Mi/Gi/Ti as well

This commit is contained in:
Joel Rosdahl 2011-07-25 23:48:23 +02:00
parent cadd1e1793
commit a36847b655
6 changed files with 96 additions and 70 deletions

2
conf.c
View File

@ -426,7 +426,7 @@ conf_create(void)
conf->hash_dir = false;
conf->log_file = x_strdup("");
conf->max_files = 0;
conf->max_size = 1024 * 1024 * 1024;
conf->max_size = 1000 * 1000 * 1000;
conf->path = x_strdup("");
conf->prefix_command = x_strdup("");
conf->read_only = false;

View File

@ -87,7 +87,7 @@ static void
display_size(uint64_t size)
{
char *s = format_human_readable_size(size);
printf("%15s", s);
printf("%11s", s);
free(s);
}

View File

@ -1795,7 +1795,7 @@ upgrade_suite() {
mkdir -p $CCACHE_DIR/0
echo "0 0 0 0 0 0 0 0 0 0 0 0 0 2000 131072" >$CCACHE_DIR/0/stats
checkstat 'max files' 32000
checkstat 'max cache size' '2.0 Gbytes'
checkstat 'max cache size' '2.1 GB'
}
######################################################################

View File

@ -53,7 +53,7 @@ TEST(conf_create)
CHECK(!conf->hash_dir);
CHECK_STR_EQ("", conf->log_file);
CHECK_INT_EQ(0, conf->max_files);
CHECK_INT_EQ(1024 * 1024 * 1024, conf->max_size);
CHECK_INT_EQ(1000 * 1000 * 1000, conf->max_size);
CHECK_STR_EQ("", conf->path);
CHECK_STR_EQ("", conf->prefix_command);
CHECK(!conf->read_only);
@ -123,7 +123,7 @@ TEST(conf_read_valid_config)
CHECK(conf->hash_dir);
CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file);
CHECK_INT_EQ(17, conf->max_files);
CHECK_INT_EQ(123 * 1024 * 1024, conf->max_size);
CHECK_INT_EQ(123 * 1000 * 1000, conf->max_size);
CHECK_STR_EQ_FREE1(format("%s.x", user), conf->path);
CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command);
CHECK(conf->read_only);

View File

@ -96,50 +96,61 @@ TEST(subst_env_in_string)
TEST(format_human_readable_size)
{
CHECK_STR_EQ_FREE2("0 bytes", format_human_readable_size(0));
CHECK_STR_EQ_FREE2("42.0 Kbytes", format_human_readable_size(42 * 1024));
CHECK_STR_EQ_FREE2("1.0 Mbytes", format_human_readable_size(1024 * 1024));
CHECK_STR_EQ_FREE2("1.2 Mbytes", format_human_readable_size(1234 * 1024));
CHECK_STR_EQ_FREE2("438.5 Mbytes",
format_human_readable_size(438.5 * 1024 * 1024));
CHECK_STR_EQ_FREE2("1.0 Gbytes",
format_human_readable_size(1024 * 1024 * 1024));
CHECK_STR_EQ_FREE2("17.1 Gbytes",
format_human_readable_size(17.11 * 1024 * 1024 * 1024));
CHECK_STR_EQ_FREE2("0", format_human_readable_size(0));
CHECK_STR_EQ_FREE2("1 B", format_human_readable_size(1));
CHECK_STR_EQ_FREE2("42.0 kB", format_human_readable_size(42 * 1000));
CHECK_STR_EQ_FREE2("1.0 MB", format_human_readable_size(1000 * 1000));
CHECK_STR_EQ_FREE2("1.2 MB", format_human_readable_size(1234 * 1000));
CHECK_STR_EQ_FREE2("438.5 MB",
format_human_readable_size(438.5 * 1000 * 1000));
CHECK_STR_EQ_FREE2("1.0 GB",
format_human_readable_size(1000 * 1000 * 1000));
CHECK_STR_EQ_FREE2("17.1 GB",
format_human_readable_size(17.11 * 1000 * 1000 * 1000));
}
TEST(format_parsable_size_with_suffix)
{
CHECK_STR_EQ_FREE2("0", format_parsable_size_with_suffix(0));
CHECK_STR_EQ_FREE2("42.0K", format_parsable_size_with_suffix(42 * 1024));
CHECK_STR_EQ_FREE2("1.0M", format_parsable_size_with_suffix(1024 * 1024));
CHECK_STR_EQ_FREE2("1.2M", format_parsable_size_with_suffix(1234 * 1024));
CHECK_STR_EQ_FREE2("42.0k", format_parsable_size_with_suffix(42 * 1000));
CHECK_STR_EQ_FREE2("1.0M", format_parsable_size_with_suffix(1000 * 1000));
CHECK_STR_EQ_FREE2("1.2M", format_parsable_size_with_suffix(1234 * 1000));
CHECK_STR_EQ_FREE2("438.5M",
format_parsable_size_with_suffix(438.5 * 1024 * 1024));
format_parsable_size_with_suffix(438.5 * 1000 * 1000));
CHECK_STR_EQ_FREE2("1.0G",
format_parsable_size_with_suffix(1024 * 1024 * 1024));
format_parsable_size_with_suffix(1000 * 1000 * 1000));
CHECK_STR_EQ_FREE2(
"17.1G",
format_parsable_size_with_suffix(17.11 * 1024 * 1024 * 1024));
format_parsable_size_with_suffix(17.11 * 1000 * 1000 * 1000));
}
TEST(parse_size_with_suffix)
{
uint64_t size;
CHECK(parse_size_with_suffix("0", &size));
CHECK_INT_EQ(0, size);
CHECK(parse_size_with_suffix("42K", &size));
CHECK_INT_EQ(42 * 1024, size);
CHECK(parse_size_with_suffix("1.0M", &size));
CHECK_INT_EQ(1024 * 1024, size);
CHECK(parse_size_with_suffix("1.1M", &size));
CHECK_INT_EQ(1.1 * 1024 * 1024, size);
CHECK(parse_size_with_suffix("438.5M", &size));
CHECK_INT_EQ(438.5 * 1024 * 1024, size);
CHECK(parse_size_with_suffix("1.0G", &size));
CHECK_INT_EQ(1024 * 1024 * 1024, size);
CHECK(parse_size_with_suffix("17.1G", &size));
CHECK_INT_EQ(17.1 * 1024 * 1024 * 1024, size);
size_t size;
size_t i;
struct { const char *size; int64_t expected; } sizes[] = {
{"0", 0},
{"42", 42},
{"78k", 78 * 1000},
{"78K", 78 * 1000},
{"1.1 M", 1.1 * 1000 * 1000},
{"438.55M", 438.55 * 1000 * 1000},
{"1 G", 1 * 1000 * 1000 * 1000},
{"2T", 2L * 1000 * 1000 * 1000 * 1000},
{"78 Ki", 78 * 1024},
{"1.1Mi", 1.1 * 1024 * 1024},
{"438.55 Mi", 438.55 * 1024 * 1024},
{"1Gi", 1 * 1024 * 1024 * 1024},
{"2 Ti", 2L * 1024 * 1024 * 1024 * 1024},
};
for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); ++i) {
CHECKM(parse_size_with_suffix(sizes[i].size, &size), sizes[i].size);
CHECK_INT_EQ(sizes[i].expected, size);
}
}
TEST_SUITE_END

83
util.c
View File

@ -819,29 +819,31 @@ char *
format_human_readable_size(uint64_t v)
{
char *s;
if (v >= 1024*1024*1024) {
s = format("%.1f Gbytes", v/((double)(1024*1024*1024)));
} else if (v >= 1024*1024) {
s = format("%.1f Mbytes", v/((double)(1024*1024)));
} else if (v >= 1024) {
s = format("%.1f Kbytes", v/((double)(1024)));
if (v >= 1000*1000*1000) {
s = format("%.1f GB", v/((double)(1000*1000*1000)));
} else if (v >= 1000*1000) {
s = format("%.1f MB", v/((double)(1000*1000)));
} else if (v >= 1000) {
s = format("%.1f kB", v/((double)(1000)));
} else if (v > 0) {
s = format("%u B", (unsigned)v);
} else {
s = format("%u bytes", (unsigned)v);
s = x_strdup("0");
}
return s;
}
/* Format a size (in KiB) as a human-readable string. Caller frees. */
/* Format a size as a parsable string. Caller frees. */
char *
format_parsable_size_with_suffix(uint64_t size)
{
char *s;
if (size >= 1024*1024*1024) {
s = format("%.1fG", size / ((double)(1024*1024*1024)));
} else if (size >= 1024*1024) {
s = format("%.1fM", size / ((double)(1024*1024)));
} else if (size >= 1024) {
s = format("%.1fK", size / ((double)(1024)));
if (size >= 1000*1000*1000) {
s = format("%.1fG", size / ((double)(1000*1000*1000)));
} else if (size >= 1000*1000) {
s = format("%.1fM", size / ((double)(1000*1000)));
} else if (size >= 1000) {
s = format("%.1fk", size / ((double)(1000)));
} else {
s = format("%u", (unsigned)size);
}
@ -849,36 +851,49 @@ format_parsable_size_with_suffix(uint64_t size)
}
/*
* Parse a value given a string that can end in K, M or G. Default suffix: G.
* Parse a "size value", i.e. a string that can end in k, M, G, T (10-based
* suffixes) or Ki, Mi, Gi, Ti (2-based suffixes). For backward compatibility,
* K is also recognized as a synonym of k.
*/
bool
parse_size_with_suffix(const char *str, uint64_t *size)
{
char *endptr;
char *p;
double x;
errno = 0;
x = strtod(str, &endptr);
if (errno != 0 || x < 0 || endptr == str || *str == '\0') {
x = strtod(str, &p);
if (errno != 0 || x < 0 || p == str || *str == '\0') {
return false;
}
switch (*endptr) {
case 'G':
case 'g':
case '\0':
x *= 1024 * 1024;
break;
case 'M':
case 'm':
x *= 1024;
break;
case 'K':
case 'k':
break;
default:
return false;
while (isspace(*p)) {
++p;
}
*size = x * 1024;
if (*p != '\0') {
unsigned multiplier;
if (*(p+1) == 'i') {
multiplier = 1024;
} else {
multiplier = 1000;
}
switch (*p) {
case 'T':
x *= multiplier;
case 'G':
x *= multiplier;
case 'M':
x *= multiplier;
case 'K':
case 'k':
x *= multiplier;
break;
default:
return false;
}
}
*size = x;
return true;
}