| /*============================================================================= |
| Copyright (c) 2001, Daniel C. Nuffer |
| http://spirit.sourceforge.net/ |
| |
| 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) |
| =============================================================================*/ |
| #ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP |
| #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP |
| |
| #include <boost/config.hpp> |
| #include <boost/throw_exception.hpp> |
| #include <deque> |
| #include <iterator> |
| #include <iostream> |
| #include <algorithm> // for std::swap |
| #include <exception> // for std::exception |
| #include <boost/limits.hpp> |
| #include <boost/iterator.hpp> |
| |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT |
| #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp> |
| #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits |
| |
| #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp> |
| |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| namespace impl { |
| template <typename T> |
| inline void mp_swap(T& t1, T& t2); |
| } |
| |
| namespace multi_pass_policies |
| { |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class ref_counted |
| // Implementation of an OwnershipPolicy used by multi_pass. |
| // |
| // Implementation modified from RefCounted class from the Loki library by |
| // Andrei Alexandrescu |
| /////////////////////////////////////////////////////////////////////////////// |
| class ref_counted |
| { |
| protected: |
| ref_counted() |
| : count(new std::size_t(1)) |
| {} |
| |
| ref_counted(ref_counted const& x) |
| : count(x.count) |
| {} |
| |
| // clone is called when a copy of the iterator is made, so increment |
| // the ref-count. |
| void clone() |
| { |
| ++*count; |
| } |
| |
| // called when a copy is deleted. Decrement the ref-count. Return |
| // value of true indicates that the last copy has been released. |
| bool release() |
| { |
| if (!--*count) |
| { |
| delete count; |
| count = 0; |
| return true; |
| } |
| return false; |
| } |
| |
| void swap(ref_counted& x) |
| { |
| impl::mp_swap(count, x.count); |
| } |
| |
| public: |
| // returns true if there is only one iterator in existence. |
| // std_deque StoragePolicy will free it's buffered data if this |
| // returns true. |
| bool unique() const |
| { |
| return *count == 1; |
| } |
| |
| private: |
| std::size_t* count; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class first_owner |
| // Implementation of an OwnershipPolicy used by multi_pass |
| // This ownership policy dictates that the first iterator created will |
| // determine the lifespan of the shared components. This works well for |
| // spirit, since no dynamic allocation of iterators is done, and all copies |
| // are make on the stack. |
| // |
| // There is a caveat about using this policy together with the std_deque |
| // StoragePolicy. Since first_owner always returns false from unique(), |
| // std_deque will only release the queued data if clear_queue() is called. |
| /////////////////////////////////////////////////////////////////////////////// |
| class first_owner |
| { |
| protected: |
| first_owner() |
| : first(true) |
| {} |
| |
| first_owner(first_owner const&) |
| : first(false) |
| {} |
| |
| void clone() |
| { |
| } |
| |
| // return true to indicate deletion of resources |
| bool release() |
| { |
| return first; |
| } |
| |
| void swap(first_owner&) |
| { |
| // if we're the first, we still remain the first, even if assigned |
| // to, so don't swap first_. swap is only called from operator= |
| } |
| |
| public: |
| bool unique() const |
| { |
| return false; // no way to know, so always return false |
| } |
| |
| private: |
| bool first; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class illegal_backtracking |
| // thrown by buf_id_check CheckingPolicy if an instance of an iterator is |
| // used after another one has invalidated the queue |
| /////////////////////////////////////////////////////////////////////////////// |
| class illegal_backtracking : public std::exception |
| { |
| public: |
| |
| illegal_backtracking() throw() {} |
| ~illegal_backtracking() throw() {} |
| |
| virtual const char* |
| what() const throw() |
| { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class buf_id_check |
| // Implementation of the CheckingPolicy used by multi_pass |
| // This policy is most effective when used together with the std_deque |
| // StoragePolicy. |
| // If used with the fixed_size_queue StoragePolicy, it will not detect |
| // iterator derefereces that are out of the range of the queue. |
| /////////////////////////////////////////////////////////////////////////////// |
| class buf_id_check |
| { |
| protected: |
| buf_id_check() |
| : shared_buf_id(new unsigned long(0)) |
| , buf_id(0) |
| {} |
| |
| buf_id_check(buf_id_check const& x) |
| : shared_buf_id(x.shared_buf_id) |
| , buf_id(x.buf_id) |
| {} |
| |
| // will be called from the destructor of the last iterator. |
| void destroy() |
| { |
| delete shared_buf_id; |
| shared_buf_id = 0; |
| } |
| |
| void swap(buf_id_check& x) |
| { |
| impl::mp_swap(shared_buf_id, x.shared_buf_id); |
| impl::mp_swap(buf_id, x.buf_id); |
| } |
| |
| // called to verify that everything is okay. |
| void check() const |
| { |
| if (buf_id != *shared_buf_id) |
| { |
| boost::throw_exception(illegal_backtracking()); |
| } |
| } |
| |
| // called from multi_pass::clear_queue, so we can increment the count |
| void clear_queue() |
| { |
| ++*shared_buf_id; |
| ++buf_id; |
| } |
| |
| private: |
| unsigned long* shared_buf_id; |
| unsigned long buf_id; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class no_check |
| // Implementation of the CheckingPolicy used by multi_pass |
| // It does not do anything :-) |
| /////////////////////////////////////////////////////////////////////////////// |
| class no_check |
| { |
| protected: |
| no_check() {} |
| no_check(no_check const&) {} |
| void destroy() {} |
| void swap(no_check&) {} |
| void check() const {} |
| void clear_queue() {} |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class std_deque |
| // Implementation of the StoragePolicy used by multi_pass |
| // This stores all data in a std::deque, and keeps an offset to the current |
| // position. It stores all the data unless there is only one |
| // iterator using the queue. |
| // Note: a position is used instead of an iterator, because a push_back on |
| // a deque can invalidate any iterators. |
| /////////////////////////////////////////////////////////////////////////////// |
| class std_deque |
| { |
| public: |
| |
| template <typename ValueT> |
| class inner |
| { |
| private: |
| |
| typedef std::deque<ValueT> queue_type; |
| queue_type* queuedElements; |
| mutable typename queue_type::size_type queuePosition; |
| |
| protected: |
| inner() |
| : queuedElements(new queue_type) |
| , queuePosition(0) |
| {} |
| |
| inner(inner const& x) |
| : queuedElements(x.queuedElements) |
| , queuePosition(x.queuePosition) |
| {} |
| |
| // will be called from the destructor of the last iterator. |
| void destroy() |
| { |
| BOOST_SPIRIT_ASSERT(NULL != queuedElements); |
| delete queuedElements; |
| queuedElements = 0; |
| } |
| |
| void swap(inner& x) |
| { |
| impl::mp_swap(queuedElements, x.queuedElements); |
| impl::mp_swap(queuePosition, x.queuePosition); |
| } |
| |
| // This is called when the iterator is dereferenced. It's a template |
| // method so we can recover the type of the multi_pass iterator |
| // and call unique and access the m_input data member. |
| template <typename MultiPassT> |
| static typename MultiPassT::reference dereference(MultiPassT const& mp) |
| { |
| if (mp.queuePosition == mp.queuedElements->size()) |
| { |
| // check if this is the only iterator |
| if (mp.unique()) |
| { |
| // free up the memory used by the queue. |
| if (mp.queuedElements->size() > 0) |
| { |
| mp.queuedElements->clear(); |
| mp.queuePosition = 0; |
| } |
| } |
| return mp.get_input(); |
| } |
| else |
| { |
| return (*mp.queuedElements)[mp.queuePosition]; |
| } |
| } |
| |
| // This is called when the iterator is incremented. It's a template |
| // method so we can recover the type of the multi_pass iterator |
| // and call unique and access the m_input data member. |
| template <typename MultiPassT> |
| static void increment(MultiPassT& mp) |
| { |
| if (mp.queuePosition == mp.queuedElements->size()) |
| { |
| // check if this is the only iterator |
| if (mp.unique()) |
| { |
| // free up the memory used by the queue. |
| if (mp.queuedElements->size() > 0) |
| { |
| mp.queuedElements->clear(); |
| mp.queuePosition = 0; |
| } |
| } |
| else |
| { |
| mp.queuedElements->push_back(mp.get_input()); |
| ++mp.queuePosition; |
| } |
| mp.advance_input(); |
| } |
| else |
| { |
| ++mp.queuePosition; |
| } |
| |
| } |
| |
| // called to forcibly clear the queue |
| void clear_queue() |
| { |
| queuedElements->clear(); |
| queuePosition = 0; |
| } |
| |
| // called to determine whether the iterator is an eof iterator |
| template <typename MultiPassT> |
| static bool is_eof(MultiPassT const& mp) |
| { |
| return mp.queuePosition == mp.queuedElements->size() && |
| mp.input_at_eof(); |
| } |
| |
| // called by operator== |
| bool equal_to(inner const& x) const |
| { |
| return queuePosition == x.queuePosition; |
| } |
| |
| // called by operator< |
| bool less_than(inner const& x) const |
| { |
| return queuePosition < x.queuePosition; |
| } |
| }; // class inner |
| |
| }; // class std_deque |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class fixed_size_queue |
| // Implementation of the StoragePolicy used by multi_pass |
| // fixed_size_queue keeps a circular buffer (implemented by |
| // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements. |
| // It is up to the user to ensure that there is enough look ahead for their |
| // grammar. Currently there is no way to tell if an iterator is pointing |
| // to forgotten data. The leading iterator will put an item in the queue |
| // and remove one when it is incremented. No dynamic allocation is done, |
| // except on creation of the queue (fixed_size_queue constructor). |
| /////////////////////////////////////////////////////////////////////////////// |
| template < std::size_t N> |
| class fixed_size_queue |
| { |
| public: |
| |
| template <typename ValueT> |
| class inner |
| { |
| private: |
| |
| typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type; |
| queue_type * queuedElements; |
| mutable typename queue_type::iterator queuePosition; |
| |
| protected: |
| inner() |
| : queuedElements(new queue_type) |
| , queuePosition(queuedElements->begin()) |
| {} |
| |
| inner(inner const& x) |
| : queuedElements(x.queuedElements) |
| , queuePosition(x.queuePosition) |
| {} |
| |
| // will be called from the destructor of the last iterator. |
| void destroy() |
| { |
| BOOST_SPIRIT_ASSERT(NULL != queuedElements); |
| delete queuedElements; |
| queuedElements = 0; |
| } |
| |
| void swap(inner& x) |
| { |
| impl::mp_swap(queuedElements, x.queuedElements); |
| impl::mp_swap(queuePosition, x.queuePosition); |
| } |
| |
| // This is called when the iterator is dereferenced. It's a template |
| // method so we can recover the type of the multi_pass iterator |
| // and access the m_input data member. |
| template <typename MultiPassT> |
| static typename MultiPassT::reference dereference(MultiPassT const& mp) |
| { |
| if (mp.queuePosition == mp.queuedElements->end()) |
| { |
| return mp.get_input(); |
| } |
| else |
| { |
| return *mp.queuePosition; |
| } |
| } |
| |
| // This is called when the iterator is incremented. It's a template |
| // method so we can recover the type of the multi_pass iterator |
| // and access the m_input data member. |
| template <typename MultiPassT> |
| static void increment(MultiPassT& mp) |
| { |
| if (mp.queuePosition == mp.queuedElements->end()) |
| { |
| // don't let the queue get larger than N |
| if (mp.queuedElements->size() >= N) |
| mp.queuedElements->pop_front(); |
| |
| mp.queuedElements->push_back(mp.get_input()); |
| mp.advance_input(); |
| } |
| ++mp.queuePosition; |
| } |
| |
| // no-op |
| void clear_queue() |
| {} |
| |
| // called to determine whether the iterator is an eof iterator |
| template <typename MultiPassT> |
| static bool is_eof(MultiPassT const& mp) |
| { |
| return mp.queuePosition == mp.queuedElements->end() && |
| mp.input_at_eof(); |
| } |
| |
| // called by operator== |
| bool equal_to(inner const& x) const |
| { |
| return queuePosition == x.queuePosition; |
| } |
| |
| // called by operator< |
| bool less_than(inner const& x) const |
| { |
| return queuePosition < x.queuePosition; |
| } |
| }; // class inner |
| |
| }; // class fixed_size_queue |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class input_iterator |
| // Implementation of the InputPolicy used by multi_pass |
| // input_iterator encapsulates an input iterator of type InputT |
| /////////////////////////////////////////////////////////////////////////////// |
| class input_iterator |
| { |
| public: |
| |
| template <typename InputT> |
| class inner |
| { |
| private: |
| typedef |
| typename boost::detail::iterator_traits<InputT>::value_type |
| result_type; |
| |
| public: |
| typedef result_type value_type; |
| |
| private: |
| struct Data { |
| Data(InputT const &input_) |
| : input(input_), was_initialized(false) |
| {} |
| |
| InputT input; |
| value_type curtok; |
| bool was_initialized; |
| }; |
| |
| // Needed by compilers not implementing the resolution to DR45. For |
| // reference, see |
| // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45. |
| |
| friend struct Data; |
| |
| public: |
| typedef |
| typename boost::detail::iterator_traits<InputT>::difference_type |
| difference_type; |
| typedef |
| typename boost::detail::iterator_traits<InputT>::pointer |
| pointer; |
| typedef |
| typename boost::detail::iterator_traits<InputT>::reference |
| reference; |
| |
| protected: |
| inner() |
| : data(0) |
| {} |
| |
| inner(InputT x) |
| : data(new Data(x)) |
| {} |
| |
| inner(inner const& x) |
| : data(x.data) |
| {} |
| |
| void destroy() |
| { |
| delete data; |
| data = 0; |
| } |
| |
| bool same_input(inner const& x) const |
| { |
| return data == x.data; |
| } |
| |
| typedef |
| typename boost::detail::iterator_traits<InputT>::value_type |
| value_t; |
| void swap(inner& x) |
| { |
| impl::mp_swap(data, x.data); |
| } |
| |
| void ensure_initialized() const |
| { |
| if (data && !data->was_initialized) { |
| data->curtok = *data->input; // get the first token |
| data->was_initialized = true; |
| } |
| } |
| |
| public: |
| reference get_input() const |
| { |
| BOOST_SPIRIT_ASSERT(NULL != data); |
| ensure_initialized(); |
| return data->curtok; |
| } |
| |
| void advance_input() |
| { |
| BOOST_SPIRIT_ASSERT(NULL != data); |
| data->was_initialized = false; // should get the next token |
| ++data->input; |
| } |
| |
| bool input_at_eof() const |
| { |
| return !data || data->input == InputT(); |
| } |
| |
| private: |
| Data *data; |
| }; |
| |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class lex_input |
| // Implementation of the InputPolicy used by multi_pass |
| // lex_input gets tokens (ints) from yylex() |
| /////////////////////////////////////////////////////////////////////////////// |
| class lex_input |
| { |
| public: |
| |
| template <typename InputT> |
| class inner |
| { |
| public: |
| typedef int value_type; |
| typedef std::ptrdiff_t difference_type; |
| typedef int* pointer; |
| typedef int& reference; |
| |
| protected: |
| inner() |
| : curtok(new int(0)) |
| {} |
| |
| inner(InputT x) |
| : curtok(new int(x)) |
| {} |
| |
| inner(inner const& x) |
| : curtok(x.curtok) |
| {} |
| |
| void destroy() |
| { |
| delete curtok; |
| curtok = 0; |
| } |
| |
| bool same_input(inner const& x) const |
| { |
| return curtok == x.curtok; |
| } |
| |
| void swap(inner& x) |
| { |
| impl::mp_swap(curtok, x.curtok); |
| } |
| |
| public: |
| reference get_input() const |
| { |
| return *curtok; |
| } |
| |
| void advance_input() |
| { |
| extern int yylex(); |
| *curtok = yylex(); |
| } |
| |
| bool input_at_eof() const |
| { |
| return *curtok == 0; |
| } |
| |
| private: |
| int* curtok; |
| |
| }; |
| |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class functor_input |
| // Implementation of the InputPolicy used by multi_pass |
| // functor_input gets tokens from a functor |
| // Note: the functor must have a typedef for result_type |
| // It also must have a static variable of type result_type defined to |
| // represent eof that is called eof. |
| /////////////////////////////////////////////////////////////////////////////// |
| class functor_input |
| { |
| public: |
| |
| template <typename FunctorT> |
| class inner |
| { |
| typedef typename FunctorT::result_type result_type; |
| public: |
| typedef result_type value_type; |
| typedef std::ptrdiff_t difference_type; |
| typedef result_type* pointer; |
| typedef result_type& reference; |
| |
| protected: |
| inner() |
| : ftor(0) |
| , curtok(0) |
| {} |
| |
| inner(FunctorT const& x) |
| : ftor(new FunctorT(x)) |
| , curtok(new result_type((*ftor)())) |
| {} |
| |
| inner(inner const& x) |
| : ftor(x.ftor) |
| , curtok(x.curtok) |
| {} |
| |
| void destroy() |
| { |
| delete ftor; |
| ftor = 0; |
| delete curtok; |
| curtok = 0; |
| } |
| |
| bool same_input(inner const& x) const |
| { |
| return ftor == x.ftor; |
| } |
| |
| void swap(inner& x) |
| { |
| impl::mp_swap(curtok, x.curtok); |
| impl::mp_swap(ftor, x.ftor); |
| } |
| |
| public: |
| reference get_input() const |
| { |
| return *curtok; |
| } |
| |
| void advance_input() |
| { |
| if (curtok) { |
| *curtok = (*ftor)(); |
| } |
| } |
| |
| bool input_at_eof() const |
| { |
| return !curtok || *curtok == ftor->eof; |
| } |
| |
| FunctorT& get_functor() const |
| { |
| return *ftor; |
| } |
| |
| |
| private: |
| FunctorT* ftor; |
| result_type* curtok; |
| |
| }; |
| |
| }; |
| |
| } // namespace multi_pass_policies |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // iterator_base_creator |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| namespace iterator_ { namespace impl { |
| |
| // Meta-function to generate a std::iterator<> base class for multi_pass. This |
| // is used mainly to improve conformance of compilers not supporting PTS |
| // and thus relying on inheritance to recognize an iterator. |
| // We are using boost::iterator<> because it offers an automatic workaround |
| // for broken std::iterator<> implementations. |
| template <typename InputPolicyT, typename InputT> |
| struct iterator_base_creator |
| { |
| typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t; |
| |
| typedef boost::iterator |
| < |
| std::forward_iterator_tag, |
| typename input_t::value_type, |
| typename input_t::difference_type, |
| typename input_t::pointer, |
| typename input_t::reference |
| > type; |
| }; |
| |
| }} |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class template multi_pass |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| // The default multi_pass instantiation uses a ref-counted std_deque scheme. |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| class multi_pass |
| : public OwnershipPolicy |
| , public CheckingPolicy |
| , public StoragePolicy::template inner< |
| typename InputPolicy::template inner<InputT>::value_type> |
| , public InputPolicy::template inner<InputT> |
| , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type |
| { |
| typedef OwnershipPolicy OP; |
| typedef CheckingPolicy CHP; |
| typedef typename StoragePolicy::template inner< |
| typename InputPolicy::template inner<InputT>::value_type> SP; |
| typedef typename InputPolicy::template inner<InputT> IP; |
| typedef typename |
| iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type |
| IB; |
| |
| public: |
| typedef typename IB::value_type value_type; |
| typedef typename IB::difference_type difference_type; |
| typedef typename IB::reference reference; |
| typedef typename IB::pointer pointer; |
| typedef InputT iterator_type; |
| |
| multi_pass(); |
| explicit multi_pass(InputT input); |
| |
| #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| multi_pass(int); |
| #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| |
| ~multi_pass(); |
| |
| multi_pass(multi_pass const&); |
| multi_pass& operator=(multi_pass const&); |
| |
| void swap(multi_pass& x); |
| |
| reference operator*() const; |
| pointer operator->() const; |
| multi_pass& operator++(); |
| multi_pass operator++(int); |
| |
| void clear_queue(); |
| |
| bool operator==(const multi_pass& y) const; |
| bool operator<(const multi_pass& y) const; |
| |
| private: // helper functions |
| bool is_eof() const; |
| }; |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| multi_pass() |
| : OP() |
| , CHP() |
| , SP() |
| , IP() |
| { |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| multi_pass(InputT input) |
| : OP() |
| , CHP() |
| , SP() |
| , IP(input) |
| { |
| } |
| |
| #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| // The standard library shipped with gcc-3.1 has a bug in |
| // bits/basic_string.tcc. It tries to use iter::iter(0) to |
| // construct an iterator. Ironically, this happens in sanity |
| // checking code that isn't required by the standard. |
| // The workaround is to provide an additional constructor that |
| // ignores its int argument and behaves like the default constructor. |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| multi_pass(int) |
| : OP() |
| , CHP() |
| , SP() |
| , IP() |
| { |
| } |
| #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| ~multi_pass() |
| { |
| if (OP::release()) |
| { |
| CHP::destroy(); |
| SP::destroy(); |
| IP::destroy(); |
| } |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| multi_pass( |
| multi_pass const& x) |
| : OP(x) |
| , CHP(x) |
| , SP(x) |
| , IP(x) |
| { |
| OP::clone(); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>& |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator=( |
| multi_pass const& x) |
| { |
| multi_pass temp(x); |
| temp.swap(*this); |
| return *this; |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline void |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| swap(multi_pass& x) |
| { |
| OP::swap(x); |
| CHP::swap(x); |
| SP::swap(x); |
| IP::swap(x); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| reference |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator*() const |
| { |
| CHP::check(); |
| return SP::dereference(*this); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| pointer |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator->() const |
| { |
| return &(operator*()); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>& |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator++() |
| { |
| CHP::check(); |
| SP::increment(*this); |
| return *this; |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy> |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator++(int) |
| { |
| multi_pass |
| < |
| InputT, |
| InputPolicy, |
| OwnershipPolicy, |
| CheckingPolicy, |
| StoragePolicy |
| > tmp(*this); |
| |
| ++*this; |
| |
| return tmp; |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline void |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| clear_queue() |
| { |
| SP::clear_queue(); |
| CHP::clear_queue(); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline bool |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| is_eof() const |
| { |
| return SP::is_eof(*this); |
| } |
| |
| ///// Comparisons |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline bool |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) const |
| { |
| bool is_eof_ = SP::is_eof(*this); |
| bool y_is_eof_ = SP::is_eof(y); |
| |
| if (is_eof_ && y_is_eof_) |
| { |
| return true; // both are EOF |
| } |
| else if (is_eof_ ^ y_is_eof_) |
| { |
| return false; // one is EOF, one isn't |
| } |
| else if (!IP::same_input(y)) |
| { |
| return false; |
| } |
| else |
| { |
| return SP::equal_to(y); |
| } |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline bool |
| multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>:: |
| operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) const |
| { |
| return SP::less_than(y); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| bool operator!=( |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& x, |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) |
| { |
| return !(x == y); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| bool operator>( |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& x, |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) |
| { |
| return y < x; |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| bool operator>=( |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& x, |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) |
| { |
| return !(x < y); |
| } |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| inline |
| bool operator<=( |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& x, |
| const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, |
| StoragePolicy>& y) |
| { |
| return !(y < x); |
| } |
| |
| ///// Generator function |
| template <typename InputT> |
| inline multi_pass<InputT, |
| multi_pass_policies::input_iterator, multi_pass_policies::ref_counted, |
| multi_pass_policies::buf_id_check, multi_pass_policies::std_deque> |
| make_multi_pass(InputT i) |
| { |
| return multi_pass<InputT, |
| multi_pass_policies::input_iterator, multi_pass_policies::ref_counted, |
| multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>(i); |
| } |
| |
| // this could be a template typedef, since such a thing doesn't |
| // exist in C++, we'll use inheritance to accomplish the same thing. |
| |
| template <typename InputT, std::size_t N> |
| class look_ahead : |
| public multi_pass< |
| InputT, |
| multi_pass_policies::input_iterator, |
| multi_pass_policies::first_owner, |
| multi_pass_policies::no_check, |
| multi_pass_policies::fixed_size_queue<N> > |
| { |
| typedef multi_pass< |
| InputT, |
| multi_pass_policies::input_iterator, |
| multi_pass_policies::first_owner, |
| multi_pass_policies::no_check, |
| multi_pass_policies::fixed_size_queue<N> > base_t; |
| public: |
| look_ahead() |
| : base_t() {} |
| |
| explicit look_ahead(InputT x) |
| : base_t(x) {} |
| |
| look_ahead(look_ahead const& x) |
| : base_t(x) {} |
| |
| #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| look_ahead(int) // workaround for a bug in the library |
| : base_t() {} // shipped with gcc 3.1 |
| #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) |
| |
| // default generated operators destructor and assignment operator are okay. |
| }; |
| |
| template |
| < |
| typename InputT, |
| typename InputPolicy, |
| typename OwnershipPolicy, |
| typename CheckingPolicy, |
| typename StoragePolicy |
| > |
| void swap( |
| multi_pass< |
| InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy |
| > &x, |
| multi_pass< |
| InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy |
| > &y) |
| { |
| x.swap(y); |
| } |
| |
| namespace impl { |
| |
| template <typename T> |
| inline void mp_swap(T& t1, T& t2) |
| { |
| using std::swap; |
| using BOOST_SPIRIT_CLASSIC_NS::swap; |
| swap(t1, t2); |
| } |
| } |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} // namespace BOOST_SPIRIT_CLASSIC_NS |
| |
| #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP |
| |
| |