LCOV - code coverage report
Current view: top level - usr/include/boost/spirit/home/classic/iterator - multi_pass.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 72 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*=============================================================================
       2             :     Copyright (c) 2001, Daniel C. Nuffer
       3             :     http://spirit.sourceforge.net/
       4             : 
       5             :   Distributed under the Boost Software License, Version 1.0. (See accompanying
       6             :   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7             : =============================================================================*/
       8             : #ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
       9             : #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
      10             : 
      11             : #include <boost/config.hpp>
      12             : #include <boost/throw_exception.hpp>
      13             : #include <deque>
      14             : #include <iterator>
      15             : #include <iostream>
      16             : #include <algorithm>    // for std::swap
      17             : #include <exception>    // for std::exception
      18             : #include <boost/limits.hpp>
      19             : 
      20             : #include <boost/spirit/home/classic/namespace.hpp>
      21             : #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
      22             : #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp>
      23             : 
      24             : #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp>
      25             : 
      26             : namespace boost { namespace spirit {
      27             : 
      28             : BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
      29             : 
      30             : namespace impl {
      31             :     template <typename T>
      32             :     inline void mp_swap(T& t1, T& t2);
      33             : }
      34             : 
      35             : namespace multi_pass_policies
      36             : {
      37             : 
      38             : ///////////////////////////////////////////////////////////////////////////////
      39             : // class ref_counted
      40             : // Implementation of an OwnershipPolicy used by multi_pass.
      41             : //
      42             : // Implementation modified from RefCounted class from the Loki library by
      43             : // Andrei Alexandrescu
      44             : ///////////////////////////////////////////////////////////////////////////////
      45             : class ref_counted
      46             : {
      47             :     protected:
      48           0 :         ref_counted()
      49           0 :             : count(new std::size_t(1))
      50             :         {}
      51             : 
      52             :         ref_counted(ref_counted const& x)
      53             :             : count(x.count)
      54             :         {}
      55             : 
      56             :         // clone is called when a copy of the iterator is made, so increment
      57             :         // the ref-count.
      58             :         void clone()
      59             :         {
      60             :             ++*count;
      61             :         }
      62             : 
      63             :         // called when a copy is deleted.  Decrement the ref-count.  Return
      64             :         // value of true indicates that the last copy has been released.
      65           0 :         bool release()
      66             :         {
      67           0 :             if (!--*count)
      68             :             {
      69           0 :                 delete count;
      70           0 :                 count = 0;
      71           0 :                 return true;
      72             :             }
      73             :             return false;
      74             :         }
      75             : 
      76             :         void swap(ref_counted& x)
      77             :         {
      78             :             impl::mp_swap(count, x.count);
      79             :         }
      80             : 
      81             :     public:
      82             :         // returns true if there is only one iterator in existence.
      83             :         // std_deque StoragePolicy will free it's buffered data if this
      84             :         // returns true.
      85           0 :         bool unique() const
      86             :         {
      87           0 :             return *count == 1;
      88             :         }
      89             : 
      90             :     private:
      91             :         std::size_t* count;
      92             : };
      93             : 
      94             : ///////////////////////////////////////////////////////////////////////////////
      95             : // class first_owner
      96             : // Implementation of an OwnershipPolicy used by multi_pass
      97             : // This ownership policy dictates that the first iterator created will
      98             : // determine the lifespan of the shared components.  This works well for
      99             : // spirit, since no dynamic allocation of iterators is done, and all copies
     100             : // are make on the stack.
     101             : //
     102             : // There is a caveat about using this policy together with the std_deque
     103             : // StoragePolicy. Since first_owner always returns false from unique(),
     104             : // std_deque will only release the queued data if clear_queue() is called.
     105             : ///////////////////////////////////////////////////////////////////////////////
     106             : class first_owner
     107             : {
     108             :     protected:
     109             :         first_owner()
     110             :             : first(true)
     111             :         {}
     112             : 
     113             :         first_owner(first_owner const&)
     114             :             : first(false)
     115             :         {}
     116             : 
     117             :         void clone()
     118             :         {
     119             :         }
     120             : 
     121             :         // return true to indicate deletion of resources
     122             :         bool release()
     123             :         {
     124             :             return first;
     125             :         }
     126             : 
     127             :         void swap(first_owner&)
     128             :         {
     129             :             // if we're the first, we still remain the first, even if assigned
     130             :             // to, so don't swap first_.  swap is only called from operator=
     131             :         }
     132             : 
     133             :     public:
     134             :         bool unique() const
     135             :         {
     136             :             return false; // no way to know, so always return false
     137             :         }
     138             : 
     139             :     private:
     140             :         bool first;
     141             : };
     142             : 
     143             : ///////////////////////////////////////////////////////////////////////////////
     144             : // class illegal_backtracking
     145             : // thrown by buf_id_check CheckingPolicy if an instance of an iterator is
     146             : // used after another one has invalidated the queue
     147             : ///////////////////////////////////////////////////////////////////////////////
     148             : class BOOST_SYMBOL_VISIBLE illegal_backtracking : public std::exception
     149             : {
     150             : public:
     151             : 
     152             :     illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
     153           0 :     ~illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
     154             : 
     155             :     virtual const char*
     156           0 :     what() const BOOST_NOEXCEPT_OR_NOTHROW
     157           0 :     { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; }
     158             : };
     159             : 
     160             : ///////////////////////////////////////////////////////////////////////////////
     161             : // class buf_id_check
     162             : // Implementation of the CheckingPolicy used by multi_pass
     163             : // This policy is most effective when used together with the std_deque
     164             : // StoragePolicy.
     165             : // If used with the fixed_size_queue StoragePolicy, it will not detect
     166             : // iterator derefereces that are out of the range of the queue.
     167             : ///////////////////////////////////////////////////////////////////////////////
     168             : class buf_id_check
     169             : {
     170             :     protected:
     171           0 :         buf_id_check()
     172           0 :             : shared_buf_id(new unsigned long(0))
     173           0 :             , buf_id(0)
     174             :         {}
     175             : 
     176             :         buf_id_check(buf_id_check const& x)
     177             :             : shared_buf_id(x.shared_buf_id)
     178             :             , buf_id(x.buf_id)
     179             :         {}
     180             : 
     181             :         // will be called from the destructor of the last iterator.
     182           0 :         void destroy()
     183             :         {
     184           0 :             delete shared_buf_id;
     185           0 :             shared_buf_id = 0;
     186             :         }
     187             : 
     188             :         void swap(buf_id_check& x)
     189             :         {
     190             :             impl::mp_swap(shared_buf_id, x.shared_buf_id);
     191             :             impl::mp_swap(buf_id, x.buf_id);
     192             :         }
     193             : 
     194             :         // called to verify that everything is okay.
     195             :         void check_if_valid() const
     196             :         {
     197             :             if (buf_id != *shared_buf_id)
     198             :             {
     199             :                 boost::throw_exception(illegal_backtracking());
     200             :             }
     201             :         }
     202             : 
     203             :         // called from multi_pass::clear_queue, so we can increment the count
     204             :         void clear_queue()
     205             :         {
     206             :             ++*shared_buf_id;
     207             :             ++buf_id;
     208             :         }
     209             : 
     210             :     private:
     211             :         unsigned long* shared_buf_id;
     212             :         unsigned long buf_id;
     213             : };
     214             : 
     215             : ///////////////////////////////////////////////////////////////////////////////
     216             : // class no_check
     217             : // Implementation of the CheckingPolicy used by multi_pass
     218             : // It does not do anything :-)
     219             : ///////////////////////////////////////////////////////////////////////////////
     220             : class no_check
     221             : {
     222             :     protected:
     223             :         no_check() {}
     224             :         no_check(no_check const&) {}
     225             :         void destroy() {}
     226             :         void swap(no_check&) {}
     227             :         void check_if_valid() const {}
     228             :         void clear_queue() {}
     229             : };
     230             : 
     231             : ///////////////////////////////////////////////////////////////////////////////
     232             : // class std_deque
     233             : // Implementation of the StoragePolicy used by multi_pass
     234             : // This stores all data in a std::deque, and keeps an offset to the current
     235             : // position. It stores all the data unless there is only one
     236             : // iterator using the queue.
     237             : // Note: a position is used instead of an iterator, because a push_back on
     238             : // a deque can invalidate any iterators.
     239             : ///////////////////////////////////////////////////////////////////////////////
     240             : class std_deque
     241             : {
     242             :     public:
     243             : 
     244             : template <typename ValueT>
     245             : class inner
     246             : {
     247             :     private:
     248             : 
     249             :         typedef std::deque<ValueT> queue_type;
     250             :         queue_type* queuedElements;
     251             :         mutable typename queue_type::size_type queuePosition;
     252             : 
     253             :     protected:
     254           0 :         inner()
     255           0 :             : queuedElements(new queue_type)
     256           0 :             , queuePosition(0)
     257           0 :         {}
     258             : 
     259             :         inner(inner const& x)
     260             :             : queuedElements(x.queuedElements)
     261             :             , queuePosition(x.queuePosition)
     262             :         {}
     263             : 
     264             :         // will be called from the destructor of the last iterator.
     265             :         void destroy()
     266             :         {
     267             :             BOOST_SPIRIT_ASSERT(NULL != queuedElements);
     268             :             delete queuedElements;
     269             :             queuedElements = 0;
     270             :         }
     271             : 
     272             :         void swap(inner& x)
     273             :         {
     274             :             impl::mp_swap(queuedElements, x.queuedElements);
     275             :             impl::mp_swap(queuePosition, x.queuePosition);
     276             :         }
     277             : 
     278             :         // This is called when the iterator is dereferenced.  It's a template
     279             :         // method so we can recover the type of the multi_pass iterator
     280             :         // and call unique and access the m_input data member.
     281             :         template <typename MultiPassT>
     282           0 :         static typename MultiPassT::reference dereference(MultiPassT const& mp)
     283             :         {
     284           0 :             if (mp.queuePosition == mp.queuedElements->size())
     285             :             {
     286             :                 // check if this is the only iterator
     287           0 :                 if (mp.unique())
     288             :                 {
     289             :                     // free up the memory used by the queue.
     290           0 :                     if (mp.queuedElements->size() > 0)
     291             :                     {
     292           0 :                         mp.queuedElements->clear();
     293           0 :                         mp.queuePosition = 0;
     294             :                     }
     295             :                 }
     296           0 :                 return mp.get_input();
     297             :             }
     298             :             else
     299             :             {
     300           0 :                 return (*mp.queuedElements)[mp.queuePosition];
     301             :             }
     302             :         }
     303             : 
     304             :         // This is called when the iterator is incremented.  It's a template
     305             :         // method so we can recover the type of the multi_pass iterator
     306             :         // and call unique and access the m_input data member.
     307             :         template <typename MultiPassT>
     308           0 :         static void increment(MultiPassT& mp)
     309             :         {
     310           0 :             if (mp.queuePosition == mp.queuedElements->size())
     311             :             {
     312             :                 // check if this is the only iterator
     313           0 :                 if (mp.unique())
     314             :                 {
     315             :                     // free up the memory used by the queue.
     316           0 :                     if (mp.queuedElements->size() > 0)
     317             :                     {
     318           0 :                         mp.queuedElements->clear();
     319           0 :                         mp.queuePosition = 0;
     320             :                     }
     321             :                 }
     322             :                 else
     323             :                 {
     324           0 :                     mp.queuedElements->push_back(mp.get_input());
     325           0 :                     ++mp.queuePosition;
     326             :                 }
     327           0 :                 mp.advance_input();
     328             :             }
     329             :             else
     330             :             {
     331           0 :                 ++mp.queuePosition;
     332             :             }
     333             : 
     334           0 :         }
     335             : 
     336             :         // called to forcibly clear the queue
     337             :         void clear_queue()
     338             :         {
     339             :             queuedElements->clear();
     340             :             queuePosition = 0;
     341             :         }
     342             : 
     343             :         // called to determine whether the iterator is an eof iterator
     344             :         template <typename MultiPassT>
     345           0 :         static bool is_eof(MultiPassT const& mp)
     346             :         {
     347           0 :             return mp.queuePosition == mp.queuedElements->size() &&
     348           0 :                 mp.input_at_eof();
     349             :         }
     350             : 
     351             :         // called by operator==
     352           0 :         bool equal_to(inner const& x) const
     353             :         {
     354           0 :             return queuePosition == x.queuePosition;
     355             :         }
     356             : 
     357             :         // called by operator<
     358             :         bool less_than(inner const& x) const
     359             :         {
     360             :             return queuePosition < x.queuePosition;
     361             :         }
     362             : }; // class inner
     363             : 
     364             : }; // class std_deque
     365             : 
     366             : 
     367             : ///////////////////////////////////////////////////////////////////////////////
     368             : // class fixed_size_queue
     369             : // Implementation of the StoragePolicy used by multi_pass
     370             : // fixed_size_queue keeps a circular buffer (implemented by
     371             : // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements.
     372             : // It is up to the user to ensure that there is enough look ahead for their
     373             : // grammar.  Currently there is no way to tell if an iterator is pointing
     374             : // to forgotten data.  The leading iterator will put an item in the queue
     375             : // and remove one when it is incremented.  No dynamic allocation is done,
     376             : // except on creation of the queue (fixed_size_queue constructor).
     377             : ///////////////////////////////////////////////////////////////////////////////
     378             : template < std::size_t N>
     379             : class fixed_size_queue
     380             : {
     381             :     public:
     382             : 
     383             : template <typename ValueT>
     384             : class inner
     385             : {
     386             :     private:
     387             : 
     388             :         typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type;
     389             :         queue_type * queuedElements;
     390             :         mutable typename queue_type::iterator queuePosition;
     391             : 
     392             :     protected:
     393             :         inner()
     394             :             : queuedElements(new queue_type)
     395             :             , queuePosition(queuedElements->begin())
     396             :         {}
     397             : 
     398             :         inner(inner const& x)
     399             :             : queuedElements(x.queuedElements)
     400             :             , queuePosition(x.queuePosition)
     401             :         {}
     402             : 
     403             :         // will be called from the destructor of the last iterator.
     404             :         void destroy()
     405             :         {
     406             :             BOOST_SPIRIT_ASSERT(NULL != queuedElements);
     407             :             delete queuedElements;
     408             :             queuedElements = 0;
     409             :         }
     410             : 
     411             :         void swap(inner& x)
     412             :         {
     413             :             impl::mp_swap(queuedElements, x.queuedElements);
     414             :             impl::mp_swap(queuePosition, x.queuePosition);
     415             :         }
     416             : 
     417             :         // This is called when the iterator is dereferenced.  It's a template
     418             :         // method so we can recover the type of the multi_pass iterator
     419             :         // and access the m_input data member.
     420             :         template <typename MultiPassT>
     421             :         static typename MultiPassT::reference dereference(MultiPassT const& mp)
     422             :         {
     423             :             if (mp.queuePosition == mp.queuedElements->end())
     424             :             {
     425             :                 return mp.get_input();
     426             :             }
     427             :             else
     428             :             {
     429             :                 return *mp.queuePosition;
     430             :             }
     431             :         }
     432             : 
     433             :         // This is called when the iterator is incremented.  It's a template
     434             :         // method so we can recover the type of the multi_pass iterator
     435             :         // and access the m_input data member.
     436             :         template <typename MultiPassT>
     437             :         static void increment(MultiPassT& mp)
     438             :         {
     439             :             if (mp.queuePosition == mp.queuedElements->end())
     440             :             {
     441             :                 // don't let the queue get larger than N
     442             :                 if (mp.queuedElements->size() >= N)
     443             :                     mp.queuedElements->pop_front();
     444             : 
     445             :                 mp.queuedElements->push_back(mp.get_input());
     446             :                 mp.advance_input();
     447             :             }
     448             :             ++mp.queuePosition;
     449             :         }
     450             : 
     451             :         // no-op
     452             :         void clear_queue()
     453             :         {}
     454             : 
     455             :         // called to determine whether the iterator is an eof iterator
     456             :         template <typename MultiPassT>
     457             :         static bool is_eof(MultiPassT const& mp)
     458             :         {
     459             :             return mp.queuePosition == mp.queuedElements->end() &&
     460             :                 mp.input_at_eof();
     461             :         }
     462             : 
     463             :         // called by operator==
     464             :         bool equal_to(inner const& x) const
     465             :         {
     466             :             return queuePosition == x.queuePosition;
     467             :         }
     468             : 
     469             :         // called by operator<
     470             :         bool less_than(inner const& x) const
     471             :         {
     472             :             return queuePosition < x.queuePosition;
     473             :         }
     474             : }; // class inner
     475             : 
     476             : }; // class fixed_size_queue
     477             : 
     478             : 
     479             : ///////////////////////////////////////////////////////////////////////////////
     480             : // class input_iterator
     481             : // Implementation of the InputPolicy used by multi_pass
     482             : // input_iterator encapsulates an input iterator of type InputT
     483             : ///////////////////////////////////////////////////////////////////////////////
     484             : class input_iterator
     485             : {
     486             :     public:
     487             : 
     488             : template <typename InputT>
     489             : class inner
     490             : {
     491             :     private:
     492             :         typedef
     493             :             typename std::iterator_traits<InputT>::value_type
     494             :             result_type;
     495             : 
     496             :     public:
     497             :         typedef result_type value_type;
     498             : 
     499             :     private:
     500             :         struct Data {
     501             :             Data(InputT const &input_) 
     502             :             :   input(input_), was_initialized(false)
     503             :             {}
     504             :             
     505             :             InputT input;
     506             :             value_type curtok;
     507             :             bool was_initialized;
     508             :         };
     509             : 
     510             :        // Needed by compilers not implementing the resolution to DR45. For
     511             :        // reference, see
     512             :        // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
     513             : 
     514             :        friend struct Data;
     515             : 
     516             :     public:
     517             :         typedef
     518             :             typename std::iterator_traits<InputT>::difference_type
     519             :             difference_type;
     520             :         typedef
     521             :             typename std::iterator_traits<InputT>::pointer
     522             :             pointer;
     523             :         typedef
     524             :             typename std::iterator_traits<InputT>::reference
     525             :             reference;
     526             : 
     527             :     protected:
     528             :         inner()
     529             :             : data(0)
     530             :         {}
     531             : 
     532             :         inner(InputT x)
     533             :             : data(new Data(x))
     534             :         {}
     535             : 
     536             :         inner(inner const& x)
     537             :             : data(x.data)
     538             :         {}
     539             : 
     540             :         void destroy()
     541             :         {
     542             :             delete data;
     543             :             data = 0;
     544             :         }
     545             : 
     546             :         bool same_input(inner const& x) const
     547             :         {
     548             :             return data == x.data;
     549             :         }
     550             : 
     551             :         typedef
     552             :             typename std::iterator_traits<InputT>::value_type
     553             :             value_t;
     554             :         void swap(inner& x)
     555             :         {
     556             :             impl::mp_swap(data, x.data);
     557             :         }
     558             : 
     559             :         void ensure_initialized() const
     560             :         {
     561             :             if (data && !data->was_initialized) {
     562             :                 data->curtok = *data->input;      // get the first token
     563             :                 data->was_initialized = true;
     564             :             }
     565             :         }
     566             : 
     567             :     public:
     568             :         reference get_input() const
     569             :         {
     570             :             BOOST_SPIRIT_ASSERT(NULL != data);
     571             :             ensure_initialized();
     572             :             return data->curtok;
     573             :         }
     574             : 
     575             :         void advance_input()
     576             :         {
     577             :             BOOST_SPIRIT_ASSERT(NULL != data);
     578             :             data->was_initialized = false;        // should get the next token
     579             :             ++data->input;
     580             :         }
     581             : 
     582             :         bool input_at_eof() const
     583             :         {
     584             :             return !data || data->input == InputT();
     585             :         }
     586             : 
     587             :     private:
     588             :         Data *data;
     589             : };
     590             : 
     591             : };
     592             : 
     593             : ///////////////////////////////////////////////////////////////////////////////
     594             : // class lex_input
     595             : // Implementation of the InputPolicy used by multi_pass
     596             : // lex_input gets tokens (ints) from yylex()
     597             : ///////////////////////////////////////////////////////////////////////////////
     598             : class lex_input
     599             : {
     600             :     public:
     601             : 
     602             : template <typename InputT>
     603             : class inner
     604             : {
     605             :     public:
     606             :         typedef int value_type;
     607             :     typedef std::ptrdiff_t difference_type;
     608             :         typedef int* pointer;
     609             :         typedef int& reference;
     610             : 
     611             :     protected:
     612             :         inner()
     613             :             : curtok(new int(0))
     614             :         {}
     615             : 
     616             :         inner(InputT x)
     617             :             : curtok(new int(x))
     618             :         {}
     619             : 
     620             :         inner(inner const& x)
     621             :             : curtok(x.curtok)
     622             :         {}
     623             : 
     624             :         void destroy()
     625             :         {
     626             :             delete curtok;
     627             :             curtok = 0;
     628             :         }
     629             : 
     630             :         bool same_input(inner const& x) const
     631             :         {
     632             :             return curtok == x.curtok;
     633             :         }
     634             : 
     635             :         void swap(inner& x)
     636             :         {
     637             :             impl::mp_swap(curtok, x.curtok);
     638             :         }
     639             : 
     640             :     public:
     641             :         reference get_input() const
     642             :         {
     643             :             return *curtok;
     644             :         }
     645             : 
     646             :         void advance_input()
     647             :         {
     648             :             extern int yylex();
     649             :             *curtok = yylex();
     650             :         }
     651             : 
     652             :         bool input_at_eof() const
     653             :         {
     654             :             return *curtok == 0;
     655             :         }
     656             : 
     657             :     private:
     658             :         int* curtok;
     659             : 
     660             : };
     661             : 
     662             : };
     663             : 
     664             : ///////////////////////////////////////////////////////////////////////////////
     665             : // class functor_input
     666             : // Implementation of the InputPolicy used by multi_pass
     667             : // functor_input gets tokens from a functor
     668             : // Note: the functor must have a typedef for result_type
     669             : // It also must have a static variable of type result_type defined to
     670             : // represent eof that is called eof.
     671             : ///////////////////////////////////////////////////////////////////////////////
     672             : class functor_input
     673             : {
     674             :     public:
     675             : 
     676             : template <typename FunctorT>
     677             : class inner
     678             : {
     679             :     typedef typename FunctorT::result_type result_type;
     680             :     public:
     681             :         typedef result_type value_type;
     682             :     typedef std::ptrdiff_t difference_type;
     683             :         typedef result_type* pointer;
     684             :         typedef result_type& reference;
     685             : 
     686             :     protected:
     687             :         inner()
     688             :             : ftor(0)
     689             :             , curtok(0)
     690             :         {}
     691             : 
     692             :         inner(FunctorT const& x)
     693             :             : ftor(new FunctorT(x))
     694             :             , curtok(new result_type((*ftor)()))
     695             :         {}
     696             : 
     697             :         inner(inner const& x)
     698             :             : ftor(x.ftor)
     699             :             , curtok(x.curtok)
     700             :         {}
     701             : 
     702             :         void destroy()
     703             :         {
     704             :             delete ftor;
     705             :             ftor = 0;
     706             :             delete curtok;
     707             :             curtok = 0;
     708             :         }
     709             : 
     710             :         bool same_input(inner const& x) const
     711             :         {
     712             :             return ftor == x.ftor;
     713             :         }
     714             : 
     715             :         void swap(inner& x)
     716             :         {
     717             :             impl::mp_swap(curtok, x.curtok);
     718             :             impl::mp_swap(ftor, x.ftor);
     719             :         }
     720             : 
     721             :     public:
     722             :         reference get_input() const
     723             :         {
     724             :             return *curtok;
     725             :         }
     726             : 
     727             :         void advance_input()
     728             :         {
     729             :             if (curtok) {
     730             :                 *curtok = (*ftor)();
     731             :             }
     732             :         }
     733             : 
     734             :         bool input_at_eof() const
     735             :         {
     736             :             return !curtok || *curtok == ftor->eof;
     737             :         }
     738             : 
     739             :         FunctorT& get_functor() const
     740             :         {
     741             :             return *ftor;
     742             :         }
     743             : 
     744             : 
     745             :     private:
     746             :         FunctorT* ftor;
     747             :         result_type* curtok;
     748             : 
     749             : };
     750             : 
     751             : };
     752             : 
     753             : } // namespace multi_pass_policies
     754             : 
     755             : ///////////////////////////////////////////////////////////////////////////////
     756             : // iterator_base_creator
     757             : ///////////////////////////////////////////////////////////////////////////////
     758             : 
     759             : namespace iterator_ { namespace impl {
     760             : 
     761             : // Meta-function to generate a std::iterator<>-like base class for multi_pass.
     762             : template <typename InputPolicyT, typename InputT>
     763             : struct iterator_base_creator
     764             : {
     765             :     typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
     766             : 
     767             :     struct type {
     768             :         typedef std::forward_iterator_tag iterator_category;
     769             :         typedef typename input_t::value_type value_type;
     770             :         typedef typename input_t::difference_type difference_type;
     771             :         typedef typename input_t::pointer pointer;
     772             :         typedef typename input_t::reference reference;
     773             :     };
     774             : };
     775             : 
     776             : }}
     777             : 
     778             : ///////////////////////////////////////////////////////////////////////////////
     779             : // class template multi_pass 
     780             : ///////////////////////////////////////////////////////////////////////////////
     781             : 
     782             : // The default multi_pass instantiation uses a ref-counted std_deque scheme.
     783             : template
     784             : <
     785             :     typename InputT,
     786             :     typename InputPolicy,
     787             :     typename OwnershipPolicy,
     788             :     typename CheckingPolicy,
     789             :     typename StoragePolicy
     790             : >
     791             : class multi_pass
     792             :     : public OwnershipPolicy
     793             :     , public CheckingPolicy
     794             :     , public StoragePolicy::template inner<
     795             :                 typename InputPolicy::template inner<InputT>::value_type>
     796             :     , public InputPolicy::template inner<InputT>
     797             :     , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
     798             : {
     799             :         typedef OwnershipPolicy OP;
     800             :         typedef CheckingPolicy CHP;
     801             :         typedef typename StoragePolicy::template inner<
     802             :             typename InputPolicy::template inner<InputT>::value_type> SP;
     803             :         typedef typename InputPolicy::template inner<InputT> IP;
     804             :         typedef typename
     805             :             iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
     806             :             IB;
     807             : 
     808             :     public:
     809             :         typedef typename IB::value_type value_type;
     810             :         typedef typename IB::difference_type difference_type;
     811             :         typedef typename IB::reference reference;
     812             :         typedef typename IB::pointer pointer;
     813             :         typedef InputT iterator_type;
     814             : 
     815             :         multi_pass();
     816             :         explicit multi_pass(InputT input);
     817             : 
     818             : #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
     819             :         multi_pass(int);
     820             : #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
     821             : 
     822             :         ~multi_pass();
     823             : 
     824             :         multi_pass(multi_pass const&);
     825             :         multi_pass& operator=(multi_pass const&);
     826             : 
     827             :         void swap(multi_pass& x);
     828             : 
     829             :         reference operator*() const;
     830             :         pointer operator->() const;
     831             :         multi_pass& operator++();
     832             :         multi_pass operator++(int);
     833             : 
     834             :         void clear_queue();
     835             : 
     836             :         bool operator==(const multi_pass& y) const;
     837             :         bool operator<(const multi_pass& y) const;
     838             : 
     839             :     private: // helper functions
     840             :         bool is_eof() const;
     841             : };
     842             : 
     843             : template
     844             : <
     845             :     typename InputT,
     846             :     typename InputPolicy,
     847             :     typename OwnershipPolicy,
     848             :     typename CheckingPolicy,
     849             :     typename StoragePolicy
     850             : >
     851             : inline
     852           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     853             : multi_pass()
     854             :     : OP()
     855             :     , CHP()
     856             :     , SP()
     857           0 :     , IP()
     858             : {
     859           0 : }
     860             : 
     861             : template
     862             : <
     863             :     typename InputT,
     864             :     typename InputPolicy,
     865             :     typename OwnershipPolicy,
     866             :     typename CheckingPolicy,
     867             :     typename StoragePolicy
     868             : >
     869             : inline
     870           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     871             : multi_pass(InputT input)
     872             :     : OP()
     873             :     , CHP()
     874             :     , SP()
     875           0 :     , IP(input)
     876             : {
     877           0 : }
     878             : 
     879             : #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
     880             :     // The standard library shipped with gcc-3.1 has a bug in
     881             :     // bits/basic_string.tcc. It tries  to use iter::iter(0) to
     882             :     // construct an iterator. Ironically, this  happens in sanity
     883             :     // checking code that isn't required by the standard.
     884             :     // The workaround is to provide an additional constructor that
     885             :     // ignores its int argument and behaves like the default constructor.
     886             : template
     887             : <
     888             :     typename InputT,
     889             :     typename InputPolicy,
     890             :     typename OwnershipPolicy,
     891             :     typename CheckingPolicy,
     892             :     typename StoragePolicy
     893             : >
     894             : inline
     895             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     896             : multi_pass(int)
     897             :     : OP()
     898             :     , CHP()
     899             :     , SP()
     900             :     , IP()
     901             : {
     902             : }
     903             : #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
     904             : 
     905             : template
     906             : <
     907             :     typename InputT,
     908             :     typename InputPolicy,
     909             :     typename OwnershipPolicy,
     910             :     typename CheckingPolicy,
     911             :     typename StoragePolicy
     912             : >
     913             : inline
     914           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     915             : ~multi_pass()
     916             : {
     917           0 :     if (OP::release())
     918             :     {
     919           0 :         CHP::destroy();
     920           0 :         SP::destroy();
     921           0 :         IP::destroy();
     922             :     }
     923           0 : }
     924             : 
     925             : template
     926             : <
     927             :     typename InputT,
     928             :     typename InputPolicy,
     929             :     typename OwnershipPolicy,
     930             :     typename CheckingPolicy,
     931             :     typename StoragePolicy
     932             : >
     933             : inline
     934             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     935             : multi_pass(
     936             :         multi_pass const& x)
     937             :     : OP(x)
     938             :     , CHP(x)
     939             :     , SP(x)
     940             :     , IP(x)
     941             : {
     942             :     OP::clone();
     943             : }
     944             : 
     945             : template
     946             : <
     947             :     typename InputT,
     948             :     typename InputPolicy,
     949             :     typename OwnershipPolicy,
     950             :     typename CheckingPolicy,
     951             :     typename StoragePolicy
     952             : >
     953             : inline
     954             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
     955             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     956             : operator=(
     957             :         multi_pass const& x)
     958             : {
     959             :     multi_pass temp(x);
     960             :     temp.swap(*this);
     961             :     return *this;
     962             : }
     963             : 
     964             : template
     965             : <
     966             :     typename InputT,
     967             :     typename InputPolicy,
     968             :     typename OwnershipPolicy,
     969             :     typename CheckingPolicy,
     970             :     typename StoragePolicy
     971             : >
     972             : inline void
     973             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     974             : swap(multi_pass& x)
     975             : {
     976             :     OP::swap(x);
     977             :     CHP::swap(x);
     978             :     SP::swap(x);
     979             :     IP::swap(x);
     980             : }
     981             : 
     982             : template
     983             : <
     984             :     typename InputT,
     985             :     typename InputPolicy,
     986             :     typename OwnershipPolicy,
     987             :     typename CheckingPolicy,
     988             :     typename StoragePolicy
     989             : >
     990             : inline
     991             : typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     992             : reference
     993           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
     994             : operator*() const
     995             : {
     996           0 :     CHP::check_if_valid();
     997           0 :     return SP::dereference(*this);
     998             : }
     999             : 
    1000             : template
    1001             : <
    1002             :     typename InputT,
    1003             :     typename InputPolicy,
    1004             :     typename OwnershipPolicy,
    1005             :     typename CheckingPolicy,
    1006             :     typename StoragePolicy
    1007             : >
    1008             : inline
    1009             : typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1010             : pointer
    1011           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1012             : operator->() const
    1013             : {
    1014           0 :     return &(operator*());
    1015             : }
    1016             : 
    1017             : template
    1018             : <
    1019             :     typename InputT,
    1020             :     typename InputPolicy,
    1021             :     typename OwnershipPolicy,
    1022             :     typename CheckingPolicy,
    1023             :     typename StoragePolicy
    1024             : >
    1025             : inline
    1026             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
    1027             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1028             : operator++()
    1029             : {
    1030             :     CHP::check_if_valid();
    1031             :     SP::increment(*this);
    1032             :     return *this;
    1033             : }
    1034             : 
    1035             : template
    1036             : <
    1037             :     typename InputT,
    1038             :     typename InputPolicy,
    1039             :     typename OwnershipPolicy,
    1040             :     typename CheckingPolicy,
    1041             :     typename StoragePolicy
    1042             : >
    1043             : inline
    1044             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
    1045             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1046             : operator++(int)
    1047             : {
    1048             :     multi_pass
    1049             :     <
    1050             :         InputT,
    1051             :         InputPolicy,
    1052             :         OwnershipPolicy,
    1053             :         CheckingPolicy,
    1054             :         StoragePolicy
    1055             :     > tmp(*this);
    1056             : 
    1057             :     ++*this;
    1058             : 
    1059             :     return tmp;
    1060             : }
    1061             : 
    1062             : template
    1063             : <
    1064             :     typename InputT,
    1065             :     typename InputPolicy,
    1066             :     typename OwnershipPolicy,
    1067             :     typename CheckingPolicy,
    1068             :     typename StoragePolicy
    1069             : >
    1070             : inline void
    1071             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1072             : clear_queue()
    1073             : {
    1074             :     SP::clear_queue();
    1075             :     CHP::clear_queue();
    1076             : }
    1077             : 
    1078             : template
    1079             : <
    1080             :     typename InputT,
    1081             :     typename InputPolicy,
    1082             :     typename OwnershipPolicy,
    1083             :     typename CheckingPolicy,
    1084             :     typename StoragePolicy
    1085             : >
    1086             : inline bool
    1087             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1088             : is_eof() const
    1089             : {
    1090             :     return SP::is_eof(*this);
    1091             : }
    1092             : 
    1093             : ///// Comparisons
    1094             : template
    1095             : <
    1096             :     typename InputT,
    1097             :     typename InputPolicy,
    1098             :     typename OwnershipPolicy,
    1099             :     typename CheckingPolicy,
    1100             :     typename StoragePolicy
    1101             : >
    1102             : inline bool
    1103           0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1104             : operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1105             :         StoragePolicy>& y) const
    1106             : {
    1107           0 :     bool is_eof_ = SP::is_eof(*this);
    1108           0 :     bool y_is_eof_ = SP::is_eof(y);
    1109             :     
    1110           0 :     if (is_eof_ && y_is_eof_)
    1111             :     {
    1112             :         return true;  // both are EOF
    1113             :     }
    1114           0 :     else if (is_eof_ ^ y_is_eof_)
    1115             :     {
    1116             :         return false; // one is EOF, one isn't
    1117             :     }
    1118           0 :     else if (!IP::same_input(y))
    1119             :     {
    1120             :         return false;
    1121             :     }
    1122             :     else
    1123             :     {
    1124           0 :         return SP::equal_to(y);
    1125             :     }
    1126             : }
    1127             : 
    1128             : template
    1129             : <
    1130             :     typename InputT,
    1131             :     typename InputPolicy,
    1132             :     typename OwnershipPolicy,
    1133             :     typename CheckingPolicy,
    1134             :     typename StoragePolicy
    1135             : >
    1136             : inline bool
    1137             : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
    1138             : operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1139             :         StoragePolicy>& y) const
    1140             : {
    1141             :     return SP::less_than(y);
    1142             : }
    1143             : 
    1144             : template
    1145             : <
    1146             :     typename InputT,
    1147             :     typename InputPolicy,
    1148             :     typename OwnershipPolicy,
    1149             :     typename CheckingPolicy,
    1150             :     typename StoragePolicy
    1151             : >
    1152             : inline
    1153           0 : bool operator!=(
    1154             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1155             :                         StoragePolicy>& x,
    1156             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1157             :                         StoragePolicy>& y)
    1158             : {
    1159           0 :     return !(x == y);
    1160             : }
    1161             : 
    1162             : template
    1163             : <
    1164             :     typename InputT,
    1165             :     typename InputPolicy,
    1166             :     typename OwnershipPolicy,
    1167             :     typename CheckingPolicy,
    1168             :     typename StoragePolicy
    1169             : >
    1170             : inline
    1171             : bool operator>(
    1172             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1173             :                         StoragePolicy>& x,
    1174             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1175             :                         StoragePolicy>& y)
    1176             : {
    1177             :     return y < x;
    1178             : }
    1179             : 
    1180             : template
    1181             : <
    1182             :     typename InputT,
    1183             :     typename InputPolicy,
    1184             :     typename OwnershipPolicy,
    1185             :     typename CheckingPolicy,
    1186             :     typename StoragePolicy
    1187             : >
    1188             : inline
    1189             : bool operator>=(
    1190             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1191             :                         StoragePolicy>& x,
    1192             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1193             :                         StoragePolicy>& y)
    1194             : {
    1195             :     return !(x < y);
    1196             : }
    1197             : 
    1198             : template
    1199             : <
    1200             :     typename InputT,
    1201             :     typename InputPolicy,
    1202             :     typename OwnershipPolicy,
    1203             :     typename CheckingPolicy,
    1204             :     typename StoragePolicy
    1205             : >
    1206             : inline
    1207             : bool operator<=(
    1208             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1209             :                         StoragePolicy>& x,
    1210             :         const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
    1211             :                         StoragePolicy>& y)
    1212             : {
    1213             :     return !(y < x);
    1214             : }
    1215             : 
    1216             : ///// Generator function
    1217             : template <typename InputT>
    1218             : inline multi_pass<InputT, 
    1219             :     multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
    1220             :     multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>
    1221             : make_multi_pass(InputT i)
    1222             : {
    1223             :     return multi_pass<InputT, 
    1224             :         multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
    1225             :         multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>(i);
    1226             : }
    1227             : 
    1228             : // this could be a template typedef, since such a thing doesn't
    1229             : // exist in C++, we'll use inheritance to accomplish the same thing.
    1230             : 
    1231             : template <typename InputT, std::size_t N>
    1232             : class look_ahead :
    1233             :     public multi_pass<
    1234             :         InputT,
    1235             :         multi_pass_policies::input_iterator,
    1236             :         multi_pass_policies::first_owner,
    1237             :         multi_pass_policies::no_check,
    1238             :         multi_pass_policies::fixed_size_queue<N> >
    1239             : {
    1240             :         typedef multi_pass<
    1241             :             InputT,
    1242             :             multi_pass_policies::input_iterator,
    1243             :             multi_pass_policies::first_owner,
    1244             :             multi_pass_policies::no_check,
    1245             :             multi_pass_policies::fixed_size_queue<N> > base_t;
    1246             :     public:
    1247             :         look_ahead()
    1248             :             : base_t() {}
    1249             : 
    1250             :         explicit look_ahead(InputT x)
    1251             :             : base_t(x) {}
    1252             : 
    1253             :         look_ahead(look_ahead const& x)
    1254             :             : base_t(x) {}
    1255             : 
    1256             : #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
    1257             :         look_ahead(int)         // workaround for a bug in the library
    1258             :             : base_t() {}       // shipped with gcc 3.1
    1259             : #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
    1260             : 
    1261             :     // default generated operators destructor and assignment operator are okay.
    1262             : };
    1263             : 
    1264             : template
    1265             : <
    1266             :     typename InputT,
    1267             :     typename InputPolicy,
    1268             :     typename OwnershipPolicy,
    1269             :     typename CheckingPolicy,
    1270             :     typename StoragePolicy
    1271             : >
    1272             : void swap(
    1273             :     multi_pass<
    1274             :         InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
    1275             :     > &x,
    1276             :     multi_pass<
    1277             :         InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
    1278             :     > &y)
    1279             : {
    1280             :     x.swap(y);
    1281             : }
    1282             : 
    1283             : namespace impl {
    1284             : 
    1285             :     template <typename T>
    1286             :     inline void mp_swap(T& t1, T& t2)
    1287             :     {
    1288             :         using std::swap;
    1289             :         using BOOST_SPIRIT_CLASSIC_NS::swap;
    1290             :         swap(t1, t2);
    1291             :     }
    1292             : }
    1293             : 
    1294             : BOOST_SPIRIT_CLASSIC_NAMESPACE_END
    1295             : 
    1296             : }} // namespace BOOST_SPIRIT_CLASSIC_NS
    1297             : 
    1298             : #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
    1299             : 
    1300             : 

Generated by: LCOV version 1.14