136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===- LineIterator.cpp - Implementation of line iteration ----------------===// 236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// The LLVM Compiler Infrastructure 436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This file is distributed under the University of Illinois Open Source 636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// License. See LICENSE.TXT for details. 736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// 836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines//===----------------------------------------------------------------------===// 936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/LineIterator.h" 1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/MemoryBuffer.h" 1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesusing namespace llvm; 1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic bool isAtLineEnd(const char *P) { 1637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (*P == '\n') 1737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return true; 1837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (*P == '\r' && *(P + 1) == '\n') 1937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return true; 2037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return false; 2137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 2237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 2337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic bool skipIfAtLineEnd(const char *&P) { 2437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (*P == '\n') { 2537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++P; 2637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return true; 2737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 2837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (*P == '\r' && *(P + 1) == '\n') { 2937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines P += 2; 3037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return true; 3137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 3237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return false; 3337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 3437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 3537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesline_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks, 3637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines char CommentMarker) 37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr), 3837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1), 39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr, 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 0) { 4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Ensure that if we are constructed on a non-empty memory buffer that it is 4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // a null terminated buffer. 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Buffer.getBufferSize()) { 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Buffer.getBufferEnd()[0] == '\0'); 4537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Make sure we don't skip a leading newline if we're keeping blanks 4637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart())) 4737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines advance(); 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid line_iterator::advance() { 5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Buffer && "Cannot advance past the end!"); 5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const char *Pos = CurrentLine.end(); 5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines assert(Pos == Buffer->getBufferStart() || isAtLineEnd(Pos) || *Pos == '\0'); 5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (skipIfAtLineEnd(Pos)) 5837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++LineNumber; 5937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!SkipBlanks && isAtLineEnd(Pos)) { 6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Nothing to do for a blank line. 6137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } else if (CommentMarker == '\0') { 6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // If we're not stripping comments, this is simpler. 6337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines while (skipIfAtLineEnd(Pos)) 6437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ++LineNumber; 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Skip comments and count line numbers, which is a bit more complex. 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (;;) { 6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (isAtLineEnd(Pos) && !SkipBlanks) 6937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines break; 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (*Pos == CommentMarker) 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines do { 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Pos; 7337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } while (*Pos != '\0' && !isAtLineEnd(Pos)); 7437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!skipIfAtLineEnd(Pos)) 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++LineNumber; 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (*Pos == '\0') { 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // We've hit the end of the buffer, reset ourselves to the end state. 82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Buffer = nullptr; 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CurrentLine = StringRef(); 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Measure the line. 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines size_t Length = 0; 8937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines while (Pos[Length] != '\0' && !isAtLineEnd(&Pos[Length])) { 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++Length; 9137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CurrentLine = StringRef(Pos, Length); 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 95