diff --git a/wpiutil/src/main/native/cpp/llvm/Twine.cpp b/wpiutil/src/main/native/cpp/llvm/Twine.cpp index ac705ff136..b8dd7c308e 100644 --- a/wpiutil/src/main/native/cpp/llvm/Twine.cpp +++ b/wpiutil/src/main/native/cpp/llvm/Twine.cpp @@ -64,6 +64,9 @@ void Twine::printOneChild(raw_ostream &OS, Child Ptr, case Twine::StringRefKind: OS << *Ptr.stringRef; break; + case Twine::StringViewKind: + OS << *Ptr.stringView; + break; case Twine::SmallStringKind: OS << *Ptr.smallString; break; @@ -117,6 +120,10 @@ void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr, OS << "stringref:\"" << Ptr.stringRef << "\""; break; + case Twine::StringViewKind: + OS << "std::string_view:\"" + << Ptr.stringView << "\""; + break; case Twine::SmallStringKind: OS << "smallstring:\"" << *Ptr.smallString << "\""; break; diff --git a/wpiutil/src/main/native/include/wpi/StringRef.h b/wpiutil/src/main/native/include/wpi/StringRef.h index a564ec1fe3..b804605f9d 100644 --- a/wpiutil/src/main/native/include/wpi/StringRef.h +++ b/wpiutil/src/main/native/include/wpi/StringRef.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,10 @@ namespace wpi { /*implicit*/ StringRef(const std::string &Str) noexcept : Data(Str.data()), Length(Str.length()) {} + /// Construct a string ref from an std::string_view. + /*implicit*/ constexpr StringRef(std::string_view Str) + : Data(Str.data()), Length(Str.size()) {} + static StringRef withNullAsEmpty(const char *data) noexcept { return StringRef(data ? data : ""); } @@ -235,6 +240,10 @@ namespace wpi { return str(); } + operator std::string_view() const { + return std::string_view(data(), size()); + } + /// @} /// @name String Predicates /// @{ diff --git a/wpiutil/src/main/native/include/wpi/Twine.h b/wpiutil/src/main/native/include/wpi/Twine.h index a5b7e973e0..e7d0f95c20 100644 --- a/wpiutil/src/main/native/include/wpi/Twine.h +++ b/wpiutil/src/main/native/include/wpi/Twine.h @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef _WIN32 #pragma warning(push) @@ -104,6 +105,9 @@ namespace wpi { /// A pointer to a StringRef instance. StringRefKind, + /// A pointer to a std::string_view instance. + StringViewKind, + /// A pointer to a SmallString instance. SmallStringKind, @@ -141,6 +145,7 @@ namespace wpi { const char *cString; const std::string *stdString; const StringRef *stringRef; + const std::string_view *stringView; const SmallVectorImpl *smallString; char character; unsigned int decUI; @@ -282,6 +287,12 @@ namespace wpi { assert(isValid() && "Invalid twine!"); } + /// Construct from a std::string_view. + /*implicit*/ Twine(const std::string_view &Str) : LHSKind(StringViewKind) { + LHS.stringView = &Str; + assert(isValid() && "Invalid twine!"); + } + /// Construct from a SmallString. /*implicit*/ Twine(const SmallVectorImpl &Str) : LHSKind(SmallStringKind) { @@ -355,6 +366,22 @@ namespace wpi { assert(isValid() && "Invalid twine!"); } + /// Construct as the concatenation of a C string and a std::string_view. + /*implicit*/ Twine(const char *LHS, const std::string_view &RHS) + : LHSKind(CStringKind), RHSKind(StringViewKind) { + this->LHS.cString = LHS; + this->RHS.stringView = &RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Construct as the concatenation of a std::string_view and a C string. + /*implicit*/ Twine(const std::string_view &LHS, const char *RHS) + : LHSKind(StringViewKind), RHSKind(CStringKind) { + this->LHS.stringView = &LHS; + this->RHS.cString = RHS; + assert(isValid() && "Invalid twine!"); + } + /// Since the intended use of twines is as temporary objects, assignments /// when concatenating might cause undefined behavior or stack corruptions Twine &operator=(const Twine &) = delete; @@ -402,6 +429,7 @@ namespace wpi { case CStringKind: case StdStringKind: case StringRefKind: + case StringViewKind: case SmallStringKind: case CharKind: return true; @@ -438,6 +466,7 @@ namespace wpi { case CStringKind: return StringRef(LHS.cString); case StdStringKind: return StringRef(*LHS.stdString); case StringRefKind: return *LHS.stringRef; + case StringViewKind: return StringRef(*LHS.stringView); case SmallStringKind: return StringRef(LHS.smallString->data(), LHS.smallString->size()); case CharKind: return StringRef(&LHS.character, 1); diff --git a/wpiutil/src/main/native/include/wpi/raw_ostream.h b/wpiutil/src/main/native/include/wpi/raw_ostream.h index bb577fee5d..348dacbf3d 100644 --- a/wpiutil/src/main/native/include/wpi/raw_ostream.h +++ b/wpiutil/src/main/native/include/wpi/raw_ostream.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -196,6 +197,21 @@ public: return *this; } + raw_ostream &operator<<(std::string_view Str) { + // Inline fast path, particularly for strings with a known length. + size_t Size = Str.size(); + + // Make sure we can use the fast path. + if (Size > (size_t)(OutBufEnd - OutBufCur)) + return write(Str.data(), Size); + + if (Size) { + memcpy(OutBufCur, Str.data(), Size); + OutBufCur += Size; + } + return *this; + } + raw_ostream &operator<<(const char *Str) { // Inline fast path, particularly for constant strings where a sufficiently // smart compiler will simplify strlen.