| 68 | // delimiter. |
| 69 | template <typename Delimiter, typename Predicate = NoFilter> |
| 70 | class SplitIterator |
| 71 | : public std::iterator<std::input_iterator_tag, StringPiece> { |
| 72 | public: |
| 73 | // Two constructors for "end" iterators. |
| 74 | explicit SplitIterator(Delimiter d) |
| 75 | : delimiter_(std::move(d)), predicate_(), is_end_(true) {} |
| 76 | SplitIterator(Delimiter d, Predicate p) |
| 77 | : delimiter_(std::move(d)), predicate_(std::move(p)), is_end_(true) {} |
| 78 | // Two constructors taking the text to iterator. |
| 79 | SplitIterator(StringPiece text, Delimiter d) |
| 80 | : text_(std::move(text)), |
| 81 | delimiter_(std::move(d)), |
| 82 | predicate_(), |
| 83 | is_end_(false) { |
| 84 | ++(*this); |
| 85 | } |
| 86 | SplitIterator(StringPiece text, Delimiter d, Predicate p) |
| 87 | : text_(std::move(text)), |
| 88 | delimiter_(std::move(d)), |
| 89 | predicate_(std::move(p)), |
| 90 | is_end_(false) { |
| 91 | ++(*this); |
| 92 | } |
| 93 | |
| 94 | StringPiece operator*() { return curr_piece_; } |
| 95 | StringPiece* operator->() { return &curr_piece_; } |
| 96 | |
| 97 | SplitIterator& operator++() { |
| 98 | do { |
| 99 | if (text_.end() == curr_piece_.end()) { |
| 100 | // Already consumed all of text_, so we're done. |
| 101 | is_end_ = true; |
| 102 | return *this; |
| 103 | } |
| 104 | StringPiece found_delimiter = delimiter_.Find(text_); |
| 105 | assert(found_delimiter.data() != NULL); |
| 106 | assert(text_.begin() <= found_delimiter.begin()); |
| 107 | assert(found_delimiter.end() <= text_.end()); |
| 108 | // found_delimiter is allowed to be empty. |
| 109 | // Sets curr_piece_ to all text up to but excluding the delimiter itself. |
| 110 | // Sets text_ to remaining data after the delimiter. |
| 111 | curr_piece_.set(text_.begin(), found_delimiter.begin() - text_.begin()); |
| 112 | text_.remove_prefix(found_delimiter.end() - text_.begin()); |
| 113 | } while (!predicate_(curr_piece_)); |
| 114 | return *this; |
| 115 | } |
| 116 | |
| 117 | SplitIterator operator++(int /* postincrement */) { |
| 118 | SplitIterator old(*this); |
| 119 | ++(*this); |
| 120 | return old; |
| 121 | } |
| 122 | |
| 123 | bool operator==(const SplitIterator& other) const { |
| 124 | // Two "end" iterators are always equal. If the two iterators being compared |
| 125 | // aren't both end iterators, then we fallback to comparing their fields. |
| 126 | // Importantly, the text being split must be equal and the current piece |
| 127 | // within the text being split must also be equal. The delimiter_ and |