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