From: Joel Rosdahl Date: Mon, 25 Jul 2011 21:48:23 +0000 (+0200) Subject: Let k/M/G/T be 10-based suffixes and introduce 2-based Ki/Mi/Gi/Ti as well X-Git-Tag: v3.2~192 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a36847b655b449836faf6122f6d2603a510f3227;p=thirdparty%2Fccache.git Let k/M/G/T be 10-based suffixes and introduce 2-based Ki/Mi/Gi/Ti as well --- diff --git a/conf.c b/conf.c index d1ac50297..5d6b802b7 100644 --- a/conf.c +++ b/conf.c @@ -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; diff --git a/stats.c b/stats.c index a7b239ff0..595688a80 100644 --- a/stats.c +++ b/stats.c @@ -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); } diff --git a/test.sh b/test.sh index ad73b0db4..14952c6d7 100755 --- a/test.sh +++ b/test.sh @@ -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' } ###################################################################### diff --git a/test/test_conf.c b/test/test_conf.c index 83c1b696b..3d687a0ae 100644 --- a/test/test_conf.c +++ b/test/test_conf.c @@ -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); diff --git a/test/test_util.c b/test/test_util.c index 0d9319170..6668c8649 100644 --- a/test/test_util.c +++ b/test/test_util.c @@ -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 diff --git a/util.c b/util.c index 74e9646e3..ebe90f948 100644 --- a/util.c +++ b/util.c @@ -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; + } + + 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 * 1024; + *size = x; return true; }