[ORC-RT] Add more string_view operations and tests.
authorLang Hames <lhames@gmail.com>
Tue, 8 Feb 2022 04:12:00 +0000 (15:12 +1100)
committerLang Hames <lhames@gmail.com>
Tue, 8 Feb 2022 04:29:31 +0000 (15:29 +1100)
Adds construction from std::string, an ostream &operator<< and std::hash
specialization. Also adds unit tests for each of these operations, as well as
tests for copy construction and assignment.

These new operations will be used in upcoming macho_platform patches.

compiler-rt/lib/orc/adt.h
compiler-rt/lib/orc/unittests/adt_test.cpp

index 3a42287..64afd5d 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <cstring>
 #include <limits>
+#include <ostream>
 #include <string>
 
 namespace __orc_rt {
@@ -76,6 +77,7 @@ public:
   constexpr string_view(const char *S, size_type Count)
       : Data(S), Size(Count) {}
   string_view(const char *S) : Data(S), Size(strlen(S)) {}
+  string_view(const std::string &S) : Data(S.data()), Size(S.size()) {}
 
   constexpr const_iterator begin() const noexcept { return Data; }
   constexpr const_iterator end() const noexcept { return Data + Size; }
@@ -104,10 +106,23 @@ private:
   size_type Size = 0;
 };
 
-inline std::string to_string(string_view SV) {
-  return std::string(SV.data(), SV.size());
+inline std::ostream &operator<<(std::ostream &OS, string_view S) {
+  return OS.write(S.data(), S.size());
 }
 
 } // end namespace __orc_rt
 
+namespace std {
+// Make string_view hashable.
+// FIXME: This can be removed (along with the string_view class) when we move
+// to C++17.
+template <> struct hash<__orc_rt::string_view> {
+  size_t operator()(const __orc_rt::string_view &S) const {
+    std::string Tmp(S.data(), S.size());
+    return hash<std::string>()(Tmp);
+  }
+};
+
+} // namespace std
+
 #endif // ORC_RT_ADT_H
index 2fa76a5..117f7b5 100644 (file)
@@ -13,6 +13,9 @@
 #include "adt.h"
 #include "gtest/gtest.h"
 
+#include <sstream>
+#include <string>
+
 using namespace __orc_rt;
 
 TEST(ADTTest, SpanDefaultConstruction) {
@@ -79,9 +82,49 @@ TEST(ADTTest, StringViewConstructFromCharPtr) {
     EXPECT_EQ(S[I], Str[I]) << "Unexpected string_view element value";
 }
 
+TEST(ADTTest, StringViewConstructFromStdString) {
+  std::string Str("abcdefg");
+  string_view S(Str);
+
+  EXPECT_FALSE(S.empty()) << "string_view should be non-empty";
+  EXPECT_EQ(S.size(), Str.size()) << "string_view has unexpected size";
+  EXPECT_EQ(static_cast<size_t>(std::distance(S.begin(), S.end())), Str.size())
+      << "Unexpected iterator range size";
+  EXPECT_EQ(S.data(), &Str[0]) << "string_view data has unexpected value";
+  for (unsigned I = 0; I != S.size(); ++I)
+    EXPECT_EQ(S[I], Str[I]) << "Unexpected string_view element value";
+}
+
+TEST(ADTTest, StringViewCopyConstructionAndAssignment) {
+  // Check that string_views are copy-constructible and copy-assignable.
+  std::string Str("abcdefg");
+  string_view Orig(Str);
+  string_view CopyConstructed(Orig);
+  string_view CopyAssigned = Orig;
+
+  EXPECT_EQ(Orig, CopyConstructed);
+  EXPECT_EQ(Orig, CopyAssigned);
+}
+
 TEST(ADTTest, StringViewEquality) {
   EXPECT_EQ("", string_view());
   EXPECT_FALSE(string_view("aab") == string_view("aac"));
   EXPECT_FALSE(string_view("aab") != string_view("aab"));
   EXPECT_NE(string_view("aab"), string_view("aac"));
 }
+
+TEST(ADTTest, StringViewOStreamOperator) {
+  std::string Str("abcdefg");
+  string_view S(Str);
+  std::ostringstream OSS;
+  OSS << S;
+
+  EXPECT_EQ(OSS.str(), Str);
+}
+
+TEST(ADTTest, StringViewHashable) {
+  std::string Str("abcdefg");
+  string_view S(Str);
+
+  EXPECT_EQ(std::hash<std::string>()(Str), std::hash<string_view>()(S));
+}