]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/support/iterators/line_pos_iterator.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / support / iterators / line_pos_iterator.hpp
1 /*==============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2010 Bryce Lelbach
4 Copyright (c) 2014 Tomoki Imai
5
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 ==============================================================================*/
9
10 #if !defined(BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR)
11 #define BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
12
13 #include <boost/iterator/iterator_adaptor.hpp>
14 #include <boost/range/iterator_range_core.hpp>
15
16 namespace boost { namespace spirit
17 {
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
28 , Iterator // Base
29 , boost::use_default // Value
30 , boost::forward_traversal_tag // CategoryOrTraversal
31 > {
32 public:
33 line_pos_iterator();
34
35 explicit line_pos_iterator(Iterator);
36
37 std::size_t position() const;
38
39 private:
40 friend class boost::iterator_core_access;
41
42 void increment();
43
44 std::size_t line; // The line position.
45 typename std::iterator_traits<Iterator>::value_type prev;
46 };
47 //]
48
49 template <class Iterator>
50 line_pos_iterator<Iterator>::line_pos_iterator() :
51 line_pos_iterator::iterator_adaptor_(), line(1), prev(0) { }
52
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) { }
56
57 template <class Iterator>
58 std::size_t line_pos_iterator<Iterator>::position() const
59 {
60 return line;
61 }
62
63 template<class Iterator>
64 void line_pos_iterator<Iterator>::increment()
65 {
66 typename std::iterator_traits<Iterator>::reference
67 ref = *(this->base());
68
69 switch (ref) {
70 case '\r':
71 if (prev != '\n')
72 ++line;
73 break;
74 case '\n':
75 if (prev != '\r')
76 ++line;
77 break;
78 default:
79 break;
80 }
81
82 prev = ref;
83 ++this->base_reference();
84 }
85
86 //[line_pos_iterator_utilities
87 //`[heading get_line]
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`. */
92
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
97 iterator. */
98
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
105 iterator. */
106
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. */
112 //]
113
114 template <class Iterator>
115 inline std::size_t get_line(Iterator)
116 {
117 return -1;
118 }
119
120 template <class Iterator>
121 inline std::size_t get_line(line_pos_iterator<Iterator> i)
122 {
123 return i.position();
124 }
125
126 template <class Iterator>
127 inline Iterator get_line_start(Iterator lower_bound, Iterator current)
128 {
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) {
133 latest = i;
134 }
135 prev_was_newline = (*i == '\r') || (*i == '\n');
136 }
137 if (prev_was_newline) {
138 latest = current;
139 }
140 return latest;
141 }
142
143 template <class Iterator>
144 inline Iterator get_line_end(Iterator current, Iterator upper_bound)
145 {
146 for (Iterator i = current; i != upper_bound; ++i) {
147 if ((*i == '\n') || (*i == '\r')) {
148 return i;
149 }
150 }
151 return upper_bound;
152 }
153
154
155 template <class Iterator>
156 inline iterator_range<Iterator>
157 get_current_line(Iterator lower_bound,
158 Iterator current,
159 Iterator upper_bound)
160 {
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);
164 }
165
166 template <class Iterator>
167 inline std::size_t get_column(Iterator lower_bound,
168 Iterator current,
169 std::size_t tabs)
170 {
171 std::size_t column = 1;
172 Iterator first = get_line_start(lower_bound, current);
173
174 for (Iterator i = first; i != current; ++i) {
175 switch (*i) {
176 case '\t':
177 column += tabs - (column - 1) % tabs;
178 break;
179 default:
180 ++column;
181 }
182 }
183
184 return column;
185 }
186
187 }}
188
189 #endif // BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
190