Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-16 09:33:23

0001 /*=============================================================================
0002     Copyright (c) 2001, Daniel C. Nuffer
0003     http://spirit.sourceforge.net/
0004 
0005   Distributed under the Boost Software License, Version 1.0. (See accompanying
0006   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 =============================================================================*/
0008 #ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
0009 #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
0010 
0011 #include <boost/config.hpp>
0012 #include <boost/throw_exception.hpp>
0013 #include <deque>
0014 #include <iterator>
0015 #include <iostream>
0016 #include <algorithm>    // for std::swap
0017 #include <exception>    // for std::exception
0018 #include <boost/limits.hpp>
0019 
0020 #include <boost/spirit/home/classic/namespace.hpp>
0021 #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
0022 #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp>
0023 
0024 #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp>
0025 
0026 namespace boost { namespace spirit {
0027 
0028 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0029 
0030 namespace impl {
0031     template <typename T>
0032     inline void mp_swap(T& t1, T& t2);
0033 }
0034 
0035 namespace multi_pass_policies
0036 {
0037 
0038 ///////////////////////////////////////////////////////////////////////////////
0039 // class ref_counted
0040 // Implementation of an OwnershipPolicy used by multi_pass.
0041 //
0042 // Implementation modified from RefCounted class from the Loki library by
0043 // Andrei Alexandrescu
0044 ///////////////////////////////////////////////////////////////////////////////
0045 class ref_counted
0046 {
0047     protected:
0048         ref_counted()
0049             : count(new std::size_t(1))
0050         {}
0051 
0052         ref_counted(ref_counted const& x)
0053             : count(x.count)
0054         {}
0055 
0056         // clone is called when a copy of the iterator is made, so increment
0057         // the ref-count.
0058         void clone()
0059         {
0060             ++*count;
0061         }
0062 
0063         // called when a copy is deleted.  Decrement the ref-count.  Return
0064         // value of true indicates that the last copy has been released.
0065         bool release()
0066         {
0067             if (!--*count)
0068             {
0069                 delete count;
0070                 count = 0;
0071                 return true;
0072             }
0073             return false;
0074         }
0075 
0076         void swap(ref_counted& x)
0077         {
0078             impl::mp_swap(count, x.count);
0079         }
0080 
0081     public:
0082         // returns true if there is only one iterator in existence.
0083         // std_deque StoragePolicy will free it's buffered data if this
0084         // returns true.
0085         bool unique() const
0086         {
0087             return *count == 1;
0088         }
0089 
0090     private:
0091         std::size_t* count;
0092 };
0093 
0094 ///////////////////////////////////////////////////////////////////////////////
0095 // class first_owner
0096 // Implementation of an OwnershipPolicy used by multi_pass
0097 // This ownership policy dictates that the first iterator created will
0098 // determine the lifespan of the shared components.  This works well for
0099 // spirit, since no dynamic allocation of iterators is done, and all copies
0100 // are make on the stack.
0101 //
0102 // There is a caveat about using this policy together with the std_deque
0103 // StoragePolicy. Since first_owner always returns false from unique(),
0104 // std_deque will only release the queued data if clear_queue() is called.
0105 ///////////////////////////////////////////////////////////////////////////////
0106 class first_owner
0107 {
0108     protected:
0109         first_owner()
0110             : first(true)
0111         {}
0112 
0113         first_owner(first_owner const&)
0114             : first(false)
0115         {}
0116 
0117         void clone()
0118         {
0119         }
0120 
0121         // return true to indicate deletion of resources
0122         bool release()
0123         {
0124             return first;
0125         }
0126 
0127         void swap(first_owner&)
0128         {
0129             // if we're the first, we still remain the first, even if assigned
0130             // to, so don't swap first_.  swap is only called from operator=
0131         }
0132 
0133     public:
0134         bool unique() const
0135         {
0136             return false; // no way to know, so always return false
0137         }
0138 
0139     private:
0140         bool first;
0141 };
0142 
0143 ///////////////////////////////////////////////////////////////////////////////
0144 // class illegal_backtracking
0145 // thrown by buf_id_check CheckingPolicy if an instance of an iterator is
0146 // used after another one has invalidated the queue
0147 ///////////////////////////////////////////////////////////////////////////////
0148 class BOOST_SYMBOL_VISIBLE illegal_backtracking : public std::exception
0149 {
0150 public:
0151 
0152     illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
0153     ~illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE {}
0154 
0155     const char*
0156     what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0157     { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; }
0158 };
0159 
0160 ///////////////////////////////////////////////////////////////////////////////
0161 // class buf_id_check
0162 // Implementation of the CheckingPolicy used by multi_pass
0163 // This policy is most effective when used together with the std_deque
0164 // StoragePolicy.
0165 // If used with the fixed_size_queue StoragePolicy, it will not detect
0166 // iterator dereferences that are out of the range of the queue.
0167 ///////////////////////////////////////////////////////////////////////////////
0168 class buf_id_check
0169 {
0170     protected:
0171         buf_id_check()
0172             : shared_buf_id(new unsigned long(0))
0173             , buf_id(0)
0174         {}
0175 
0176         buf_id_check(buf_id_check const& x)
0177             : shared_buf_id(x.shared_buf_id)
0178             , buf_id(x.buf_id)
0179         {}
0180 
0181         // will be called from the destructor of the last iterator.
0182         void destroy()
0183         {
0184             delete shared_buf_id;
0185             shared_buf_id = 0;
0186         }
0187 
0188         void swap(buf_id_check& x)
0189         {
0190             impl::mp_swap(shared_buf_id, x.shared_buf_id);
0191             impl::mp_swap(buf_id, x.buf_id);
0192         }
0193 
0194         // called to verify that everything is okay.
0195         void check_if_valid() const
0196         {
0197             if (buf_id != *shared_buf_id)
0198             {
0199                 boost::throw_exception(illegal_backtracking());
0200             }
0201         }
0202 
0203         // called from multi_pass::clear_queue, so we can increment the count
0204         void clear_queue()
0205         {
0206             ++*shared_buf_id;
0207             ++buf_id;
0208         }
0209 
0210     private:
0211         unsigned long* shared_buf_id;
0212         unsigned long buf_id;
0213 };
0214 
0215 ///////////////////////////////////////////////////////////////////////////////
0216 // class no_check
0217 // Implementation of the CheckingPolicy used by multi_pass
0218 // It does not do anything :-)
0219 ///////////////////////////////////////////////////////////////////////////////
0220 class no_check
0221 {
0222     protected:
0223         no_check() {}
0224         no_check(no_check const&) {}
0225         void destroy() {}
0226         void swap(no_check&) {}
0227         void check_if_valid() const {}
0228         void clear_queue() {}
0229 };
0230 
0231 ///////////////////////////////////////////////////////////////////////////////
0232 // class std_deque
0233 // Implementation of the StoragePolicy used by multi_pass
0234 // This stores all data in a std::deque, and keeps an offset to the current
0235 // position. It stores all the data unless there is only one
0236 // iterator using the queue.
0237 // Note: a position is used instead of an iterator, because a push_back on
0238 // a deque can invalidate any iterators.
0239 ///////////////////////////////////////////////////////////////////////////////
0240 class std_deque
0241 {
0242     public:
0243 
0244 template <typename ValueT>
0245 class inner
0246 {
0247     private:
0248 
0249         typedef std::deque<ValueT> queue_type;
0250         queue_type* queuedElements;
0251         mutable typename queue_type::size_type queuePosition;
0252 
0253     protected:
0254         inner()
0255             : queuedElements(new queue_type)
0256             , queuePosition(0)
0257         {}
0258 
0259         inner(inner const& x)
0260             : queuedElements(x.queuedElements)
0261             , queuePosition(x.queuePosition)
0262         {}
0263 
0264         // will be called from the destructor of the last iterator.
0265         void destroy()
0266         {
0267             BOOST_SPIRIT_ASSERT(NULL != queuedElements);
0268             delete queuedElements;
0269             queuedElements = 0;
0270         }
0271 
0272         void swap(inner& x)
0273         {
0274             impl::mp_swap(queuedElements, x.queuedElements);
0275             impl::mp_swap(queuePosition, x.queuePosition);
0276         }
0277 
0278         // This is called when the iterator is dereferenced.  It's a template
0279         // method so we can recover the type of the multi_pass iterator
0280         // and call unique and access the m_input data member.
0281         template <typename MultiPassT>
0282         static typename MultiPassT::reference dereference(MultiPassT const& mp)
0283         {
0284             if (mp.queuePosition == mp.queuedElements->size())
0285             {
0286                 // check if this is the only iterator
0287                 if (mp.unique())
0288                 {
0289                     // free up the memory used by the queue.
0290                     if (mp.queuedElements->size() > 0)
0291                     {
0292                         mp.queuedElements->clear();
0293                         mp.queuePosition = 0;
0294                     }
0295                 }
0296                 return mp.get_input();
0297             }
0298             else
0299             {
0300                 return (*mp.queuedElements)[mp.queuePosition];
0301             }
0302         }
0303 
0304         // This is called when the iterator is incremented.  It's a template
0305         // method so we can recover the type of the multi_pass iterator
0306         // and call unique and access the m_input data member.
0307         template <typename MultiPassT>
0308         static void increment(MultiPassT& mp)
0309         {
0310             if (mp.queuePosition == mp.queuedElements->size())
0311             {
0312                 // check if this is the only iterator
0313                 if (mp.unique())
0314                 {
0315                     // free up the memory used by the queue.
0316                     if (mp.queuedElements->size() > 0)
0317                     {
0318                         mp.queuedElements->clear();
0319                         mp.queuePosition = 0;
0320                     }
0321                 }
0322                 else
0323                 {
0324                     mp.queuedElements->push_back(mp.get_input());
0325                     ++mp.queuePosition;
0326                 }
0327                 mp.advance_input();
0328             }
0329             else
0330             {
0331                 ++mp.queuePosition;
0332             }
0333 
0334         }
0335 
0336         // called to forcibly clear the queue
0337         void clear_queue()
0338         {
0339             queuedElements->clear();
0340             queuePosition = 0;
0341         }
0342 
0343         // called to determine whether the iterator is an eof iterator
0344         template <typename MultiPassT>
0345         static bool is_eof(MultiPassT const& mp)
0346         {
0347             return mp.queuePosition == mp.queuedElements->size() &&
0348                 mp.input_at_eof();
0349         }
0350 
0351         // called by operator==
0352         bool equal_to(inner const& x) const
0353         {
0354             return queuePosition == x.queuePosition;
0355         }
0356 
0357         // called by operator<
0358         bool less_than(inner const& x) const
0359         {
0360             return queuePosition < x.queuePosition;
0361         }
0362 }; // class inner
0363 
0364 }; // class std_deque
0365 
0366 
0367 ///////////////////////////////////////////////////////////////////////////////
0368 // class fixed_size_queue
0369 // Implementation of the StoragePolicy used by multi_pass
0370 // fixed_size_queue keeps a circular buffer (implemented by
0371 // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements.
0372 // It is up to the user to ensure that there is enough look ahead for their
0373 // grammar.  Currently there is no way to tell if an iterator is pointing
0374 // to forgotten data.  The leading iterator will put an item in the queue
0375 // and remove one when it is incremented.  No dynamic allocation is done,
0376 // except on creation of the queue (fixed_size_queue constructor).
0377 ///////////////////////////////////////////////////////////////////////////////
0378 template < std::size_t N>
0379 class fixed_size_queue
0380 {
0381     public:
0382 
0383 template <typename ValueT>
0384 class inner
0385 {
0386     private:
0387 
0388         typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type;
0389         queue_type * queuedElements;
0390         mutable typename queue_type::iterator queuePosition;
0391 
0392     protected:
0393         inner()
0394             : queuedElements(new queue_type)
0395             , queuePosition(queuedElements->begin())
0396         {}
0397 
0398         inner(inner const& x)
0399             : queuedElements(x.queuedElements)
0400             , queuePosition(x.queuePosition)
0401         {}
0402 
0403         // will be called from the destructor of the last iterator.
0404         void destroy()
0405         {
0406             BOOST_SPIRIT_ASSERT(NULL != queuedElements);
0407             delete queuedElements;
0408             queuedElements = 0;
0409         }
0410 
0411         void swap(inner& x)
0412         {
0413             impl::mp_swap(queuedElements, x.queuedElements);
0414             impl::mp_swap(queuePosition, x.queuePosition);
0415         }
0416 
0417         // This is called when the iterator is dereferenced.  It's a template
0418         // method so we can recover the type of the multi_pass iterator
0419         // and access the m_input data member.
0420         template <typename MultiPassT>
0421         static typename MultiPassT::reference dereference(MultiPassT const& mp)
0422         {
0423             if (mp.queuePosition == mp.queuedElements->end())
0424             {
0425                 return mp.get_input();
0426             }
0427             else
0428             {
0429                 return *mp.queuePosition;
0430             }
0431         }
0432 
0433         // This is called when the iterator is incremented.  It's a template
0434         // method so we can recover the type of the multi_pass iterator
0435         // and access the m_input data member.
0436         template <typename MultiPassT>
0437         static void increment(MultiPassT& mp)
0438         {
0439             if (mp.queuePosition == mp.queuedElements->end())
0440             {
0441                 // don't let the queue get larger than N
0442                 if (mp.queuedElements->size() >= N)
0443                     mp.queuedElements->pop_front();
0444 
0445                 mp.queuedElements->push_back(mp.get_input());
0446                 mp.advance_input();
0447             }
0448             ++mp.queuePosition;
0449         }
0450 
0451         // no-op
0452         void clear_queue()
0453         {}
0454 
0455         // called to determine whether the iterator is an eof iterator
0456         template <typename MultiPassT>
0457         static bool is_eof(MultiPassT const& mp)
0458         {
0459             return mp.queuePosition == mp.queuedElements->end() &&
0460                 mp.input_at_eof();
0461         }
0462 
0463         // called by operator==
0464         bool equal_to(inner const& x) const
0465         {
0466             return queuePosition == x.queuePosition;
0467         }
0468 
0469         // called by operator<
0470         bool less_than(inner const& x) const
0471         {
0472             return queuePosition < x.queuePosition;
0473         }
0474 }; // class inner
0475 
0476 }; // class fixed_size_queue
0477 
0478 
0479 ///////////////////////////////////////////////////////////////////////////////
0480 // class input_iterator
0481 // Implementation of the InputPolicy used by multi_pass
0482 // input_iterator encapsulates an input iterator of type InputT
0483 ///////////////////////////////////////////////////////////////////////////////
0484 class input_iterator
0485 {
0486     public:
0487 
0488 template <typename InputT>
0489 class inner
0490 {
0491     private:
0492         typedef
0493             typename std::iterator_traits<InputT>::value_type
0494             result_type;
0495 
0496     public:
0497         typedef result_type value_type;
0498 
0499     private:
0500         struct Data {
0501             Data(InputT const &input_) 
0502             :   input(input_), was_initialized(false)
0503             {}
0504             
0505             InputT input;
0506             value_type curtok;
0507             bool was_initialized;
0508         };
0509 
0510        // Needed by compilers not implementing the resolution to DR45. For
0511        // reference, see
0512        // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
0513 
0514        friend struct Data;
0515 
0516     public:
0517         typedef
0518             typename std::iterator_traits<InputT>::difference_type
0519             difference_type;
0520         typedef
0521             typename std::iterator_traits<InputT>::pointer
0522             pointer;
0523         typedef
0524             typename std::iterator_traits<InputT>::reference
0525             reference;
0526 
0527     protected:
0528         inner()
0529             : data(0)
0530         {}
0531 
0532         inner(InputT x)
0533             : data(new Data(x))
0534         {}
0535 
0536         inner(inner const& x)
0537             : data(x.data)
0538         {}
0539 
0540         void destroy()
0541         {
0542             delete data;
0543             data = 0;
0544         }
0545 
0546         bool same_input(inner const& x) const
0547         {
0548             return data == x.data;
0549         }
0550 
0551         typedef
0552             typename std::iterator_traits<InputT>::value_type
0553             value_t;
0554         void swap(inner& x)
0555         {
0556             impl::mp_swap(data, x.data);
0557         }
0558 
0559         void ensure_initialized() const
0560         {
0561             if (data && !data->was_initialized) {
0562                 data->curtok = *data->input;      // get the first token
0563                 data->was_initialized = true;
0564             }
0565         }
0566 
0567     public:
0568         reference get_input() const
0569         {
0570             BOOST_SPIRIT_ASSERT(NULL != data);
0571             ensure_initialized();
0572             return data->curtok;
0573         }
0574 
0575         void advance_input()
0576         {
0577             BOOST_SPIRIT_ASSERT(NULL != data);
0578             data->was_initialized = false;        // should get the next token
0579             ++data->input;
0580         }
0581 
0582         bool input_at_eof() const
0583         {
0584             return !data || data->input == InputT();
0585         }
0586 
0587     private:
0588         Data *data;
0589 };
0590 
0591 };
0592 
0593 ///////////////////////////////////////////////////////////////////////////////
0594 // class lex_input
0595 // Implementation of the InputPolicy used by multi_pass
0596 // lex_input gets tokens (ints) from yylex()
0597 ///////////////////////////////////////////////////////////////////////////////
0598 class lex_input
0599 {
0600     public:
0601 
0602 template <typename InputT>
0603 class inner
0604 {
0605     public:
0606         typedef int value_type;
0607     typedef std::ptrdiff_t difference_type;
0608         typedef int* pointer;
0609         typedef int& reference;
0610 
0611     protected:
0612         inner()
0613             : curtok(new int(0))
0614         {}
0615 
0616         inner(InputT x)
0617             : curtok(new int(x))
0618         {}
0619 
0620         inner(inner const& x)
0621             : curtok(x.curtok)
0622         {}
0623 
0624         void destroy()
0625         {
0626             delete curtok;
0627             curtok = 0;
0628         }
0629 
0630         bool same_input(inner const& x) const
0631         {
0632             return curtok == x.curtok;
0633         }
0634 
0635         void swap(inner& x)
0636         {
0637             impl::mp_swap(curtok, x.curtok);
0638         }
0639 
0640     public:
0641         reference get_input() const
0642         {
0643             return *curtok;
0644         }
0645 
0646         void advance_input()
0647         {
0648             extern int yylex();
0649             *curtok = yylex();
0650         }
0651 
0652         bool input_at_eof() const
0653         {
0654             return *curtok == 0;
0655         }
0656 
0657     private:
0658         int* curtok;
0659 
0660 };
0661 
0662 };
0663 
0664 ///////////////////////////////////////////////////////////////////////////////
0665 // class functor_input
0666 // Implementation of the InputPolicy used by multi_pass
0667 // functor_input gets tokens from a functor
0668 // Note: the functor must have a typedef for result_type
0669 // It also must have a static variable of type result_type defined to
0670 // represent eof that is called eof.
0671 ///////////////////////////////////////////////////////////////////////////////
0672 class functor_input
0673 {
0674     public:
0675 
0676 template <typename FunctorT>
0677 class inner
0678 {
0679     typedef typename FunctorT::result_type result_type;
0680     public:
0681         typedef result_type value_type;
0682     typedef std::ptrdiff_t difference_type;
0683         typedef result_type* pointer;
0684         typedef result_type& reference;
0685 
0686     protected:
0687         inner()
0688             : ftor(0)
0689             , curtok(0)
0690         {}
0691 
0692         inner(FunctorT const& x)
0693             : ftor(new FunctorT(x))
0694             , curtok(new result_type((*ftor)()))
0695         {}
0696 
0697         inner(inner const& x)
0698             : ftor(x.ftor)
0699             , curtok(x.curtok)
0700         {}
0701 
0702         void destroy()
0703         {
0704             delete ftor;
0705             ftor = 0;
0706             delete curtok;
0707             curtok = 0;
0708         }
0709 
0710         bool same_input(inner const& x) const
0711         {
0712             return ftor == x.ftor;
0713         }
0714 
0715         void swap(inner& x)
0716         {
0717             impl::mp_swap(curtok, x.curtok);
0718             impl::mp_swap(ftor, x.ftor);
0719         }
0720 
0721     public:
0722         reference get_input() const
0723         {
0724             return *curtok;
0725         }
0726 
0727         void advance_input()
0728         {
0729             if (curtok) {
0730                 *curtok = (*ftor)();
0731             }
0732         }
0733 
0734         bool input_at_eof() const
0735         {
0736             return !curtok || *curtok == ftor->eof;
0737         }
0738 
0739         FunctorT& get_functor() const
0740         {
0741             return *ftor;
0742         }
0743 
0744 
0745     private:
0746         FunctorT* ftor;
0747         result_type* curtok;
0748 
0749 };
0750 
0751 };
0752 
0753 } // namespace multi_pass_policies
0754 
0755 ///////////////////////////////////////////////////////////////////////////////
0756 // iterator_base_creator
0757 ///////////////////////////////////////////////////////////////////////////////
0758 
0759 namespace iterator_ { namespace impl {
0760 
0761 // Meta-function to generate a std::iterator<>-like base class for multi_pass.
0762 template <typename InputPolicyT, typename InputT>
0763 struct iterator_base_creator
0764 {
0765     typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
0766 
0767     struct type {
0768         typedef std::forward_iterator_tag iterator_category;
0769         typedef typename input_t::value_type value_type;
0770         typedef typename input_t::difference_type difference_type;
0771         typedef typename input_t::pointer pointer;
0772         typedef typename input_t::reference reference;
0773     };
0774 };
0775 
0776 }}
0777 
0778 ///////////////////////////////////////////////////////////////////////////////
0779 // class template multi_pass 
0780 ///////////////////////////////////////////////////////////////////////////////
0781 
0782 // The default multi_pass instantiation uses a ref-counted std_deque scheme.
0783 template
0784 <
0785     typename InputT,
0786     typename InputPolicy,
0787     typename OwnershipPolicy,
0788     typename CheckingPolicy,
0789     typename StoragePolicy
0790 >
0791 class multi_pass
0792     : public OwnershipPolicy
0793     , public CheckingPolicy
0794     , public StoragePolicy::template inner<
0795                 typename InputPolicy::template inner<InputT>::value_type>
0796     , public InputPolicy::template inner<InputT>
0797     , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
0798 {
0799         typedef OwnershipPolicy OP;
0800         typedef CheckingPolicy CHP;
0801         typedef typename StoragePolicy::template inner<
0802             typename InputPolicy::template inner<InputT>::value_type> SP;
0803         typedef typename InputPolicy::template inner<InputT> IP;
0804         typedef typename
0805             iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
0806             IB;
0807 
0808     public:
0809         typedef typename IB::value_type value_type;
0810         typedef typename IB::difference_type difference_type;
0811         typedef typename IB::reference reference;
0812         typedef typename IB::pointer pointer;
0813         typedef InputT iterator_type;
0814 
0815         multi_pass();
0816         explicit multi_pass(InputT input);
0817 
0818 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
0819         multi_pass(int);
0820 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
0821 
0822         ~multi_pass();
0823 
0824         multi_pass(multi_pass const&);
0825         multi_pass& operator=(multi_pass const&);
0826 
0827         void swap(multi_pass& x);
0828 
0829         reference operator*() const;
0830         pointer operator->() const;
0831         multi_pass& operator++();
0832         multi_pass operator++(int);
0833 
0834         void clear_queue();
0835 
0836         bool operator==(const multi_pass& y) const;
0837         bool operator<(const multi_pass& y) const;
0838 
0839     private: // helper functions
0840         bool is_eof() const;
0841 };
0842 
0843 template
0844 <
0845     typename InputT,
0846     typename InputPolicy,
0847     typename OwnershipPolicy,
0848     typename CheckingPolicy,
0849     typename StoragePolicy
0850 >
0851 inline
0852 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0853 multi_pass()
0854     : OP()
0855     , CHP()
0856     , SP()
0857     , IP()
0858 {
0859 }
0860 
0861 template
0862 <
0863     typename InputT,
0864     typename InputPolicy,
0865     typename OwnershipPolicy,
0866     typename CheckingPolicy,
0867     typename StoragePolicy
0868 >
0869 inline
0870 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0871 multi_pass(InputT input)
0872     : OP()
0873     , CHP()
0874     , SP()
0875     , IP(input)
0876 {
0877 }
0878 
0879 #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
0880     // The standard library shipped with gcc-3.1 has a bug in
0881     // bits/basic_string.tcc. It tries  to use iter::iter(0) to
0882     // construct an iterator. Ironically, this  happens in sanity
0883     // checking code that isn't required by the standard.
0884     // The workaround is to provide an additional constructor that
0885     // ignores its int argument and behaves like the default constructor.
0886 template
0887 <
0888     typename InputT,
0889     typename InputPolicy,
0890     typename OwnershipPolicy,
0891     typename CheckingPolicy,
0892     typename StoragePolicy
0893 >
0894 inline
0895 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0896 multi_pass(int)
0897     : OP()
0898     , CHP()
0899     , SP()
0900     , IP()
0901 {
0902 }
0903 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
0904 
0905 template
0906 <
0907     typename InputT,
0908     typename InputPolicy,
0909     typename OwnershipPolicy,
0910     typename CheckingPolicy,
0911     typename StoragePolicy
0912 >
0913 inline
0914 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0915 ~multi_pass()
0916 {
0917     if (OP::release())
0918     {
0919         CHP::destroy();
0920         SP::destroy();
0921         IP::destroy();
0922     }
0923 }
0924 
0925 template
0926 <
0927     typename InputT,
0928     typename InputPolicy,
0929     typename OwnershipPolicy,
0930     typename CheckingPolicy,
0931     typename StoragePolicy
0932 >
0933 inline
0934 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0935 multi_pass(
0936         multi_pass const& x)
0937     : OP(x)
0938     , CHP(x)
0939     , SP(x)
0940     , IP(x)
0941 {
0942     OP::clone();
0943 }
0944 
0945 template
0946 <
0947     typename InputT,
0948     typename InputPolicy,
0949     typename OwnershipPolicy,
0950     typename CheckingPolicy,
0951     typename StoragePolicy
0952 >
0953 inline
0954 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
0955 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0956 operator=(
0957         multi_pass const& x)
0958 {
0959     multi_pass temp(x);
0960     temp.swap(*this);
0961     return *this;
0962 }
0963 
0964 template
0965 <
0966     typename InputT,
0967     typename InputPolicy,
0968     typename OwnershipPolicy,
0969     typename CheckingPolicy,
0970     typename StoragePolicy
0971 >
0972 inline void
0973 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0974 swap(multi_pass& x)
0975 {
0976     OP::swap(x);
0977     CHP::swap(x);
0978     SP::swap(x);
0979     IP::swap(x);
0980 }
0981 
0982 template
0983 <
0984     typename InputT,
0985     typename InputPolicy,
0986     typename OwnershipPolicy,
0987     typename CheckingPolicy,
0988     typename StoragePolicy
0989 >
0990 inline
0991 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0992 reference
0993 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
0994 operator*() const
0995 {
0996     CHP::check_if_valid();
0997     return SP::dereference(*this);
0998 }
0999 
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 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1012 operator->() const
1013 {
1014     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 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1104 operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1105         StoragePolicy>& y) const
1106 {
1107     bool is_eof_ = SP::is_eof(*this);
1108     bool y_is_eof_ = SP::is_eof(y);
1109     
1110     if (is_eof_ && y_is_eof_)
1111     {
1112         return true;  // both are EOF
1113     }
1114     else if (is_eof_ ^ y_is_eof_)
1115     {
1116         return false; // one is EOF, one isn't
1117     }
1118     else if (!IP::same_input(y))
1119     {
1120         return false;
1121     }
1122     else
1123     {
1124         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 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     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