config_parser: Add common boolean parser
This more accurately parses systemd values instead of just comparing to
"false" or "true".
Change-Id: I0d70ef418075d555bf6f090fefa0b34332491ed0
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/config_parser.cpp b/src/config_parser.cpp
index 1d8371d..b684fa2 100644
--- a/src/config_parser.cpp
+++ b/src/config_parser.cpp
@@ -14,6 +14,29 @@
namespace config
{
+using std::literals::string_view_literals::operator""sv;
+
+bool icaseeq(std::string_view in, std::string_view expected) noexcept
+{
+ return std::equal(in.begin(), in.end(), expected.begin(), expected.end(),
+ [](auto a, auto b) { return tolower(a) == b; });
+}
+
+std::optional<bool> parseBool(std::string_view in) noexcept
+{
+ if (in == "1"sv || icaseeq(in, "yes"sv) || icaseeq(in, "y"sv) ||
+ icaseeq(in, "true"sv) || icaseeq(in, "t"sv) || icaseeq(in, "on"sv))
+ {
+ return true;
+ }
+ if (in == "0"sv || icaseeq(in, "no"sv) || icaseeq(in, "n"sv) ||
+ icaseeq(in, "false"sv) || icaseeq(in, "f"sv) || icaseeq(in, "off"sv))
+ {
+ return false;
+ }
+ return std::nullopt;
+}
+
Parser::Parser(const fs::path& filename)
{
setFile(filename);
diff --git a/src/config_parser.hpp b/src/config_parser.hpp
index abbf25c..75ef4a7 100644
--- a/src/config_parser.hpp
+++ b/src/config_parser.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <filesystem>
+#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
@@ -13,6 +14,11 @@
namespace config
{
+/** @brief Compare in (case insensitive) vs expected (sensitive) */
+bool icaseeq(std::string_view in, std::string_view expected) noexcept;
+/** @brief Turns a systemd bool string into a c++ bool */
+std::optional<bool> parseBool(std::string_view in) noexcept;
+
struct string_hash : public std::hash<std::string_view>
{
using is_transparent = void;
diff --git a/src/dhcp_configuration.cpp b/src/dhcp_configuration.cpp
index 0605a6a..ec9e6d9 100644
--- a/src/dhcp_configuration.cpp
+++ b/src/dhcp_configuration.cpp
@@ -98,7 +98,14 @@
log<level::NOTICE>(msg.c_str(), entry("PROP=%s", prop.c_str()));
return true;
}
- return values.back() != "false";
+ auto ret = config::parseBool(values.back());
+ if (!ret.has_value())
+ {
+ auto msg = fmt::format("Failed to parse section DHCP[{}]: `{}`", prop,
+ values.back());
+ log<level::NOTICE>(msg.c_str(), entry("PROP=%s", prop.c_str()));
+ }
+ return ret.value_or(true);
}
} // namespace dhcp
} // namespace network
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 90c987d..06ccc93 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -955,7 +955,15 @@
log<level::NOTICE>("Unable to get the value for Network[IPv6AcceptRA]");
return false;
}
- return values.back() == "true";
+ auto ret = config::parseBool(values.back());
+ if (!ret.has_value())
+ {
+ auto msg =
+ fmt::format("Failed to parse section Network[IPv6AcceptRA]: `{}`",
+ values.back());
+ log<level::NOTICE>(msg.c_str());
+ }
+ return ret.value_or(false);
}
ServerList EthernetInterface::getNTPServersFromConf()
diff --git a/src/util.cpp b/src/util.cpp
index de0bc9d..13be8d0 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -367,8 +367,6 @@
EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
const std::string& intf)
{
- EthernetInterfaceIntf::DHCPConf dhcp =
- EthernetInterfaceIntf::DHCPConf::none;
// Get the interface mode value from systemd conf
// using namespace std::string_literals;
fs::path confPath = confDir;
@@ -381,21 +379,25 @@
if (values.empty())
{
log<level::NOTICE>("Unable to get the value for Network[DHCP]");
- return dhcp;
+ return EthernetInterfaceIntf::DHCPConf::none;
}
- if (values.back() == "true")
+ if (config::icaseeq(values.back(), "ipv4"))
{
- dhcp = EthernetInterfaceIntf::DHCPConf::both;
+ return EthernetInterfaceIntf::DHCPConf::v4;
}
- else if (values.back() == "ipv4")
+ if (config::icaseeq(values.back(), "ipv6"))
{
- dhcp = EthernetInterfaceIntf::DHCPConf::v4;
+ return EthernetInterfaceIntf::DHCPConf::v6;
}
- else if (values.back() == "ipv6")
+ auto ret = config::parseBool(values.back());
+ if (!ret.has_value())
{
- dhcp = EthernetInterfaceIntf::DHCPConf::v6;
+ auto str =
+ fmt::format("Unable to parse Network[DHCP]: `{}`", values.back());
+ log<level::NOTICE>(str.c_str());
}
- return dhcp;
+ return ret.value_or(false) ? EthernetInterfaceIntf::DHCPConf::both
+ : EthernetInterfaceIntf::DHCPConf::none;
}
namespace mac_address