1 //===- LineIterator.cpp - Implementation of line iteration ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Support/LineIterator.h" 11 #include "llvm/Support/MemoryBuffer.h" 12 13 using namespace llvm; 14 15 static bool isAtLineEnd(const char *P) { 16 if (*P == '\n') 17 return true; 18 if (*P == '\r' && *(P + 1) == '\n') 19 return true; 20 return false; 21 } 22 23 static bool skipIfAtLineEnd(const char *&P) { 24 if (*P == '\n') { 25 ++P; 26 return true; 27 } 28 if (*P == '\r' && *(P + 1) == '\n') { 29 P += 2; 30 return true; 31 } 32 return false; 33 } 34 35 line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks, 36 char CommentMarker) 37 : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr), 38 CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1), 39 CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr, 40 0) { 41 // Ensure that if we are constructed on a non-empty memory buffer that it is 42 // a null terminated buffer. 43 if (Buffer.getBufferSize()) { 44 assert(Buffer.getBufferEnd()[0] == '\0'); 45 // Make sure we don't skip a leading newline if we're keeping blanks 46 if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart())) 47 advance(); 48 } 49 } 50 51 void line_iterator::advance() { 52 assert(Buffer && "Cannot advance past the end!"); 53 54 const char *Pos = CurrentLine.end(); 55 assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0'); 56 57 if (skipIfAtLineEnd(Pos)) 58 ++LineNumber; 59 if (!SkipBlanks && isAtLineEnd(Pos)) { 60 // Nothing to do for a blank line. 61 } else if (CommentMarker == '\0') { 62 // If we're not stripping comments, this is simpler. 63 while (skipIfAtLineEnd(Pos)) 64 ++LineNumber; 65 } else { 66 // Skip comments and count line numbers, which is a bit more complex. 67 for (;;) { 68 if (isAtLineEnd(Pos) && !SkipBlanks) 69 break; 70 if (*Pos == CommentMarker) 71 do { 72 ++Pos; 73 } while (*Pos != '\0' && !isAtLineEnd(Pos)); 74 if (!skipIfAtLineEnd(Pos)) 75 break; 76 ++LineNumber; 77 } 78 } 79 80 if (*Pos == '\0') { 81 // We've hit the end of the buffer, reset ourselves to the end state. 82 Buffer = nullptr; 83 CurrentLine = StringRef(); 84 return; 85 } 86 87 // Measure the line. 88 size_t Length = 0; 89 while (Pos[Length] != '\0' && !isAtLineEnd(&Pos[Length])) { 90 ++Length; 91 } 92 93 CurrentLine = StringRef(Pos, Length); 94 } 95