types: Add constexpr in_addr parser
Change-Id: Id24af0b9722b3ed68ab7dc5175c841e86b94ab64
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/types.hpp b/src/types.hpp
index 3c0b6d9..1a87faa 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -286,6 +286,29 @@
}
};
+template <>
+struct ToAddr<in_addr>
+{
+ constexpr in_addr operator()(std::string_view str) const
+ {
+ constexpr DecodeInt<uint8_t, 10> di;
+ uint32_t addr = {};
+ for (size_t i = 0; i < 3; ++i)
+ {
+ auto loc = str.find(".");
+ addr |= di(str.substr(0, loc));
+ addr <<= 8;
+ str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
+ if (str.empty())
+ {
+ throw std::invalid_argument("Missing addr data");
+ }
+ }
+ addr |= di(str);
+ return {hton(addr)};
+ }
+};
+
namespace detail
{
diff --git a/test/test_types.cpp b/test/test_types.cpp
index f9e49b3..fc4a998 100644
--- a/test/test_types.cpp
+++ b/test/test_types.cpp
@@ -120,6 +120,22 @@
ToAddr<ether_addr>{}("FFEEDDccbbaa"));
}
+TEST(ToAddr, InAddr)
+{
+ EXPECT_THROW(ToAddr<in_addr>{}(""), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("0.0.0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("0.0.0."), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}(".0.0.0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("0.0.0.0.0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("x.0.0.0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("ff.0.0.0"), std::invalid_argument);
+ EXPECT_THROW(ToAddr<in_addr>{}("256.0.0.0"), std::overflow_error);
+
+ EXPECT_EQ((in_addr{}), ToAddr<in_addr>{}("0.0.0.0"));
+ EXPECT_EQ((in_addr{htonl(0xc0a80101)}), ToAddr<in_addr>{}("192.168.001.1"));
+}
+
namespace detail
{