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