summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rosdahl <joel@rosdahl.net>2023-02-21 21:34:18 +0100
committerJoel Rosdahl <joel@rosdahl.net>2023-03-04 10:10:20 +0100
commit66c9c76151497638f1be2bb05ccc2d58d075fc2d (patch)
treeebafdebf63cccc72fa547376d86d935d5a85ad71
parentd62b9df5546bee65795188b4e4cbd8dc872887d7 (diff)
downloadccache-66c9c76151497638f1be2bb05ccc2d58d075fc2d.tar.gz
refactor: Move Util::parse_size to util
-rw-r--r--src/Config.cpp2
-rw-r--r--src/Util.cpp41
-rw-r--r--src/Util.hpp5
-rw-r--r--src/core/mainoptions.cpp4
-rw-r--r--src/util/string.cpp42
-rw-r--r--src/util/string.hpp5
-rw-r--r--unittest/test_Util.cpp27
-rw-r--r--unittest/test_util_string.cpp27
8 files changed, 77 insertions, 76 deletions
diff --git a/src/Config.cpp b/src/Config.cpp
index 1e554773..bf79acea 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -1037,7 +1037,7 @@ Config::set_item(const std::string& key,
break;
case ConfigItem::max_size:
- m_max_size = Util::parse_size(value);
+ m_max_size = util::value_or_throw<core::Error>(util::parse_size(value));
break;
case ConfigItem::msvc_dep_prefix:
diff --git a/src/Util.cpp b/src/Util.cpp
index c9cf3cbb..6ba1b343 100644
--- a/src/Util.cpp
+++ b/src/Util.cpp
@@ -980,47 +980,6 @@ parse_duration(std::string_view duration)
}
}
-uint64_t
-parse_size(const std::string& value)
-{
- errno = 0;
-
- char* p;
- double result = strtod(value.c_str(), &p);
- if (errno != 0 || result < 0 || p == value.c_str() || value.empty()) {
- throw core::Error(FMT("invalid size: \"{}\"", value));
- }
-
- while (isspace(*p)) {
- ++p;
- }
-
- if (*p != '\0') {
- unsigned multiplier = *(p + 1) == 'i' ? 1024 : 1000;
- switch (*p) {
- case 'T':
- result *= multiplier;
- [[fallthrough]];
- case 'G':
- result *= multiplier;
- [[fallthrough]];
- case 'M':
- result *= multiplier;
- [[fallthrough]];
- case 'K':
- case 'k':
- result *= multiplier;
- break;
- default:
- throw core::Error(FMT("invalid size: \"{}\"", value));
- }
- } else {
- // Default suffix: G.
- result *= 1000 * 1000 * 1000;
- }
- return static_cast<uint64_t>(result);
-}
-
#ifndef _WIN32
std::string
read_link(const std::string& path)
diff --git a/src/Util.hpp b/src/Util.hpp
index 7f7be73e..d1a4796f 100644
--- a/src/Util.hpp
+++ b/src/Util.hpp
@@ -277,11 +277,6 @@ std::string normalize_concrete_absolute_path(const std::string& path);
// into seconds. Throws `core::Error` on error.
uint64_t parse_duration(std::string_view duration);
-// 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. Throws `core::Error` on parse error.
-uint64_t parse_size(const std::string& value);
-
#ifndef _WIN32
// Like readlink(2) but returns the string (or the empty string on failure).
std::string read_link(const std::string& path);
diff --git a/src/core/mainoptions.cpp b/src/core/mainoptions.cpp
index 40db41dc..1fba40db 100644
--- a/src/core/mainoptions.cpp
+++ b/src/core/mainoptions.cpp
@@ -485,7 +485,7 @@ process_main_options(int argc, const char* const* argv)
break;
case TRIM_MAX_SIZE:
- trim_max_size = Util::parse_size(arg);
+ trim_max_size = util::value_or_throw<Error>(util::parse_size(arg));
break;
case TRIM_METHOD:
@@ -657,7 +657,7 @@ process_main_options(int argc, const char* const* argv)
}
case 'M': { // --max-size
- uint64_t size = Util::parse_size(arg);
+ uint64_t size = util::value_or_throw<Error>(util::parse_size(arg));
config.set_value_in_file(config.config_path(), "max_size", arg);
if (size == 0) {
PRINT_RAW(stdout, "Unset cache size limit\n");
diff --git a/src/util/string.cpp b/src/util/string.cpp
index 914f1f74..4ad3decd 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -114,6 +114,48 @@ parse_signed(std::string_view value,
}
}
+nonstd::expected<uint64_t, std::string>
+parse_size(const std::string& value)
+{
+ errno = 0;
+
+ char* p;
+ double result = strtod(value.c_str(), &p);
+ if (errno != 0 || result < 0 || p == value.c_str() || value.empty()) {
+ return nonstd::make_unexpected(FMT("invalid size: \"{}\"", value));
+ }
+
+ while (isspace(*p)) {
+ ++p;
+ }
+
+ if (*p != '\0') {
+ unsigned multiplier = *(p + 1) == 'i' ? 1024 : 1000;
+ switch (*p) {
+ case 'T':
+ result *= multiplier;
+ [[fallthrough]];
+ case 'G':
+ result *= multiplier;
+ [[fallthrough]];
+ case 'M':
+ result *= multiplier;
+ [[fallthrough]];
+ case 'K':
+ case 'k':
+ result *= multiplier;
+ break;
+ default:
+ return nonstd::make_unexpected(FMT("invalid size: \"{}\"", value));
+ }
+ } else {
+ // Default suffix: G.
+ result *= 1000 * 1000 * 1000;
+ }
+
+ return static_cast<uint64_t>(result);
+}
+
nonstd::expected<mode_t, std::string>
parse_umask(std::string_view value)
{
diff --git a/src/util/string.hpp b/src/util/string.hpp
index 5154915d..7df40aad 100644
--- a/src/util/string.hpp
+++ b/src/util/string.hpp
@@ -77,6 +77,11 @@ parse_signed(std::string_view value,
std::optional<int64_t> max_value = std::nullopt,
std::string_view description = "integer");
+// 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.
+nonstd::expected<uint64_t, std::string> parse_size(const std::string& value);
+
// Parse `value` (an octal integer).
nonstd::expected<mode_t, std::string> parse_umask(std::string_view value);
diff --git a/unittest/test_Util.cpp b/unittest/test_Util.cpp
index 9c54e0b4..fd02076b 100644
--- a/unittest/test_Util.cpp
+++ b/unittest/test_Util.cpp
@@ -601,33 +601,6 @@ TEST_CASE("Util::parse_duration")
"invalid suffix (supported: d (day) and s (second)): \"2\"");
}
-TEST_CASE("Util::parse_size")
-{
- CHECK(Util::parse_size("0") == 0);
- CHECK(Util::parse_size("42") // Default suffix: G
- == static_cast<uint64_t>(42) * 1000 * 1000 * 1000);
- CHECK(Util::parse_size("78k") == 78 * 1000);
- CHECK(Util::parse_size("78K") == 78 * 1000);
- CHECK(Util::parse_size("1.1 M") == (int64_t(1.1 * 1000 * 1000)));
- CHECK(Util::parse_size("438.55M") == (int64_t(438.55 * 1000 * 1000)));
- CHECK(Util::parse_size("1 G") == 1 * 1000 * 1000 * 1000);
- CHECK(Util::parse_size("2T")
- == static_cast<uint64_t>(2) * 1000 * 1000 * 1000 * 1000);
- CHECK(Util::parse_size("78 Ki") == 78 * 1024);
- CHECK(Util::parse_size("1.1Mi") == (int64_t(1.1 * 1024 * 1024)));
- CHECK(Util::parse_size("438.55 Mi") == (int64_t(438.55 * 1024 * 1024)));
- CHECK(Util::parse_size("1Gi") == 1 * 1024 * 1024 * 1024);
- CHECK(Util::parse_size("2 Ti")
- == static_cast<uint64_t>(2) * 1024 * 1024 * 1024 * 1024);
-
- CHECK(Util::parse_size("9MB") == 9 * 1000 * 1000);
- CHECK(Util::parse_size("9MiB") == 9 * 1024 * 1024);
-
- CHECK_THROWS_WITH(Util::parse_size(""), "invalid size: \"\"");
- CHECK_THROWS_WITH(Util::parse_size("x"), "invalid size: \"x\"");
- CHECK_THROWS_WITH(Util::parse_size("10x"), "invalid size: \"10x\"");
-}
-
TEST_CASE("Util::remove_extension")
{
CHECK(Util::remove_extension("") == "");
diff --git a/unittest/test_util_string.cpp b/unittest/test_util_string.cpp
index 26fcab24..12746d08 100644
--- a/unittest/test_util_string.cpp
+++ b/unittest/test_util_string.cpp
@@ -183,6 +183,33 @@ TEST_CASE("util::parse_signed")
== "banana must be between 1 and 2");
}
+TEST_CASE("util::parse_size")
+{
+ CHECK(*util::parse_size("0") == 0);
+ CHECK(*util::parse_size("42") // Default suffix: G
+ == static_cast<uint64_t>(42) * 1000 * 1000 * 1000);
+ CHECK(*util::parse_size("78k") == 78 * 1000);
+ CHECK(*util::parse_size("78K") == 78 * 1000);
+ CHECK(*util::parse_size("1.1 M") == (int64_t(1.1 * 1000 * 1000)));
+ CHECK(*util::parse_size("438.55M") == (int64_t(438.55 * 1000 * 1000)));
+ CHECK(*util::parse_size("1 G") == 1 * 1000 * 1000 * 1000);
+ CHECK(*util::parse_size("2T")
+ == static_cast<uint64_t>(2) * 1000 * 1000 * 1000 * 1000);
+ CHECK(*util::parse_size("78 Ki") == 78 * 1024);
+ CHECK(*util::parse_size("1.1Mi") == (int64_t(1.1 * 1024 * 1024)));
+ CHECK(*util::parse_size("438.55 Mi") == (int64_t(438.55 * 1024 * 1024)));
+ CHECK(*util::parse_size("1Gi") == 1 * 1024 * 1024 * 1024);
+ CHECK(*util::parse_size("2 Ti")
+ == static_cast<uint64_t>(2) * 1024 * 1024 * 1024 * 1024);
+
+ CHECK(*util::parse_size("9MB") == 9 * 1000 * 1000);
+ CHECK(*util::parse_size("9MiB") == 9 * 1024 * 1024);
+
+ CHECK(util::parse_size("").error() == "invalid size: \"\"");
+ CHECK(util::parse_size("x").error() == "invalid size: \"x\"");
+ CHECK(util::parse_size("10x").error() == "invalid size: \"10x\"");
+}
+
TEST_CASE("util::parse_umask")
{
CHECK(util::parse_umask("1") == 1U);