llvm.org GIT mirror llvm / 0a277ea
LineIterator: Provide a variant that keeps blank lines It isn't always useful to skip blank lines, as evidenced by the somewhat awkward use of line_iterator in llvm-cov. This adds a knob to control whether or not to skip blanks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217960 91177308-0d34-0410-b5e6-96231b3b80d8 Justin Bogner 5 years ago
6 changed file(s) with 117 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
119119 LLVM_DELETED_FUNCTION;
120120 public:
121121 TextInstrProfReader(std::unique_ptr DataBuffer_)
122 : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {}
122 : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
123123
124124 /// Read the header.
125125 std::error_code readHeader() override { return success(); }
1717
1818 class MemoryBuffer;
1919
20 /// \brief A forward iterator which reads non-blank text lines from a buffer.
20 /// \brief A forward iterator which reads text lines from a buffer.
2121 ///
2222 /// This class provides a forward iterator interface for reading one line at
2323 /// a time from a buffer. When default constructed the iterator will be the
2424 /// "end" iterator.
2525 ///
26 /// The iterator also is aware of what line number it is currently processing
27 /// and can strip comment lines given the comment-starting character.
26 /// The iterator is aware of what line number it is currently processing. It
27 /// strips blank lines by default, and comment lines given a comment-starting
28 /// character.
2829 ///
2930 /// Note that this iterator requires the buffer to be nul terminated.
3031 class line_iterator
3132 : public std::iterator {
3233 const MemoryBuffer *Buffer;
3334 char CommentMarker;
35 bool SkipBlanks;
3436
3537 unsigned LineNumber;
3638 StringRef CurrentLine;
4042 line_iterator() : Buffer(nullptr) {}
4143
4244 /// \brief Construct a new iterator around some memory buffer.
43 explicit line_iterator(const MemoryBuffer &Buffer, char CommentMarker = '\0');
45 explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true,
46 char CommentMarker = '\0');
4447
4548 /// \brief Return true if we've reached EOF or are an "end" iterator.
4649 bool is_at_eof() const { return !Buffer; }
158158 return false;
159159 }
160160 MemoryBuffer &Buffer = *BufferOrErr.get();
161 line_iterator LineIt(Buffer, '#');
161 line_iterator LineIt(Buffer, /*SkipBlanks=*/true, '#');
162162
163163 // Read the profile of each function. Since each function may be
164164 // mentioned more than once, and we are collecting flat profiles,
1111
1212 using namespace llvm;
1313
14 line_iterator::line_iterator(const MemoryBuffer &Buffer, char CommentMarker)
14 line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks,
15 char CommentMarker)
1516 : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr),
16 CommentMarker(CommentMarker), LineNumber(1),
17 CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1),
1718 CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,
1819 0) {
1920 // Ensure that if we are constructed on a non-empty memory buffer that it is
2021 // a null terminated buffer.
2122 if (Buffer.getBufferSize()) {
2223 assert(Buffer.getBufferEnd()[0] == '\0');
23 advance();
24 // Make sure we don't skip a leading newline if we're keeping blanks
25 if (SkipBlanks || *Buffer.getBufferStart() != '\n')
26 advance();
2427 }
2528 }
2629
3033 const char *Pos = CurrentLine.end();
3134 assert(Pos == Buffer->getBufferStart() || *Pos == '\n' || *Pos == '\0');
3235
33 if (CommentMarker == '\0') {
36 if (*Pos == '\n') {
37 ++Pos;
38 ++LineNumber;
39 }
40 if (!SkipBlanks && *Pos == '\n') {
41 // Nothing to do for a blank line.
42 } else if (CommentMarker == '\0') {
3443 // If we're not stripping comments, this is simpler.
3544 size_t Blanks = 0;
3645 while (Pos[Blanks] == '\n')
4049 } else {
4150 // Skip comments and count line numbers, which is a bit more complex.
4251 for (;;) {
52 if (*Pos == '\n' && !SkipBlanks)
53 break;
4354 if (*Pos == CommentMarker)
4455 do {
4556 ++Pos;
6071
6172 // Measure the line.
6273 size_t Length = 0;
63 do {
74 while (Pos[Length] != '\0' && Pos[Length] != '\n') {
6475 ++Length;
65 } while (Pos[Length] != '\0' && Pos[Length] != '\n');
76 }
6677
6778 CurrentLine = StringRef(Pos, Length);
6879 }
205205 size_t CurrentHighlightRange = 0;
206206 size_t CurrentRegionMarker = 0;
207207
208 line_iterator Lines(File);
208 line_iterator Lines(File, /*SkipBlanks=*/false);
209209 // Advance the line iterator to the first line.
210210 while (Lines.line_number() < LineOffset)
211211 ++Lines;
227227 auto NextISV = InstantiationSubViews.begin();
228228 auto EndISV = InstantiationSubViews.end();
229229
230 for (size_t I = 0, E = LineStats.size(); I < E; ++I) {
231 unsigned LineNo = I + LineOffset;
230 for (size_t I = 0, E = LineStats.size(); I < E && !Lines.is_at_eof();
231 ++I, ++Lines) {
232 unsigned LineNo = Lines.line_number();
232233
233234 renderIndent(OS, IndentLevel);
234235 if (Options.ShowLineStats)
251252
252253 // Display the source code for the current line.
253254 StringRef Line = *Lines;
254 // Check if the line is empty, as line_iterator skips blank lines.
255 if (LineNo < Lines.line_number())
256 Line = "";
257 else if (!Lines.is_at_eof())
258 ++Lines;
259255 renderLine(OS, Line, LineRanges);
260256
261257 // Show the region markers.
3939 EXPECT_EQ(E, I);
4040 }
4141
42 TEST(LineIteratorTest, CommentSkipping) {
42 TEST(LineIteratorTest, CommentAndBlankSkipping) {
4343 std::unique_ptr Buffer(
4444 MemoryBuffer::getMemBuffer("line 1\n"
4545 "line 2\n"
4646 "# Comment 1\n"
47 "line 4\n"
47 "\n"
48 "line 5\n"
49 "\n"
4850 "# Comment 2"));
4951
50 line_iterator I = line_iterator(*Buffer, '#'), E;
52 line_iterator I = line_iterator(*Buffer, true, '#'), E;
5153
5254 EXPECT_FALSE(I.is_at_eof());
5355 EXPECT_NE(E, I);
5860 EXPECT_EQ("line 2", *I);
5961 EXPECT_EQ(2, I.line_number());
6062 ++I;
61 EXPECT_EQ("line 4", *I);
62 EXPECT_EQ(4, I.line_number());
63 EXPECT_EQ("line 5", *I);
64 EXPECT_EQ(5, I.line_number());
6365 ++I;
6466
6567 EXPECT_TRUE(I.is_at_eof());
6668 EXPECT_EQ(E, I);
6769 }
70
71 TEST(LineIteratorTest, CommentSkippingKeepBlanks) {
72 std::unique_ptr Buffer(
73 MemoryBuffer::getMemBuffer("line 1\n"
74 "line 2\n"
75 "# Comment 1\n"
76 "# Comment 2\n"
77 "\n"
78 "line 6\n"
79 "\n"
80 "# Comment 3"));
81
82 line_iterator I = line_iterator(*Buffer, false, '#'), E;
83
84 EXPECT_FALSE(I.is_at_eof());
85 EXPECT_NE(E, I);
86
87 EXPECT_EQ("line 1", *I);
88 EXPECT_EQ(1, I.line_number());
89 ++I;
90 EXPECT_EQ("line 2", *I);
91 EXPECT_EQ(2, I.line_number());
92 ++I;
93 EXPECT_EQ("", *I);
94 EXPECT_EQ(5, I.line_number());
95 ++I;
96 EXPECT_EQ("line 6", *I);
97 EXPECT_EQ(6, I.line_number());
98 ++I;
99 EXPECT_EQ("", *I);
100 EXPECT_EQ(7, I.line_number());
101 ++I;
102
103 EXPECT_TRUE(I.is_at_eof());
104 EXPECT_EQ(E, I);
105 }
106
68107
69108 TEST(LineIteratorTest, BlankSkipping) {
70109 std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("\n\n\n"
89128 EXPECT_EQ(E, I);
90129 }
91130
131 TEST(LineIteratorTest, BlankKeeping) {
132 std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("\n\n"
133 "line 3\n"
134 "\n"
135 "line 5\n"
136 "\n\n");
137 line_iterator I = line_iterator(*Buffer, false), E;
138
139 EXPECT_FALSE(I.is_at_eof());
140 EXPECT_NE(E, I);
141
142 EXPECT_EQ("", *I);
143 EXPECT_EQ(1, I.line_number());
144 ++I;
145 EXPECT_EQ("", *I);
146 EXPECT_EQ(2, I.line_number());
147 ++I;
148 EXPECT_EQ("line 3", *I);
149 EXPECT_EQ(3, I.line_number());
150 ++I;
151 EXPECT_EQ("", *I);
152 EXPECT_EQ(4, I.line_number());
153 ++I;
154 EXPECT_EQ("line 5", *I);
155 EXPECT_EQ(5, I.line_number());
156 ++I;
157 EXPECT_EQ("", *I);
158 EXPECT_EQ(6, I.line_number());
159 ++I;
160 EXPECT_EQ("", *I);
161 EXPECT_EQ(7, I.line_number());
162 ++I;
163
164 EXPECT_TRUE(I.is_at_eof());
165 EXPECT_EQ(E, I);
166 }
167
92168 TEST(LineIteratorTest, EmptyBuffers) {
93169 std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("");
94170 EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());
95171 EXPECT_EQ(line_iterator(), line_iterator(*Buffer));
172 EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof());
173 EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false));
96174
97175 Buffer = MemoryBuffer::getMemBuffer("\n\n\n");
98176 EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());
101179 Buffer = MemoryBuffer::getMemBuffer("# foo\n"
102180 "\n"
103181 "# bar");
104 EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof());
105 EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#'));
182 EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof());
183 EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#'));
106184
107185 Buffer = MemoryBuffer::getMemBuffer("\n"
108186 "# baz\n"
109187 "\n");
110 EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof());
111 EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#'));
188 EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof());
189 EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#'));
112190 }
113191
114192 } // anonymous namespace