zstring: Add class
This is the most efficient wrapper for nul-terminated strings as it does
not care about determining string length. Conversions to / from
ztring_view are provided to make it trivial to upgrade.
Change-Id: Ic83626c53b95b851c3c4a13b1eded8f1e40539f0
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/zstring.cpp b/test/zstring.cpp
new file mode 100644
index 0000000..07ea1f1
--- /dev/null
+++ b/test/zstring.cpp
@@ -0,0 +1,103 @@
+#include <gtest/gtest.h>
+#include <iostream>
+#include <stdplus/zstring.hpp>
+#include <string>
+#include <string_view>
+
+using std::literals::string_literals::operator""s;
+using std::literals::string_view_literals::operator""sv;
+
+namespace stdplus
+{
+
+TEST(Zstring, Construct)
+{
+ auto str = "a\0"s;
+ const auto cstr = str;
+#ifdef NDEBUG
+ EXPECT_EQ("a", zstring(str));
+ EXPECT_EQ("a", const_zstring(str));
+ EXPECT_EQ("a", const_zstring(cstr));
+#else
+ EXPECT_THROW((zstring(str)), std::invalid_argument);
+ EXPECT_THROW((const_zstring(str)), std::invalid_argument);
+ EXPECT_THROW((const_zstring(cstr)), std::invalid_argument);
+#endif
+#ifdef NDEBUG
+ EXPECT_EQ("b", const_zstring("b\0"));
+#else
+ EXPECT_THROW(const_zstring("b\0"), std::invalid_argument);
+#endif
+ char as[] = "c";
+ EXPECT_EQ("c", zstring(as));
+ EXPECT_EQ("c", const_zstring(as));
+
+ std::cerr << const_zstring(as);
+}
+
+TEST(Zstring, NoTypeCoercion)
+{
+ char empty[] = "";
+ auto zs = zstring(empty);
+ auto czs = const_zstring("");
+
+ EXPECT_NE(zs, "\0");
+ EXPECT_NE("\0", zs);
+ EXPECT_NE(zs, "\0"sv);
+ EXPECT_NE("\0"sv, zs);
+ EXPECT_LT(zs, "\0"sv);
+ EXPECT_GT("\0"sv, zs);
+ EXPECT_NE(czs, "\0");
+ EXPECT_NE("\0", czs);
+ EXPECT_NE(czs, "\0"sv);
+ EXPECT_NE("\0"sv, czs);
+ EXPECT_LT(czs, "\0"sv);
+ EXPECT_GT("\0"sv, czs);
+
+ auto str = "\0"s;
+ EXPECT_NE(zs, str);
+ EXPECT_NE(str, zs);
+ EXPECT_LT(zs, str);
+ EXPECT_GT(str, zs);
+ EXPECT_NE(czs, str);
+ EXPECT_NE(str, czs);
+ EXPECT_LT(czs, str);
+ EXPECT_GT(str, czs);
+}
+
+TEST(Zstring, Comparison)
+{
+ char mut[] = "ac";
+ auto zs = zstring(mut);
+ auto czs = const_zstring("ac");
+
+#define test(cmp, rcmp, str) \
+ EXPECT_##cmp(zs, const_zstring(str)); \
+ EXPECT_##rcmp(const_zstring(str), zs); \
+ EXPECT_##cmp(czs, const_zstring(str)); \
+ EXPECT_##rcmp(const_zstring(str), czs); \
+ EXPECT_##cmp(zs, str); \
+ EXPECT_##rcmp(str, zs); \
+ EXPECT_##cmp(czs, str); \
+ EXPECT_##rcmp(str, czs); \
+ EXPECT_##cmp(zs, str##sv); \
+ EXPECT_##rcmp(str##sv, zs); \
+ EXPECT_##cmp(czs, str##sv); \
+ EXPECT_##rcmp(str##sv, czs); \
+ EXPECT_##cmp(zs, str##s); \
+ EXPECT_##rcmp(str##s, zs); \
+ EXPECT_##cmp(czs, str##s); \
+ EXPECT_##rcmp(str##s, czs); \
+ EXPECT_##cmp(zs, reinterpret_cast<const char*>(str)); \
+ EXPECT_##rcmp(reinterpret_cast<const char*>(str), zs); \
+ EXPECT_##cmp(czs, reinterpret_cast<const char*>(str)); \
+ EXPECT_##rcmp(reinterpret_cast<const char*>(str), czs)
+ test(EQ, EQ, "ac");
+ test(GT, LT, "a");
+ test(LT, GT, "acb");
+ test(LT, GT, "ad");
+ test(GT, LT, "ab");
+#undef test
+}
+
+} // namespace stdplus