10b57cec5SDimitry Andric //===- LineIterator.h - Iterator to read a text buffer's lines --*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_SUPPORT_LINEITERATOR_H 100b57cec5SDimitry Andric #define LLVM_SUPPORT_LINEITERATOR_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 130b57cec5SDimitry Andric #include "llvm/Support/DataTypes.h" 14e8d8bef9SDimitry Andric #include "llvm/Support/MemoryBufferRef.h" 150b57cec5SDimitry Andric #include <iterator> 16*bdd1243dSDimitry Andric #include <optional> 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric namespace llvm { 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric class MemoryBuffer; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric /// A forward iterator which reads text lines from a buffer. 230b57cec5SDimitry Andric /// 240b57cec5SDimitry Andric /// This class provides a forward iterator interface for reading one line at 250b57cec5SDimitry Andric /// a time from a buffer. When default constructed the iterator will be the 260b57cec5SDimitry Andric /// "end" iterator. 270b57cec5SDimitry Andric /// 280b57cec5SDimitry Andric /// The iterator is aware of what line number it is currently processing. It 290b57cec5SDimitry Andric /// strips blank lines by default, and comment lines given a comment-starting 300b57cec5SDimitry Andric /// character. 310b57cec5SDimitry Andric /// 320b57cec5SDimitry Andric /// Note that this iterator requires the buffer to be nul terminated. 33fe6060f1SDimitry Andric class line_iterator { 34*bdd1243dSDimitry Andric std::optional<MemoryBufferRef> Buffer; 35480093f4SDimitry Andric char CommentMarker = '\0'; 36480093f4SDimitry Andric bool SkipBlanks = true; 370b57cec5SDimitry Andric 38480093f4SDimitry Andric unsigned LineNumber = 1; 390b57cec5SDimitry Andric StringRef CurrentLine; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric public: 42fe6060f1SDimitry Andric using iterator_category = std::forward_iterator_tag; 43fe6060f1SDimitry Andric using value_type = StringRef; 44fe6060f1SDimitry Andric using difference_type = std::ptrdiff_t; 45fe6060f1SDimitry Andric using pointer = value_type *; 46fe6060f1SDimitry Andric using reference = value_type &; 47fe6060f1SDimitry Andric 480b57cec5SDimitry Andric /// Default construct an "end" iterator. 49480093f4SDimitry Andric line_iterator() = default; 500b57cec5SDimitry Andric 51e8d8bef9SDimitry Andric /// Construct a new iterator around an unowned memory buffer. 52e8d8bef9SDimitry Andric explicit line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks = true, 53e8d8bef9SDimitry Andric char CommentMarker = '\0'); 54e8d8bef9SDimitry Andric 550b57cec5SDimitry Andric /// Construct a new iterator around some memory buffer. 560b57cec5SDimitry Andric explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true, 570b57cec5SDimitry Andric char CommentMarker = '\0'); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric /// Return true if we've reached EOF or are an "end" iterator. is_at_eof()600b57cec5SDimitry Andric bool is_at_eof() const { return !Buffer; } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Return true if we're an "end" iterator or have reached EOF. is_at_end()630b57cec5SDimitry Andric bool is_at_end() const { return is_at_eof(); } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// Return the current line number. May return any number at EOF. line_number()660b57cec5SDimitry Andric int64_t line_number() const { return LineNumber; } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric /// Advance to the next (non-empty, non-comment) line. 690b57cec5SDimitry Andric line_iterator &operator++() { 700b57cec5SDimitry Andric advance(); 710b57cec5SDimitry Andric return *this; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric line_iterator operator++(int) { 740b57cec5SDimitry Andric line_iterator tmp(*this); 750b57cec5SDimitry Andric advance(); 760b57cec5SDimitry Andric return tmp; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Get the current line as a \c StringRef. 800b57cec5SDimitry Andric StringRef operator*() const { return CurrentLine; } 810b57cec5SDimitry Andric const StringRef *operator->() const { return &CurrentLine; } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) { 840b57cec5SDimitry Andric return LHS.Buffer == RHS.Buffer && 850b57cec5SDimitry Andric LHS.CurrentLine.begin() == RHS.CurrentLine.begin(); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric friend bool operator!=(const line_iterator &LHS, const line_iterator &RHS) { 890b57cec5SDimitry Andric return !(LHS == RHS); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric private: 930b57cec5SDimitry Andric /// Advance the iterator to the next line. 940b57cec5SDimitry Andric void advance(); 950b57cec5SDimitry Andric }; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric #endif 99