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);