123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*==============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2010 Bryce Lelbach
- Copyright (c) 2014 Tomoki Imai
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- ==============================================================================*/
- #if !defined(BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR)
- #define BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
- #include <boost/iterator/iterator_adaptor.hpp>
- #include <boost/range/iterator_range.hpp>
- namespace boost { namespace spirit
- {
- //[line_pos_iterator_class
- /*`The `line_pos_iterator` is a lightweight line position iterator.
- This iterator adapter only stores the current line number, nothing else.
- Unlike __classic__'s `position_iterator`, it does not store the
- column number and does not need an end iterator. The current column can
- be computed, if needed. */
- //`[heading Class Reference]
- template <class Iterator>
- class line_pos_iterator : public boost::iterator_adaptor<
- line_pos_iterator<Iterator> // Derived
- , Iterator // Base
- , boost::use_default // Value
- , boost::forward_traversal_tag // CategoryOrTraversal
- > {
- public:
- line_pos_iterator();
- explicit line_pos_iterator(Iterator);
- std::size_t position() const;
- private:
- friend class boost::iterator_core_access;
- void increment();
- std::size_t line; // The line position.
- typename std::iterator_traits<Iterator>::value_type prev;
- };
- //]
- template <class Iterator>
- line_pos_iterator<Iterator>::line_pos_iterator() :
- line_pos_iterator::iterator_adaptor_(), line(1), prev(0) { }
- template <class Iterator>
- line_pos_iterator<Iterator>::line_pos_iterator(Iterator base) :
- line_pos_iterator::iterator_adaptor_(base), line(1), prev(0) { }
- template <class Iterator>
- std::size_t line_pos_iterator<Iterator>::position() const
- {
- return line;
- }
-
- template<class Iterator>
- void line_pos_iterator<Iterator>::increment()
- {
- typename std::iterator_traits<Iterator>::reference
- ref = *(this->base());
-
- switch (ref) {
- case '\r':
- if (prev != '\n')
- ++line;
- break;
- case '\n':
- if (prev != '\r')
- ++line;
- break;
- default:
- break;
- }
-
- prev = ref;
- ++this->base_reference();
- }
- //[line_pos_iterator_utilities
- //`[heading get_line]
- template <class Iterator>
- inline std::size_t get_line(Iterator);
- /*`Get the line position. Returns -1 if Iterator is not a
- `line_pos_iterator`. */
- //`[heading get_line_start]
- template <class Iterator>
- inline Iterator get_line_start(Iterator lower_bound, Iterator current);
- /*`Get an iterator to the beginning of the line. Applicable to any
- iterator. */
- //`[heading get_current_line]
- template <class Iterator>
- inline iterator_range<Iterator>
- get_current_line(Iterator lower_bound, Iterator current,
- Iterator upper_bound);
- /*`Get an `iterator_range` containing the current line. Applicable to any
- iterator. */
- //`[heading get_column]
- template <class Iterator>
- inline std::size_t get_column(Iterator lower_bound, Iterator current,
- std::size_t tabs = 4);
- /*`Get the current column. Applicable to any iterator. */
- //]
- template <class Iterator>
- inline std::size_t get_line(Iterator)
- {
- return -1;
- }
-
- template <class Iterator>
- inline std::size_t get_line(line_pos_iterator<Iterator> i)
- {
- return i.position();
- }
-
- template <class Iterator>
- inline Iterator get_line_start(Iterator lower_bound, Iterator current)
- {
- Iterator latest = lower_bound;
- bool prev_was_newline = false;
- for (Iterator i = lower_bound; i != current; ++i) {
- if (prev_was_newline) {
- latest = i;
- }
- prev_was_newline = (*i == '\r') || (*i == '\n');
- }
- if (prev_was_newline) {
- latest = current;
- }
- return latest;
- }
- template <class Iterator>
- inline Iterator get_line_end(Iterator current, Iterator upper_bound)
- {
- for (Iterator i = current; i != upper_bound; ++i) {
- if ((*i == '\n') || (*i == '\r')) {
- return i;
- }
- }
- return upper_bound;
- }
-
- template <class Iterator>
- inline iterator_range<Iterator>
- get_current_line(Iterator lower_bound,
- Iterator current,
- Iterator upper_bound)
- {
- Iterator first = get_line_start(lower_bound, current);
- Iterator last = get_line_end(current, upper_bound);
- return iterator_range<Iterator>(first, last);
- }
-
- template <class Iterator>
- inline std::size_t get_column(Iterator lower_bound,
- Iterator current,
- std::size_t tabs)
- {
- std::size_t column = 1;
- Iterator first = get_line_start(lower_bound, current);
-
- for (Iterator i = first; i != current; ++i) {
- switch (*i) {
- case '\t':
- column += tabs - (column - 1) % tabs;
- break;
- default:
- ++column;
- }
- }
-
- return column;
- }
- }}
- #endif // BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
|