}
}
-unsigned
-parse_unsigned(const std::string& value)
-{
- size_t end;
- long result;
- bool failed = false;
- try {
- result = std::stol(value, &end, 10);
- } catch (std::exception&) {
- failed = true;
- }
- if (failed || end != value.size() || result < 0) {
- throw Error(fmt::format("invalid unsigned integer: \"{}\"", value));
- }
- return result;
-}
-
void
verify_absolute_path(const std::string& value)
{
break;
case ConfigItem::cache_dir_levels:
- m_cache_dir_levels = parse_unsigned(value);
+ m_cache_dir_levels = Util::parse_uint32(value);
if (m_cache_dir_levels < 1 || m_cache_dir_levels > 8) {
throw Error("cache directory levels must be between 1 and 8");
}
break;
case ConfigItem::max_files:
- m_max_files = parse_unsigned(value);
+ m_max_files = Util::parse_uint32(value);
break;
case ConfigItem::max_size:
return result;
}
+uint32_t
+parse_uint32(const std::string& value)
+{
+ size_t end;
+ long long result;
+ bool failed = false;
+ try {
+ result = std::stoll(value, &end, 10);
+ } catch (std::exception&) {
+ failed = true;
+ }
+ if (failed || end != value.size() || result < 0
+ || result > std::numeric_limits<uint32_t>::max()) {
+ throw Error(fmt::format("invalid 32-bit unsigned integer: \"{}\"", value));
+ }
+ return result;
+}
+
std::string
read_file(const std::string& path, size_t size_hint)
{
// Throws `Error` if parse value is <0
unsigned parse_duration_with_suffix_to_seconds(const std::string& value);
-// Parse a string into an integer.
+// Parse a string into a signed integer.
//
-// Throws Error on error.
+// Throws `Error` on error.
int parse_int(const std::string& value);
+// Parse a string into an unsigned 32-bit integer.
+//
+// Throws `Error` on error.
+uint32_t parse_uint32(const std::string& value);
+
// Return `path`'s content as a string. If `size_hint` is not 0 then assume that
// `path` has this size (this saves system calls).
//
{
Util::write_file("ccache.conf", "max_files =");
REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
- "ccache.conf:1: invalid unsigned integer: \"\"");
+ "ccache.conf:1: invalid 32-bit unsigned integer: \"\"");
Util::write_file("ccache.conf", "max_files = -42");
- REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
- "ccache.conf:1: invalid unsigned integer: \"-42\"");
+ REQUIRE_THROWS_WITH(
+ config.update_from_file("ccache.conf"),
+ "ccache.conf:1: invalid 32-bit unsigned integer: \"-42\"");
Util::write_file("ccache.conf", "max_files = foo");
- REQUIRE_THROWS_WITH(config.update_from_file("ccache.conf"),
- "ccache.conf:1: invalid unsigned integer: \"foo\"");
+ REQUIRE_THROWS_WITH(
+ config.update_from_file("ccache.conf"),
+ "ccache.conf:1: invalid 32-bit unsigned integer: \"foo\"");
}
SUBCASE("missing file")
}
}
+TEST_CASE("Util::parse_uint32")
+{
+ CHECK(Util::parse_uint32("0") == 0);
+ CHECK(Util::parse_uint32("2") == 2);
+ CHECK(Util::parse_uint32("42") == 42);
+ CHECK(Util::parse_uint32("0666") == 666);
+ CHECK(Util::parse_uint32(" 777") == 777);
+
+ CHECK_THROWS_WITH(Util::parse_uint32(""),
+ "invalid 32-bit unsigned integer: \"\"");
+ CHECK_THROWS_WITH(Util::parse_uint32("x"),
+ "invalid 32-bit unsigned integer: \"x\"");
+ CHECK_THROWS_WITH(Util::parse_uint32("0x"),
+ "invalid 32-bit unsigned integer: \"0x\"");
+ CHECK_THROWS_WITH(Util::parse_uint32("0x4"),
+ "invalid 32-bit unsigned integer: \"0x4\"");
+ CHECK_THROWS_WITH(Util::parse_uint32("0 "),
+ "invalid 32-bit unsigned integer: \"0 \"");
+
+ // check boundary values
+ CHECK(Util::parse_uint32("4294967295") == 4294967295);
+ CHECK_THROWS_WITH(Util::parse_uint32("-1"),
+ "invalid 32-bit unsigned integer: \"-1\"");
+ CHECK_THROWS_WITH(Util::parse_uint32("4294967296"),
+ "invalid 32-bit unsigned integer: \"4294967296\"");
+}
+
TEST_CASE("Util::read_file and Util::write_file")
{
TestContext test_context;