diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 82f46c9379c..ab8d3653e33 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -382,6 +382,14 @@ namespace llvm { /// SmallVector and a StringRef to the SmallVector's data is returned. StringRef toStringRef(SmallVectorImpl &Out) const; + /// toNullTerminatedStringRef - This returns the twine as a single null + /// terminated StringRef if it can be represented as such. Otherwise the + /// twine is written into the given SmallVector and a StringRef to the + /// SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; + /// print - Write the concatenated string represented by this twine to the /// stream \arg OS. void print(raw_ostream &OS) const; diff --git a/lib/Support/Twine.cpp b/lib/Support/Twine.cpp index 093e29de96a..4f6f479a7ea 100644 --- a/lib/Support/Twine.cpp +++ b/lib/Support/Twine.cpp @@ -30,6 +30,18 @@ StringRef Twine::toStringRef(SmallVectorImpl &Out) const { return StringRef(Out.data(), Out.size()); } +StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl &Out) const { + if (isSingleStringRef()) { + StringRef sr = getSingleStringRef(); + if (*(sr.begin() + sr.size()) == 0) + return sr; + } + toVector(Out); + Out.push_back(0); + Out.pop_back(); + return StringRef(Out.data(), Out.size()); +} + void Twine::printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const { switch (Kind) { diff --git a/unittests/ADT/TwineTest.cpp b/unittests/ADT/TwineTest.cpp index 61e8a0ac37c..57f54cb0060 100644 --- a/unittests/ADT/TwineTest.cpp +++ b/unittests/ADT/TwineTest.cpp @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -69,6 +70,13 @@ TEST(TwineTest, Concat) { repr(Twine("a").concat(Twine("b").concat(Twine("c"))))); } +TEST(TwineTest, toNullTerminatedStringRef) { + SmallString<8> storage; + EXPECT_EQ(0, *Twine("hello").toNullTerminatedStringRef(storage).end()); + EXPECT_EQ(0, + *Twine(StringRef("hello")).toNullTerminatedStringRef(storage).end()); +} + // I suppose linking in the entire code generator to add a unit test to check // the code size of the concat operation is overkill... :)