diff options
author | Joel Rosdahl <joel@rosdahl.net> | 2023-02-21 21:34:18 +0100 |
---|---|---|
committer | Joel Rosdahl <joel@rosdahl.net> | 2023-03-04 10:10:20 +0100 |
commit | 66c9c76151497638f1be2bb05ccc2d58d075fc2d (patch) | |
tree | ebafdebf63cccc72fa547376d86d935d5a85ad71 | |
parent | d62b9df5546bee65795188b4e4cbd8dc872887d7 (diff) | |
download | ccache-66c9c76151497638f1be2bb05ccc2d58d075fc2d.tar.gz |
refactor: Move Util::parse_size to util
-rw-r--r-- | src/Config.cpp | 2 | ||||
-rw-r--r-- | src/Util.cpp | 41 | ||||
-rw-r--r-- | src/Util.hpp | 5 | ||||
-rw-r--r-- | src/core/mainoptions.cpp | 4 | ||||
-rw-r--r-- | src/util/string.cpp | 42 | ||||
-rw-r--r-- | src/util/string.hpp | 5 | ||||
-rw-r--r-- | unittest/test_Util.cpp | 27 | ||||
-rw-r--r-- | unittest/test_util_string.cpp | 27 |
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); |