File indexing completed on 2025-01-19 09:47:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #if !defined(BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR)
0013 #define BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
0014
0015 #include <boost/iterator/iterator_adaptor.hpp>
0016 #include <boost/range/iterator_range_core.hpp>
0017 #include <iterator>
0018
0019 namespace boost { namespace spirit
0020 {
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template <class Iterator>
0031 class line_pos_iterator : public boost::iterator_adaptor<
0032 line_pos_iterator<Iterator>
0033 , Iterator
0034 , boost::use_default
0035 , boost::forward_traversal_tag
0036 > {
0037 public:
0038 line_pos_iterator();
0039
0040 explicit line_pos_iterator(Iterator, std::size_t line_start = 1);
0041
0042 std::size_t position() const;
0043
0044 private:
0045 friend class boost::iterator_core_access;
0046
0047 void increment();
0048
0049 std::size_t line;
0050 bool prev_n;
0051 bool prev_r;
0052 };
0053
0054
0055 template <class Iterator>
0056 line_pos_iterator<Iterator>::line_pos_iterator() :
0057 line_pos_iterator::iterator_adaptor_(), line(1), prev_n(), prev_r() { }
0058
0059 template <class Iterator>
0060 line_pos_iterator<Iterator>::line_pos_iterator(Iterator base, std::size_t line_start ) :
0061 line_pos_iterator::iterator_adaptor_(base), line(line_start), prev_n(), prev_r() { }
0062
0063 template <class Iterator>
0064 std::size_t line_pos_iterator<Iterator>::position() const
0065 {
0066 return line;
0067 }
0068
0069 template<class Iterator>
0070 void line_pos_iterator<Iterator>::increment()
0071 {
0072 typename std::iterator_traits<Iterator>::reference
0073 ch = *(this->base());
0074
0075 int newline = ((ch == '\n') & !prev_r) | ((ch == '\r') & !prev_n);
0076 line += newline;
0077 prev_r = (ch == '\r') & newline;
0078 prev_n = (ch == '\n') & newline;
0079
0080 ++this->base_reference();
0081 }
0082
0083
0084
0085 template <class Iterator>
0086 inline std::size_t get_line(Iterator);
0087
0088
0089
0090
0091 template <class Iterator>
0092 inline Iterator get_line_start(Iterator lower_bound, Iterator current);
0093
0094
0095
0096
0097 template <class Iterator>
0098 inline Iterator get_line_end(Iterator current, Iterator upper_bound);
0099
0100
0101
0102
0103 template <class Iterator>
0104 inline iterator_range<Iterator>
0105 get_current_line(Iterator lower_bound, Iterator current,
0106 Iterator upper_bound);
0107
0108
0109
0110
0111 template <class Iterator>
0112 inline std::size_t get_column(Iterator lower_bound, Iterator current,
0113 std::size_t tabs = 4);
0114
0115
0116
0117 template <class Iterator>
0118 inline std::size_t get_line(Iterator)
0119 {
0120 return -1;
0121 }
0122
0123 template <class Iterator>
0124 inline std::size_t get_line(line_pos_iterator<Iterator> i)
0125 {
0126 return i.position();
0127 }
0128
0129 namespace detail {
0130
0131
0132 template <class Iterator>
0133 inline Iterator get_line_start(Iterator lower_bound,
0134 Iterator current,
0135 std::forward_iterator_tag)
0136 {
0137 Iterator latest = lower_bound;
0138 for (Iterator it = lower_bound; it != current; ) {
0139 if ((*it == '\r') || (*it == '\n')) {
0140 latest = ++it;
0141 }
0142 else {
0143 ++it;
0144 }
0145 }
0146 return latest;
0147 }
0148
0149
0150
0151 template <class Iterator>
0152 inline Iterator get_line_start(Iterator lower_bound,
0153 Iterator current,
0154 std::bidirectional_iterator_tag)
0155 {
0156 while (current != lower_bound) {
0157 --current;
0158 if ((*current == '\r') || (*current == '\n')) {
0159 return ++current;
0160 }
0161 }
0162 return current;
0163 }
0164 }
0165
0166 template <class Iterator>
0167 inline Iterator get_line_start(Iterator lower_bound, Iterator current)
0168 {
0169 return detail::get_line_start(
0170 lower_bound,
0171 current,
0172 typename std::iterator_traits<Iterator>::iterator_category()
0173 );
0174 }
0175
0176 template <class Iterator>
0177 inline line_pos_iterator<Iterator>
0178 get_line_start(line_pos_iterator<Iterator> lower_bound,
0179 line_pos_iterator<Iterator> current)
0180 {
0181
0182 Iterator it = get_line_start(lower_bound.base(), current.base());
0183 return line_pos_iterator<Iterator>(it, current.position());
0184 }
0185
0186 template <class Iterator>
0187 inline Iterator get_line_end(Iterator current, Iterator upper_bound)
0188 {
0189 for (Iterator i = current; i != upper_bound; ++i) {
0190 if ((*i == '\n') || (*i == '\r')) {
0191 return i;
0192 }
0193 }
0194 return upper_bound;
0195 }
0196
0197 template <class Iterator>
0198 inline line_pos_iterator<Iterator>
0199 get_line_end(line_pos_iterator<Iterator> current,
0200 line_pos_iterator<Iterator> upper_bound)
0201 {
0202
0203 Iterator it = get_line_end(current.base(), upper_bound.base());
0204 return line_pos_iterator<Iterator>(it, current.position());
0205 }
0206
0207 template <class Iterator>
0208 inline iterator_range<Iterator>
0209 get_current_line(Iterator lower_bound,
0210 Iterator current,
0211 Iterator upper_bound)
0212 {
0213 Iterator first = get_line_start(lower_bound, current);
0214 Iterator last = get_line_end(current, upper_bound);
0215 return iterator_range<Iterator>(first, last);
0216 }
0217
0218 template <class Iterator>
0219 inline std::size_t get_column(Iterator lower_bound,
0220 Iterator current,
0221 std::size_t tabs)
0222 {
0223 std::size_t column = 1;
0224 Iterator first = get_line_start(lower_bound, current);
0225
0226 for (Iterator i = first; i != current; ++i) {
0227 switch (*i) {
0228 case '\t':
0229 column += tabs - (column - 1) % tabs;
0230 break;
0231 default:
0232 ++column;
0233 }
0234 }
0235
0236 return column;
0237 }
0238
0239 template <class Iterator>
0240 inline std::size_t get_column(line_pos_iterator<Iterator> lower_bound,
0241 line_pos_iterator<Iterator> current,
0242 std::size_t tabs = 4)
0243 {
0244 return get_column(lower_bound.base(), current.base(), tabs);
0245 }
0246
0247 }}
0248
0249 #endif
0250