From f2b7d9f7faa2788e362a91761a1624fb6b020851 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Duncan=20P=2E=20N=2E=20Exon=C2=A0Smith?= Date: Mon, 12 Oct 2020 18:00:55 -0400 Subject: [PATCH] Support: Allow use of MemoryBufferRef with line_iterator Split out from https://reviews.llvm.org/D66782, use `Optional` in `line_iterator` so you don't need access to a `MemoryBuffer*`. Follow up patches in `clang/` will leverage this. Differential Revision: https://reviews.llvm.org/D89280 --- llvm/include/llvm/Support/LineIterator.h | 8 +++++++- llvm/lib/Support/LineIterator.cpp | 8 ++++++-- llvm/unittests/Support/LineIteratorTest.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Support/LineIterator.h b/llvm/include/llvm/Support/LineIterator.h index 2a1e47b..b391412 100644 --- a/llvm/include/llvm/Support/LineIterator.h +++ b/llvm/include/llvm/Support/LineIterator.h @@ -9,8 +9,10 @@ #ifndef LLVM_SUPPORT_LINEITERATOR_H #define LLVM_SUPPORT_LINEITERATOR_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBufferRef.h" #include namespace llvm { @@ -30,7 +32,7 @@ class MemoryBuffer; /// Note that this iterator requires the buffer to be nul terminated. class line_iterator : public std::iterator { - const MemoryBuffer *Buffer = nullptr; + Optional Buffer; char CommentMarker = '\0'; bool SkipBlanks = true; @@ -41,6 +43,10 @@ public: /// Default construct an "end" iterator. line_iterator() = default; + /// Construct a new iterator around an unowned memory buffer. + explicit line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks = true, + char CommentMarker = '\0'); + /// Construct a new iterator around some memory buffer. explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true, char CommentMarker = '\0'); diff --git a/llvm/lib/Support/LineIterator.cpp b/llvm/lib/Support/LineIterator.cpp index 164436a..7bdf127 100644 --- a/llvm/lib/Support/LineIterator.cpp +++ b/llvm/lib/Support/LineIterator.cpp @@ -33,7 +33,11 @@ static bool skipIfAtLineEnd(const char *&P) { line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks, char CommentMarker) - : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr), + : line_iterator(Buffer.getMemBufferRef(), SkipBlanks, CommentMarker) {} + +line_iterator::line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks, + char CommentMarker) + : Buffer(Buffer.getBufferSize() ? Optional(Buffer) : None), CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1), CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr, 0) { @@ -78,7 +82,7 @@ void line_iterator::advance() { if (*Pos == '\0') { // We've hit the end of the buffer, reset ourselves to the end state. - Buffer = nullptr; + Buffer = None; CurrentLine = StringRef(); return; } diff --git a/llvm/unittests/Support/LineIteratorTest.cpp b/llvm/unittests/Support/LineIteratorTest.cpp index 96cf37a..7d1bae1 100644 --- a/llvm/unittests/Support/LineIteratorTest.cpp +++ b/llvm/unittests/Support/LineIteratorTest.cpp @@ -39,6 +39,30 @@ TEST(LineIteratorTest, Basic) { EXPECT_EQ(E, I); } +TEST(LineIteratorTest, Ref) { + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3"); + + line_iterator I = line_iterator(Buffer->getMemBufferRef()), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + TEST(LineIteratorTest, CommentAndBlankSkipping) { std::unique_ptr Buffer( MemoryBuffer::getMemBuffer("line 1\n" -- 2.7.4