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->hash_dir = false;
conf->log_file = x_strdup(""); conf->log_file = x_strdup("");
conf->max_files = 0; conf->max_files = 0;
conf->max_size = 1024 * 1024 * 1024; conf->max_size = 1000 * 1000 * 1000;
conf->path = x_strdup(""); conf->path = x_strdup("");
conf->prefix_command = x_strdup(""); conf->prefix_command = x_strdup("");
conf->read_only = false; conf->read_only = false;

View File

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

View File

@ -1795,7 +1795,7 @@ upgrade_suite() {
mkdir -p $CCACHE_DIR/0 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 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 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(!conf->hash_dir);
CHECK_STR_EQ("", conf->log_file); CHECK_STR_EQ("", conf->log_file);
CHECK_INT_EQ(0, conf->max_files); 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->path);
CHECK_STR_EQ("", conf->prefix_command); CHECK_STR_EQ("", conf->prefix_command);
CHECK(!conf->read_only); CHECK(!conf->read_only);
@ -123,7 +123,7 @@ TEST(conf_read_valid_config)
CHECK(conf->hash_dir); CHECK(conf->hash_dir);
CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file); CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file);
CHECK_INT_EQ(17, conf->max_files); 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("%s.x", user), conf->path);
CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command); CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command);
CHECK(conf->read_only); CHECK(conf->read_only);

View File

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

83
util.c
View File

@ -819,29 +819,31 @@ char *
format_human_readable_size(uint64_t v) format_human_readable_size(uint64_t v)
{ {
char *s; char *s;
if (v >= 1024*1024*1024) { if (v >= 1000*1000*1000) {
s = format("%.1f Gbytes", v/((double)(1024*1024*1024))); s = format("%.1f GB", v/((double)(1000*1000*1000)));
} else if (v >= 1024*1024) { } else if (v >= 1000*1000) {
s = format("%.1f Mbytes", v/((double)(1024*1024))); s = format("%.1f MB", v/((double)(1000*1000)));
} else if (v >= 1024) { } else if (v >= 1000) {
s = format("%.1f Kbytes", v/((double)(1024))); s = format("%.1f kB", v/((double)(1000)));
} else if (v > 0) {
s = format("%u B", (unsigned)v);
} else { } else {
s = format("%u bytes", (unsigned)v); s = x_strdup("0");
} }
return s; return s;
} }
/* Format a size (in KiB) as a human-readable string. Caller frees. */ /* Format a size as a parsable string. Caller frees. */
char * char *
format_parsable_size_with_suffix(uint64_t size) format_parsable_size_with_suffix(uint64_t size)
{ {
char *s; char *s;
if (size >= 1024*1024*1024) { if (size >= 1000*1000*1000) {
s = format("%.1fG", size / ((double)(1024*1024*1024))); s = format("%.1fG", size / ((double)(1000*1000*1000)));
} else if (size >= 1024*1024) { } else if (size >= 1000*1000) {
s = format("%.1fM", size / ((double)(1024*1024))); s = format("%.1fM", size / ((double)(1000*1000)));
} else if (size >= 1024) { } else if (size >= 1000) {
s = format("%.1fK", size / ((double)(1024))); s = format("%.1fk", size / ((double)(1000)));
} else { } else {
s = format("%u", (unsigned)size); 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 bool
parse_size_with_suffix(const char *str, uint64_t *size) parse_size_with_suffix(const char *str, uint64_t *size)
{ {
char *endptr; char *p;
double x; double x;
errno = 0; errno = 0;
x = strtod(str, &endptr); x = strtod(str, &p);
if (errno != 0 || x < 0 || endptr == str || *str == '\0') { if (errno != 0 || x < 0 || p == str || *str == '\0') {
return false; return false;
} }
switch (*endptr) { while (isspace(*p)) {
case 'G': ++p;
case 'g':
case '\0':
x *= 1024 * 1024;
break;
case 'M':
case 'm':
x *= 1024;
break;
case 'K':
case 'k':
break;
default:
return false;
} }
*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; return true;
} }