From ec6a4a831e57834bf4d7abb91fc8b298c2fbfcc2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 15 Jan 2016 17:11:19 +0100 Subject: [PATCH] provide a constexpr char[] overload for APT::StringView The commit also adds a few trivial tests Git-Dch: Ignore --- apt-pkg/contrib/string_view.h | 14 ++++-- test/libapt/stringview_test.cc | 88 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 test/libapt/stringview_test.cc diff --git a/apt-pkg/contrib/string_view.h b/apt-pkg/contrib/string_view.h index d4ff80028..ea38224e8 100644 --- a/apt-pkg/contrib/string_view.h +++ b/apt-pkg/contrib/string_view.h @@ -27,6 +27,10 @@ class StringView { const char *data_; size_t size_; + // without this little stunt the "char const *" overload is always preferred + // over char[], but if we got a char[] we can deduct the length at compile time + #define APT_T_IS_CHARPOINTER template{} && !std::is_array{}>::type* = nullptr> + public: static constexpr size_t npos = static_cast(-1); static_assert(APT::StringView::npos == std::string::npos, "npos values are different"); @@ -35,9 +39,10 @@ public: constexpr StringView() : data_(""), size_(0) {} constexpr StringView(const char *data, size_t size) : data_(data), size_(size) {} - StringView(const char *data) : data_(data), size_(strlen(data)) {} - StringView(std::string const & str): data_(str.data()), size_(str.size()) {} + template constexpr StringView(char const (&data)[N]) : StringView(data, N-1) {} + APT_T_IS_CHARPOINTER StringView(T data) : data_(data), size_(strlen(data)) {} + StringView(std::string const & str): data_(str.data()), size_(str.size()) {} /* Viewers */ constexpr StringView substr(size_t pos, size_t n = npos) const { @@ -114,7 +119,8 @@ public: } -inline bool operator ==(const char *other, APT::StringView that); -inline bool operator ==(const char *other, APT::StringView that) { return that.operator==(other); } +template inline bool operator ==(char const (&other)[N], APT::StringView that) { return that.operator==(other); } +APT_T_IS_CHARPOINTER inline bool operator ==(T other, APT::StringView that) { return that.operator==(other); } +#undef APT_T_IS_CHARPOINTER #endif diff --git a/test/libapt/stringview_test.cc b/test/libapt/stringview_test.cc new file mode 100644 index 000000000..bac69ec2e --- /dev/null +++ b/test/libapt/stringview_test.cc @@ -0,0 +1,88 @@ +#if !(defined APT_PKG_EXPOSE_STRING_VIEW) + #define APT_PKG_EXPOSE_STRING_VIEW +#endif + +#include +#include +#include + +#include + +#include + +TEST(StringViewTest,EmptyString) +{ + constexpr APT::StringView defString; + static_assert( 0 == defString.length(), "def right size"); + + APT::StringView strString{std::string{}}; + EXPECT_EQ(0, strString.length()); + + constexpr char const * const charp = ""; + constexpr APT::StringView charpString{charp, 0}; + static_assert( 0 == charpString.length(), "charp right size"); + + APT::StringView charp2String{charp}; + EXPECT_EQ(0, strString.length()); + + constexpr APT::StringView charaString{""}; + static_assert( 0 == charaString.length(), "chara right size"); + + EXPECT_TRUE(APT::StringView("") == ""); + EXPECT_FALSE(APT::StringView("") != ""); +} + +TEST(StringViewTest,FooString) +{ + constexpr APT::StringView defString("foo", 3); + static_assert( 3 == defString.length(), "def right size"); + EXPECT_EQ(defString.to_string(), defString.data()); + + APT::StringView strString{std::string{"foo"}}; + EXPECT_EQ(3, strString.length()); + EXPECT_EQ(strString.to_string(), strString.data()); + + constexpr char const * const charp = "foo"; + constexpr APT::StringView charpString{charp, 3}; + static_assert( 3 == charpString.length(), "charp right size"); + EXPECT_EQ(charpString.to_string(), charpString.data()); + + APT::StringView charp2String{charp}; + EXPECT_EQ(3, charp2String.length()); + EXPECT_EQ(charp2String.to_string(), charp2String.data()); + + constexpr APT::StringView charaString{"foo"}; + static_assert( 3 == charaString.length(), "chara right size"); + EXPECT_EQ(charaString.to_string(), charaString.data()); + + EXPECT_TRUE(APT::StringView("foo") == "foo"); + EXPECT_FALSE(APT::StringView("foo") != "foo"); +} + +TEST(StringViewTest,SubStr) +{ + constexpr APT::StringView defString("Hello World!"); + EXPECT_EQ(defString.to_string().substr(6), defString.substr(6).to_string()); + EXPECT_EQ(defString.to_string().substr(0,5), defString.substr(0,5).to_string()); + EXPECT_EQ(defString.to_string().substr(6,5), defString.substr(6,5).to_string()); +} + +TEST(StringViewTest,Find) +{ + constexpr APT::StringView defString("Hello World!"); + EXPECT_EQ(defString.to_string().find('l'), defString.find('l')); + EXPECT_EQ(defString.to_string().find('X'), defString.find('X')); + EXPECT_EQ(defString.to_string().find('e',3), defString.find('e',3)); + EXPECT_EQ(defString.to_string().find('l',6), defString.find('l',6)); + EXPECT_EQ(defString.to_string().find('l',11), defString.find('l',11)); +} + +TEST(StringViewTest,RFind) +{ + constexpr APT::StringView defString("Hello World!"); + EXPECT_EQ(defString.to_string().rfind('l'), defString.rfind('l')); + EXPECT_EQ(defString.to_string().rfind('X'), defString.rfind('X')); + EXPECT_EQ(defString.to_string().rfind('e',3), defString.rfind('e',3)); + EXPECT_EQ(defString.to_string().rfind('l',6), defString.rfind('l',6)); + EXPECT_EQ(defString.to_string().rfind('l',11), defString.rfind('l',11)); +} -- 2.45.2