Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:51

0001 /*==============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2010      Bryce Lelbach
0004     Copyright (c) 2014      Tomoki Imai
0005     Copyright (c) 2023      Kniazev Nikita
0006     Copyright (c) 2023      Tobias Loew
0007 
0008     Distributed under the Boost Software License, Version 1.0. (See accompanying
0009     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     //[line_pos_iterator_class
0022     /*`The `line_pos_iterator` is a lightweight line position iterator.
0023        This iterator adapter only stores the current line number, nothing else.
0024        Unlike __classic__'s `position_iterator`, it does not store the
0025        column number and does not need an end iterator. The current column can
0026        be computed, if needed.
0027        NOTE: line counting considers position inside multicharacter line-breaks
0028        (such as CRLF and LFCR) as being on the next line already. */
0029     //`[heading Class Reference]
0030     template <class Iterator>
0031     class line_pos_iterator : public boost::iterator_adaptor<
0032         line_pos_iterator<Iterator>  // Derived
0033       , Iterator                     // Base
0034       , boost::use_default           // Value
0035       , boost::forward_traversal_tag // CategoryOrTraversal
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; // The line position.
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 /* = 1 */ ) :
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     //[line_pos_iterator_utilities
0084     //`[heading get_line]
0085     template <class Iterator>
0086     inline std::size_t get_line(Iterator);
0087     /*`Get the line position. Returns -1 if Iterator is not a
0088        `line_pos_iterator`. */
0089 
0090     //`[heading get_line_start]
0091     template <class Iterator>
0092     inline Iterator get_line_start(Iterator lower_bound, Iterator current); 
0093     /*`Get an iterator to the beginning of the line. Applicable to any
0094        iterator. */
0095 
0096     //`[heading get_line_end]
0097     template <class Iterator>
0098     inline Iterator get_line_end(Iterator current, Iterator upper_bound);
0099     /*`Get an iterator to the end of the line. Applicable to any
0100        iterator. */
0101 
0102     //`[heading get_current_line]
0103     template <class Iterator>
0104     inline iterator_range<Iterator>
0105     get_current_line(Iterator lower_bound, Iterator current,
0106                      Iterator upper_bound); 
0107     /*`Get an `iterator_range` containing the current line. Applicable to any
0108        iterator. */ 
0109 
0110     //`[heading get_column]
0111     template <class Iterator>
0112     inline std::size_t get_column(Iterator lower_bound, Iterator current,
0113                                   std::size_t tabs = 4); 
0114     /*`Get the current column. Applicable to any iterator. */ 
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         // get_line_start for forward iterators: forward linear search starting from lower-bound
0131         // complexity: linear in length of [lower_bound, current)
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         // get_line_start for forward iterators: backward linear search starting from current
0150         // complexity: linear in avarage line-length
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         // No need in line number counting because it will be the same
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         // No need in line number counting because it will be the same
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 // BOOST_SPIRIT_SUPPORT_LINE_POS_ITERATOR
0250