ソースを参照

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.
Brad King 6 年 前
コミット
a0841b59bd

+ 1 - 0
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

+ 14 - 1
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>
@@ -89,6 +90,12 @@ struct IntoString<string_view> : std::true_type
   static std::string into_string(string_view s) { return std::string(s); }
 };
 
+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
 {
@@ -156,6 +163,12 @@ struct AsStringView<string_view> : std::true_type
   static string_view view(string_view const& s) { return s; }
 };
 
+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
 {
@@ -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);

+ 41 - 0
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

+ 47 - 2
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()
@@ -977,6 +1008,14 @@ static bool testAddition()
     ASSERT_TRUE("a" + (cm::String("b") + "c") + "d" == "abcd");
     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";
@@ -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;
   }