1 /*==============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2010 Bryce Lelbach
4 Copyright (c) 2014 Tomoki Imai
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ==============================================================================*/
10 #if !defined(BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR)
11 #define BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
13 #include <boost/iterator/iterator_adaptor.hpp>
14 #include <boost/range/iterator_range_core.hpp>
16 namespace boost { namespace spirit
18 //[line_pos_iterator_class
19 /*`The `line_pos_iterator` is a lightweight line position iterator.
20 This iterator adapter only stores the current line number, nothing else.
21 Unlike __classic__'s `position_iterator`, it does not store the
22 column number and does not need an end iterator. The current column can
23 be computed, if needed. */
24 //`[heading Class Reference]
25 template <class Iterator>
26 class line_pos_iterator : public boost::iterator_adaptor<
27 line_pos_iterator<Iterator> // Derived
29 , boost::use_default // Value
30 , boost::forward_traversal_tag // CategoryOrTraversal
35 explicit line_pos_iterator(Iterator);
37 std::size_t position() const;
40 friend class boost::iterator_core_access;
44 std::size_t line; // The line position.
45 typename std::iterator_traits<Iterator>::value_type prev;
49 template <class Iterator>
50 line_pos_iterator<Iterator>::line_pos_iterator() :
51 line_pos_iterator::iterator_adaptor_(), line(1), prev(0) { }
53 template <class Iterator>
54 line_pos_iterator<Iterator>::line_pos_iterator(Iterator base) :
55 line_pos_iterator::iterator_adaptor_(base), line(1), prev(0) { }
57 template <class Iterator>
58 std::size_t line_pos_iterator<Iterator>::position() const
63 template<class Iterator>
64 void line_pos_iterator<Iterator>::increment()
66 typename std::iterator_traits<Iterator>::reference
67 ref = *(this->base());
83 ++this->base_reference();
86 //[line_pos_iterator_utilities
88 template <class Iterator>
89 inline std::size_t get_line(Iterator);
90 /*`Get the line position. Returns -1 if Iterator is not a
91 `line_pos_iterator`. */
93 //`[heading get_line_start]
94 template <class Iterator>
95 inline Iterator get_line_start(Iterator lower_bound, Iterator current);
96 /*`Get an iterator to the beginning of the line. Applicable to any
99 //`[heading get_current_line]
100 template <class Iterator>
101 inline iterator_range<Iterator>
102 get_current_line(Iterator lower_bound, Iterator current,
103 Iterator upper_bound);
104 /*`Get an `iterator_range` containing the current line. Applicable to any
107 //`[heading get_column]
108 template <class Iterator>
109 inline std::size_t get_column(Iterator lower_bound, Iterator current,
110 std::size_t tabs = 4);
111 /*`Get the current column. Applicable to any iterator. */
114 template <class Iterator>
115 inline std::size_t get_line(Iterator)
120 template <class Iterator>
121 inline std::size_t get_line(line_pos_iterator<Iterator> i)
126 template <class Iterator>
127 inline Iterator get_line_start(Iterator lower_bound, Iterator current)
129 Iterator latest = lower_bound;
130 bool prev_was_newline = false;
131 for (Iterator i = lower_bound; i != current; ++i) {
132 if (prev_was_newline) {
135 prev_was_newline = (*i == '\r') || (*i == '\n');
137 if (prev_was_newline) {
143 template <class Iterator>
144 inline Iterator get_line_end(Iterator current, Iterator upper_bound)
146 for (Iterator i = current; i != upper_bound; ++i) {
147 if ((*i == '\n') || (*i == '\r')) {
155 template <class Iterator>
156 inline iterator_range<Iterator>
157 get_current_line(Iterator lower_bound,
159 Iterator upper_bound)
161 Iterator first = get_line_start(lower_bound, current);
162 Iterator last = get_line_end(current, upper_bound);
163 return iterator_range<Iterator>(first, last);
166 template <class Iterator>
167 inline std::size_t get_column(Iterator lower_bound,
171 std::size_t column = 1;
172 Iterator first = get_line_start(lower_bound, current);
174 for (Iterator i = first; i != current; ++i) {
177 column += tabs - (column - 1) % tabs;
189 #endif // BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR