diff options
author | Brad King <brad.king@kitware.com> | 2018-12-08 02:08:17 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2018-12-12 13:10:15 (GMT) |
commit | a0841b59bdacc1e550e6607d9e44e79ae456cd19 (patch) | |
tree | 780f579afba03f7feb663889582889438d775e0a | |
parent | 9d5fe8e96a074b6e112d981302c77e31a1bcde00 (diff) | |
download | CMake-a0841b59bdacc1e550e6607d9e44e79ae456cd19.zip CMake-a0841b59bdacc1e550e6607d9e44e79ae456cd19.tar.gz CMake-a0841b59bdacc1e550e6607d9e44e79ae456cd19.tar.bz2 |
String: Add support for a ""_s string literal syntax
Create a `static_string_view` type that binds only to the static storage
of string literals. Teach `cm::String` to borrow from these implicitly.
-rw-r--r-- | Source/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Source/cmString.hxx | 15 | ||||
-rw-r--r-- | Source/cm_static_string_view.hxx | 41 | ||||
-rw-r--r-- | Tests/CMakeLib/testString.cxx | 49 |
4 files changed, 103 insertions, 3 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 0ce09d4..ab3e835 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -377,6 +377,7 @@ set(SRCS cmake.h cm_string_view.cxx cm_string_view.hxx + cm_static_string_view.hxx cmCommand.cxx cmCommand.h diff --git a/Source/cmString.hxx b/Source/cmString.hxx index 3b59353..52e891c 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cm_static_string_view.hxx" #include "cm_string_view.hxx" #include <algorithm> @@ -90,6 +91,12 @@ struct IntoString<string_view> : std::true_type }; template <> +struct IntoString<static_string_view> : std::true_type +{ + static string_view into_string(static_string_view s) { return s; } +}; + +template <> struct IntoString<char> : std::true_type { static std::string into_string(char const& c) { return std::string(1, c); } @@ -157,6 +164,12 @@ struct AsStringView<string_view> : std::true_type }; template <> +struct AsStringView<static_string_view> : std::true_type +{ + static string_view view(static_string_view const& s) { return s; } +}; + +template <> struct AsStringView<String> : std::true_type { static string_view view(String const& s); @@ -370,7 +383,7 @@ public: } /** Assign to an empty string. */ - void clear() { *this = String(string_view("", 0), Private()); } + void clear() { *this = ""_s; } /** Insert 'count' copies of 'ch' at position 'index'. */ String& insert(size_type index, size_type count, char ch); diff --git a/Source/cm_static_string_view.hxx b/Source/cm_static_string_view.hxx new file mode 100644 index 0000000..1bef0c6 --- /dev/null +++ b/Source/cm_static_string_view.hxx @@ -0,0 +1,41 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_static_string_view_hxx +#define cm_static_string_view_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_string_view.hxx" + +#include <cstddef> + +namespace cm { + +/** A string_view that only binds to static storage. + * + * This is used together with the `""_s` user-defined literal operator + * to construct a type-safe abstraction of a string_view that only views + * statically allocated strings. These strings are const and available + * for the entire lifetime of the program. + */ +class static_string_view : public string_view +{ + static_string_view(string_view v) + : string_view(v) + { + } + + friend static_string_view operator"" _s(const char* data, size_t size); +}; + +/** Create a static_string_view using `""_s` literal syntax. */ +inline static_string_view operator"" _s(const char* data, size_t size) +{ + return string_view(data, size); +} + +} // namespace cm + +using cm::operator"" _s; + +#endif diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index 411a61a..8bdcb15 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -3,6 +3,7 @@ #include "cmString.hxx" +#include "cm_static_string_view.hxx" #include "cm_string_view.hxx" #include <cstring> @@ -254,6 +255,36 @@ static bool testConstructFromN() return true; } +static const auto staticStringView = "abc"_s; + +static bool testFromStaticStringView(cm::String str) +{ + cm::String const& str_const = str; + ASSERT_TRUE(str_const.data() == staticStringView.data()); + ASSERT_TRUE(str_const.size() == staticStringView.size()); + ASSERT_TRUE(str.c_str() == staticStringView); + cm::String substr = str.substr(1); + cm::String const& substr_const = substr; + ASSERT_TRUE(substr_const.data() == &staticStringView[1]); + ASSERT_TRUE(substr_const.size() == 2); + ASSERT_TRUE(substr.c_str() == &staticStringView[1]); + return true; +} + +static bool testConstructFromStaticStringView() +{ + std::cout << "testConstructFromStaticStringView()\n"; + return testFromStaticStringView(staticStringView); +} + +static bool testAssignFromStaticStringView() +{ + std::cout << "testAssignFromStaticStringView()\n"; + cm::String str; + str = staticStringView; + return testFromStaticStringView(str); +} + static bool testConstructCopy() { std::cout << "testConstructCopy()\n"; @@ -730,7 +761,7 @@ static bool testMethod_substr_AtEnd(cm::String str) static bool testMethod_substr_AtEndBorrowed() { std::cout << "testMethod_substr_AtEndBorrowed()\n"; - return testMethod_substr_AtEnd(cm::String::borrow("abc")); + return testMethod_substr_AtEnd("abc"_s); } static bool testMethod_substr_AtEndOwned() @@ -784,7 +815,7 @@ static bool testMethod_substr_AtStart(cm::String str) static bool testMethod_substr_AtStartBorrowed() { std::cout << "testMethod_substr_AtStartBorrowed()\n"; - return testMethod_substr_AtStart(cm::String::borrow("abc")); + return testMethod_substr_AtStart("abc"_s); } static bool testMethod_substr_AtStartOwned() @@ -978,6 +1009,14 @@ static bool testAddition() ASSERT_TRUE("abcd" == "a" + (cm::String("b") + "c") + "d"); } { + ASSERT_TRUE(cm::String("a"_s) + "b"_s == "ab"_s); + ASSERT_TRUE("ab"_s == "a"_s + cm::String("b"_s)); + ASSERT_TRUE("a"_s + cm::String("b"_s) + "c"_s == "abc"_s); + ASSERT_TRUE("abc"_s == "a"_s + cm::String("b"_s) + "c"_s); + ASSERT_TRUE("a"_s + (cm::String("b"_s) + "c"_s) + "d"_s == "abcd"_s); + ASSERT_TRUE("abcd"_s == "a"_s + (cm::String("b"_s) + "c"_s) + "d"_s); + } + { const char* a = "a"; const char* b = "b"; const char* ab = "ab"; @@ -1101,6 +1140,9 @@ int testString(int /*unused*/, char* /*unused*/ []) if (!testConstructFromN()) { return 1; } + if (!testConstructFromStaticStringView()) { + return 1; + } if (!testConstructCopy()) { return 1; } @@ -1137,6 +1179,9 @@ int testString(int /*unused*/, char* /*unused*/ []) if (!testAssignFromInitList()) { return 1; } + if (!testAssignFromStaticStringView()) { + return 1; + } if (!testOperatorBool()) { return 1; } |