diff options
-rw-r--r-- | Source/cmString.hxx | 101 | ||||
-rw-r--r-- | Tests/CMakeLib/testString.cxx | 101 |
2 files changed, 202 insertions, 0 deletions
diff --git a/Source/cmString.hxx b/Source/cmString.hxx index 833234c..ddafd56 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -662,6 +662,107 @@ operator>=(L&& l, R&& r) std::ostream& operator<<(std::ostream& os, String const& s); std::string& operator+=(std::string& self, String const& s); +template <typename L, typename R> +struct StringOpPlus +{ + L l; + R r; +#if defined(__SUNPRO_CC) + StringOpPlus(L in_l, R in_r) + : l(in_l) + , r(in_r) + { + } +#endif + operator std::string() const; + std::string::size_type size() const { return l.size() + r.size(); } +}; + +template <typename T> +struct StringAdd +{ + static const bool value = AsStringView<T>::value; + typedef string_view temp_type; + template <typename S> + static temp_type temp(S&& s) + { + return AsStringView<T>::view(std::forward<S>(s)); + } +}; + +template <typename L, typename R> +struct StringAdd<StringOpPlus<L, R>> : std::true_type +{ + typedef StringOpPlus<L, R> const& temp_type; + static temp_type temp(temp_type s) { return s; } +}; + +template <typename L, typename R> +StringOpPlus<L, R>::operator std::string() const +{ + std::string s; + s.reserve(size()); + s += *this; + return s; +} + +template <typename L, typename R> +std::string& operator+=(std::string& s, StringOpPlus<L, R> const& a) +{ + s.reserve(s.size() + a.size()); + s += a.l; + s += a.r; + return s; +} + +template <typename L, typename R> +String& operator+=(String& s, StringOpPlus<L, R> const& a) +{ + std::string r; + r.reserve(s.size() + a.size()); + r.assign(s.data(), s.size()); + r += a.l; + r += a.r; + s = std::move(r); + return s; +} + +template <typename L, typename R> +std::ostream& operator<<(std::ostream& os, StringOpPlus<L, R> const& a) +{ + return os << a.l << a.r; +} + +template <typename L, typename R> +struct IntoString<StringOpPlus<L, R>> : std::true_type +{ + static std::string into_string(StringOpPlus<L, R> const& a) { return a; } +}; + +template <typename L, typename R> +typename std::enable_if<StringAdd<L>::value && StringAdd<R>::value, + StringOpPlus<typename StringAdd<L>::temp_type, + typename StringAdd<R>::temp_type>>::type +operator+(L&& l, R&& r) +{ + return { StringAdd<L>::temp(std::forward<L>(l)), + StringAdd<R>::temp(std::forward<R>(r)) }; +} + +template <typename LL, typename LR, typename R> +typename std::enable_if<AsStringView<R>::value, bool>::type operator==( + StringOpPlus<LL, LR> const& l, R&& r) +{ + return std::string(l) == AsStringView<R>::view(std::forward<R>(r)); +} + +template <typename L, typename RL, typename RR> +typename std::enable_if<AsStringView<L>::value, bool>::type operator==( + L&& l, StringOpPlus<RL, RR> const& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) == std::string(r); +} + } // namespace cm namespace std { diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index 9fe2e39..63688af 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -11,6 +11,7 @@ #include <sstream> #include <stdexcept> #include <string> +#include <type_traits> #include <utility> #define ASSERT_TRUE(x) \ @@ -942,6 +943,103 @@ static bool testMethod_find_last_not_of() return true; } +static bool testAddition() +{ + std::cout << "testAddition()\n"; + { + ASSERT_TRUE(cm::String("a") + "b" == "ab"); + ASSERT_TRUE("ab" == "a" + cm::String("b")); + ASSERT_TRUE("a" + cm::String("b") + "c" == "abc"); + ASSERT_TRUE("abc" == "a" + cm::String("b") + "c"); + ASSERT_TRUE("a" + (cm::String("b") + "c") + "d" == "abcd"); + ASSERT_TRUE("abcd" == "a" + (cm::String("b") + "c") + "d"); + } + { + const char* a = "a"; + const char* b = "b"; + const char* ab = "ab"; + ASSERT_TRUE(cm::String(a) + b == ab); + ASSERT_TRUE(ab == a + cm::String(b)); + const char* c = "c"; + const char* abc = "abc"; + ASSERT_TRUE(a + cm::String(b) + c == abc); + ASSERT_TRUE(abc == a + cm::String(b) + c); + const char* d = "d"; + const char* abcd = "abcd"; + ASSERT_TRUE(a + (cm::String(b) + c) + d == abcd); + ASSERT_TRUE(abcd == a + (cm::String(b) + c) + d); + } + { + ASSERT_TRUE(cm::String('a') + 'b' == "ab"); + ASSERT_TRUE("ab" == 'a' + cm::String('b')); + ASSERT_TRUE('a' + cm::String('b') + 'c' == "abc"); + ASSERT_TRUE("abc" == 'a' + cm::String('b') + 'c'); + ASSERT_TRUE('a' + (cm::String('b') + 'c') + 'd' == "abcd"); + ASSERT_TRUE("abcd" == 'a' + (cm::String('b') + 'c') + 'd'); + } + { + std::string a = "a"; + std::string b = "b"; + std::string ab = "ab"; + ASSERT_TRUE(cm::String(a) + b == ab); + ASSERT_TRUE(ab == a + cm::String(b)); + std::string c = "c"; + std::string abc = "abc"; + ASSERT_TRUE(a + cm::String(b) + c == abc); + ASSERT_TRUE(abc == a + cm::String(b) + c); + std::string d = "d"; + std::string abcd = "abcd"; + ASSERT_TRUE(a + (cm::String(b) + c) + d == abcd); + ASSERT_TRUE(abcd == a + (cm::String(b) + c) + d); + } + { + cm::string_view a("a", 1); + cm::string_view b("b", 1); + cm::string_view ab("ab", 2); + ASSERT_TRUE(cm::String(a) + b == ab); + ASSERT_TRUE(ab == a + cm::String(b)); + cm::string_view c("c", 1); + cm::string_view abc("abc", 3); + ASSERT_TRUE(a + cm::String(b) + c == abc); + ASSERT_TRUE(abc == a + cm::String(b) + c); + cm::string_view d("d", 1); + cm::string_view abcd("abcd", 4); + ASSERT_TRUE(a + (cm::String(b) + c) + d == abcd); + ASSERT_TRUE(abcd == a + (cm::String(b) + c) + d); + } + { + cm::String a = "a"; + cm::String b = "b"; + cm::String ab = "ab"; + ASSERT_TRUE(a + b == ab); + ASSERT_TRUE(ab == a + b); + cm::String c = "c"; + cm::String abc = "abc"; + ASSERT_TRUE(a + cm::String(b) + c == abc); + ASSERT_TRUE(abc == a + cm::String(b) + c); + cm::String d = "d"; + cm::String abcd = "abcd"; + ASSERT_TRUE(a + (cm::String(b) + c) + d == abcd); + ASSERT_TRUE(abcd == a + (cm::String(b) + c) + d); + } + { + cm::String str; + str += "a" + cm::String("b") + 'c'; + ASSERT_TRUE(str == "abc"); + } + { + std::string s; + s += "a" + cm::String("b") + 'c'; + ASSERT_TRUE(s == "abc"); + } + { + std::ostringstream ss; + ss << ("a" + cm::String("b") + 'c'); + ASSERT_TRUE(ss.str() == "abc"); + } + return true; +} + int testString(int /*unused*/, char* /*unused*/ []) { if (!testConstructDefault()) { @@ -1106,5 +1204,8 @@ int testString(int /*unused*/, char* /*unused*/ []) if (!testMethod_find_last_not_of()) { return 1; } + if (!testAddition()) { + return 1; + } return 0; } |