Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/spirit/iterator/multi_pass.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 32.9 KB
Line 
1/*=============================================================================
2    Copyright (c) 2001, Daniel C. Nuffer
3    http://spirit.sourceforge.net/
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
10#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
11
12#include <boost/config.hpp>
13#include <boost/throw_exception.hpp>
14#include <deque>
15#include <iterator>
16#include <iostream>
17#include <algorithm>    // for std::swap
18#include <exception>    // for std::exception
19#include <boost/limits.hpp>
20#include <boost/iterator.hpp>
21
22#include <boost/spirit/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
23#include <boost/spirit/iterator/fixed_size_queue.hpp>
24#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
25
26#include <boost/spirit/iterator/multi_pass_fwd.hpp>
27
28namespace boost { namespace spirit {
29
30namespace impl {
31    template <typename T>
32    inline void mp_swap(T& t1, T& t2);
33}
34
35namespace 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///////////////////////////////////////////////////////////////////////////////
45class ref_counted
46{
47    protected:
48        ref_counted()
49            : 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        bool release()
66        {
67            if (!--*count)
68            {
69                delete count;
70                count = 0;
71                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        bool unique() const
86        {
87            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///////////////////////////////////////////////////////////////////////////////
106class 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///////////////////////////////////////////////////////////////////////////////
148class illegal_backtracking : public std::exception
149{
150public:
151
152    illegal_backtracking() throw() {}
153    ~illegal_backtracking() throw() {}
154
155    virtual const char*
156    what() const throw()
157    { return "boost::spirit::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///////////////////////////////////////////////////////////////////////////////
168class buf_id_check
169{
170    protected:
171        buf_id_check()
172            : shared_buf_id(new unsigned long(0))
173            , 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        void destroy()
183        {
184            delete shared_buf_id;
185            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() 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///////////////////////////////////////////////////////////////////////////////
220class 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() 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///////////////////////////////////////////////////////////////////////////////
240class std_deque
241{
242    public:
243
244template <typename ValueT>
245class 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        inner()
255            : queuedElements(new queue_type)
256            , queuePosition(0)
257        {}
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        static typename MultiPassT::reference dereference(MultiPassT const& mp)
283        {
284            if (mp.queuePosition == mp.queuedElements->size())
285            {
286                // check if this is the only iterator
287                if (mp.unique())
288                {
289                    // free up the memory used by the queue.
290                    if (mp.queuedElements->size() > 0)
291                    {
292                        mp.queuedElements->clear();
293                        mp.queuePosition = 0;
294                    }
295                }
296                return mp.get_input();
297            }
298            else
299            {
300                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        static void increment(MultiPassT& mp)
309        {
310            if (mp.queuePosition == mp.queuedElements->size())
311            {
312                // check if this is the only iterator
313                if (mp.unique())
314                {
315                    // free up the memory used by the queue.
316                    if (mp.queuedElements->size() > 0)
317                    {
318                        mp.queuedElements->clear();
319                        mp.queuePosition = 0;
320                    }
321                }
322                else
323                {
324                    mp.queuedElements->push_back(mp.get_input());
325                    ++mp.queuePosition;
326                }
327                mp.advance_input();
328            }
329            else
330            {
331                ++mp.queuePosition;
332            }
333
334        }
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        static bool is_eof(MultiPassT const& mp)
346        {
347            return mp.queuePosition == mp.queuedElements->size() &&
348                mp.input_at_eof();
349        }
350
351        // called by operator==
352        bool equal_to(inner const& x) const
353        {
354            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::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///////////////////////////////////////////////////////////////////////////////
378template < std::size_t N>
379class fixed_size_queue
380{
381    public:
382
383template <typename ValueT>
384class inner
385{
386    private:
387
388        typedef boost::spirit::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///////////////////////////////////////////////////////////////////////////////
484class input_iterator
485{
486    public:
487
488template <typename InputT>
489class inner
490{
491        typedef
492            typename boost::detail::iterator_traits<InputT>::value_type
493            result_type;
494
495        struct Data {
496            Data(InputT const &input_) 
497            :   input(input_), was_initialized(false)
498            {}
499           
500            InputT input;
501            result_type curtok;
502            bool was_initialized;
503        };
504
505       // Needed by compilers not implementing the resolution to DR45. For
506       // reference, see
507       // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
508
509       friend struct Data;
510
511    public:
512        typedef result_type value_type;
513        typedef
514            typename boost::detail::iterator_traits<InputT>::difference_type
515            difference_type;
516        typedef
517            typename boost::detail::iterator_traits<InputT>::pointer
518            pointer;
519        typedef
520            typename boost::detail::iterator_traits<InputT>::reference
521            reference;
522
523    protected:
524        inner()
525            : data(0)
526        {}
527
528        inner(InputT x)
529            : data(new Data(x))
530        {}
531
532        inner(inner const& x)
533            : data(x.data)
534        {}
535
536        void destroy()
537        {
538            delete data;
539            data = 0;
540        }
541
542        bool same_input(inner const& x) const
543        {
544            return data == x.data;
545        }
546
547        typedef
548            typename boost::detail::iterator_traits<InputT>::value_type
549            value_t;
550        void swap(inner& x)
551        {
552            impl::mp_swap(data, x.data);
553        }
554
555        void ensure_initialized() const
556        {
557            if (data && !data->was_initialized) {
558                data->curtok = *data->input;      // get the first token
559                data->was_initialized = true;
560            }
561        }
562
563    public:
564        reference get_input() const
565        {
566            BOOST_SPIRIT_ASSERT(NULL != data);
567            ensure_initialized();
568            return data->curtok;
569        }
570
571        void advance_input()
572        {
573            BOOST_SPIRIT_ASSERT(NULL != data);
574            data->was_initialized = false;        // should get the next token
575            ++data->input;
576        }
577
578        bool input_at_eof() const
579        {
580            return !data || data->input == InputT();
581        }
582
583    private:
584        Data *data;
585};
586
587};
588
589///////////////////////////////////////////////////////////////////////////////
590// class lex_input
591// Implementation of the InputPolicy used by multi_pass
592// lex_input gets tokens (ints) from yylex()
593///////////////////////////////////////////////////////////////////////////////
594class lex_input
595{
596    public:
597
598template <typename InputT>
599class inner
600{
601    public:
602        typedef int value_type;
603    typedef std::ptrdiff_t difference_type;
604        typedef int* pointer;
605        typedef int& reference;
606
607    protected:
608        inner()
609            : curtok(new int(0))
610        {}
611
612        inner(InputT x)
613            : curtok(new int(x))
614        {}
615
616        inner(inner const& x)
617            : curtok(x.curtok)
618        {}
619
620        void destroy()
621        {
622            delete curtok;
623            curtok = 0;
624        }
625
626        bool same_input(inner const& x) const
627        {
628            return curtok == x.curtok;
629        }
630
631        void swap(inner& x)
632        {
633            impl::mp_swap(curtok, x.curtok);
634        }
635
636    public:
637        reference get_input() const
638        {
639            return *curtok;
640        }
641
642        void advance_input()
643        {
644            extern int yylex();
645            *curtok = yylex();
646        }
647
648        bool input_at_eof() const
649        {
650            return *curtok == 0;
651        }
652
653    private:
654        int* curtok;
655
656};
657
658};
659
660///////////////////////////////////////////////////////////////////////////////
661// class functor_input
662// Implementation of the InputPolicy used by multi_pass
663// functor_input gets tokens from a functor
664// Note: the functor must have a typedef for result_type
665// It also must have a static variable of type result_type defined to
666// represent eof that is called eof.
667///////////////////////////////////////////////////////////////////////////////
668class functor_input
669{
670    public:
671
672template <typename FunctorT>
673class inner
674{
675    typedef typename FunctorT::result_type result_type;
676    public:
677        typedef result_type value_type;
678    typedef std::ptrdiff_t difference_type;
679        typedef result_type* pointer;
680        typedef result_type& reference;
681
682    protected:
683        inner()
684            : ftor(0)
685            , curtok(0)
686        {}
687
688        inner(FunctorT const& x)
689            : ftor(new FunctorT(x))
690            , curtok(new result_type((*ftor)()))
691        {}
692
693        inner(inner const& x)
694            : ftor(x.ftor)
695            , curtok(x.curtok)
696        {}
697
698        void destroy()
699        {
700            delete ftor;
701            ftor = 0;
702            delete curtok;
703            curtok = 0;
704        }
705
706        bool same_input(inner const& x) const
707        {
708            return ftor == x.ftor;
709        }
710
711        void swap(inner& x)
712        {
713            impl::mp_swap(curtok, x.curtok);
714            impl::mp_swap(ftor, x.ftor);
715        }
716
717    public:
718        reference get_input() const
719        {
720            return *curtok;
721        }
722
723        void advance_input()
724        {
725            if (curtok) {
726                *curtok = (*ftor)();
727            }
728        }
729
730        bool input_at_eof() const
731        {
732            return !curtok || *curtok == ftor->eof;
733        }
734
735        FunctorT& get_functor() const
736        {
737            return *ftor;
738        }
739
740
741    private:
742        FunctorT* ftor;
743        result_type* curtok;
744
745};
746
747};
748
749} // namespace multi_pass_policies
750
751///////////////////////////////////////////////////////////////////////////////
752// iterator_base_creator
753///////////////////////////////////////////////////////////////////////////////
754
755namespace iterator_ { namespace impl {
756
757// Meta-function to generate a std::iterator<> base class for multi_pass. This
758//  is used mainly to improve conformance of compilers not supporting PTS
759//  and thus relying on inheritance to recognize an iterator.
760// We are using boost::iterator<> because it offers an automatic workaround
761//  for broken std::iterator<> implementations.
762template <typename InputPolicyT, typename InputT>
763struct iterator_base_creator
764{
765    typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
766
767    typedef boost::iterator
768    <
769        std::forward_iterator_tag,
770        typename input_t::value_type,
771        typename input_t::difference_type,
772        typename input_t::pointer,
773        typename input_t::reference
774    > type;
775};
776
777}}
778
779///////////////////////////////////////////////////////////////////////////////
780// class template multi_pass
781///////////////////////////////////////////////////////////////////////////////
782
783// The default multi_pass instantiation uses a ref-counted std_deque scheme.
784template
785<
786    typename InputT,
787    typename InputPolicy,
788    typename OwnershipPolicy,
789    typename CheckingPolicy,
790    typename StoragePolicy
791>
792class multi_pass
793    : public OwnershipPolicy
794    , public CheckingPolicy
795    , public StoragePolicy::template inner<
796                typename InputPolicy::template inner<InputT>::value_type>
797    , public InputPolicy::template inner<InputT>
798    , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
799{
800        typedef OwnershipPolicy OP;
801        typedef CheckingPolicy CHP;
802        typedef typename StoragePolicy::template inner<
803            typename InputPolicy::template inner<InputT>::value_type> SP;
804        typedef typename InputPolicy::template inner<InputT> IP;
805        typedef typename
806            iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
807            IB;
808
809    public:
810        typedef typename IB::value_type value_type;
811        typedef typename IB::difference_type difference_type;
812        typedef typename IB::reference reference;
813        typedef typename IB::pointer pointer;
814        typedef InputT iterator_type;
815
816        multi_pass();
817        explicit multi_pass(InputT input);
818
819#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
820        multi_pass(int);
821#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
822
823        ~multi_pass();
824
825        multi_pass(multi_pass const&);
826        multi_pass& operator=(multi_pass const&);
827
828        void swap(multi_pass& x);
829
830        reference operator*() const;
831        pointer operator->() const;
832        multi_pass& operator++();
833        multi_pass operator++(int);
834
835        void clear_queue();
836
837        bool operator==(const multi_pass& y) const;
838        bool operator<(const multi_pass& y) const;
839
840    private: // helper functions
841        bool is_eof() const;
842};
843
844template
845<
846    typename InputT,
847    typename InputPolicy,
848    typename OwnershipPolicy,
849    typename CheckingPolicy,
850    typename StoragePolicy
851>
852inline
853multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
854multi_pass()
855    : OP()
856    , CHP()
857    , SP()
858    , IP()
859{
860}
861
862template
863<
864    typename InputT,
865    typename InputPolicy,
866    typename OwnershipPolicy,
867    typename CheckingPolicy,
868    typename StoragePolicy
869>
870inline
871multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
872multi_pass(InputT input)
873    : OP()
874    , CHP()
875    , SP()
876    , IP(input)
877{
878}
879
880#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
881    // The standard library shipped with gcc-3.1 has a bug in
882    // bits/basic_string.tcc. It tries  to use iter::iter(0) to
883    // construct an iterator. Ironically, this  happens in sanity
884    // checking code that isn't required by the standard.
885    // The workaround is to provide an additional constructor that
886    // ignores its int argument and behaves like the default constructor.
887template
888<
889    typename InputT,
890    typename InputPolicy,
891    typename OwnershipPolicy,
892    typename CheckingPolicy,
893    typename StoragePolicy
894>
895inline
896multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
897multi_pass(int)
898    : OP()
899    , CHP()
900    , SP()
901    , IP()
902{
903}
904#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
905
906template
907<
908    typename InputT,
909    typename InputPolicy,
910    typename OwnershipPolicy,
911    typename CheckingPolicy,
912    typename StoragePolicy
913>
914inline
915multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
916~multi_pass()
917{
918    if (OP::release())
919    {
920        CHP::destroy();
921        SP::destroy();
922        IP::destroy();
923    }
924}
925
926template
927<
928    typename InputT,
929    typename InputPolicy,
930    typename OwnershipPolicy,
931    typename CheckingPolicy,
932    typename StoragePolicy
933>
934inline
935multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
936multi_pass(
937        multi_pass const& x)
938    : OP(x)
939    , CHP(x)
940    , SP(x)
941    , IP(x)
942{
943    OP::clone();
944}
945
946template
947<
948    typename InputT,
949    typename InputPolicy,
950    typename OwnershipPolicy,
951    typename CheckingPolicy,
952    typename StoragePolicy
953>
954inline
955multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
956multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
957operator=(
958        multi_pass const& x)
959{
960    multi_pass temp(x);
961    temp.swap(*this);
962    return *this;
963}
964
965template
966<
967    typename InputT,
968    typename InputPolicy,
969    typename OwnershipPolicy,
970    typename CheckingPolicy,
971    typename StoragePolicy
972>
973inline void
974multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
975swap(multi_pass& x)
976{
977    OP::swap(x);
978    CHP::swap(x);
979    SP::swap(x);
980    IP::swap(x);
981}
982
983template
984<
985    typename InputT,
986    typename InputPolicy,
987    typename OwnershipPolicy,
988    typename CheckingPolicy,
989    typename StoragePolicy
990>
991inline
992typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
993reference
994multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
995operator*() const
996{
997    CHP::check();
998    return SP::dereference(*this);
999}
1000
1001template
1002<
1003    typename InputT,
1004    typename InputPolicy,
1005    typename OwnershipPolicy,
1006    typename CheckingPolicy,
1007    typename StoragePolicy
1008>
1009inline
1010typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1011pointer
1012multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1013operator->() const
1014{
1015    return &(operator*());
1016}
1017
1018template
1019<
1020    typename InputT,
1021    typename InputPolicy,
1022    typename OwnershipPolicy,
1023    typename CheckingPolicy,
1024    typename StoragePolicy
1025>
1026inline
1027multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
1028multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1029operator++()
1030{
1031    CHP::check();
1032    SP::increment(*this);
1033    return *this;
1034}
1035
1036template
1037<
1038    typename InputT,
1039    typename InputPolicy,
1040    typename OwnershipPolicy,
1041    typename CheckingPolicy,
1042    typename StoragePolicy
1043>
1044inline
1045multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
1046multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1047operator++(int)
1048{
1049    multi_pass
1050    <
1051        InputT,
1052        InputPolicy,
1053        OwnershipPolicy,
1054        CheckingPolicy,
1055        StoragePolicy
1056    > tmp(*this);
1057
1058    ++*this;
1059
1060    return tmp;
1061}
1062
1063template
1064<
1065    typename InputT,
1066    typename InputPolicy,
1067    typename OwnershipPolicy,
1068    typename CheckingPolicy,
1069    typename StoragePolicy
1070>
1071inline void
1072multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1073clear_queue()
1074{
1075    SP::clear_queue();
1076    CHP::clear_queue();
1077}
1078
1079template
1080<
1081    typename InputT,
1082    typename InputPolicy,
1083    typename OwnershipPolicy,
1084    typename CheckingPolicy,
1085    typename StoragePolicy
1086>
1087inline bool
1088multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1089is_eof() const
1090{
1091    return SP::is_eof(*this);
1092}
1093
1094///// Comparisons
1095template
1096<
1097    typename InputT,
1098    typename InputPolicy,
1099    typename OwnershipPolicy,
1100    typename CheckingPolicy,
1101    typename StoragePolicy
1102>
1103inline bool
1104multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1105operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1106        StoragePolicy>& y) const
1107{
1108    bool is_eof_ = SP::is_eof(*this);
1109    bool y_is_eof_ = SP::is_eof(y);
1110   
1111    if (is_eof_ && y_is_eof_)
1112    {
1113        return true;  // both are EOF
1114    }
1115    else if (is_eof_ ^ y_is_eof_)
1116    {
1117        return false; // one is EOF, one isn't
1118    }
1119    else if (!IP::same_input(y))
1120    {
1121        return false;
1122    }
1123    else
1124    {
1125        return SP::equal_to(y);
1126    }
1127}
1128
1129template
1130<
1131    typename InputT,
1132    typename InputPolicy,
1133    typename OwnershipPolicy,
1134    typename CheckingPolicy,
1135    typename StoragePolicy
1136>
1137inline bool
1138multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1139operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1140        StoragePolicy>& y) const
1141{
1142    return SP::less_than(y);
1143}
1144
1145template
1146<
1147    typename InputT,
1148    typename InputPolicy,
1149    typename OwnershipPolicy,
1150    typename CheckingPolicy,
1151    typename StoragePolicy
1152>
1153inline
1154bool operator!=(
1155        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1156                        StoragePolicy>& x,
1157        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1158                        StoragePolicy>& y)
1159{
1160    return !(x == y);
1161}
1162
1163template
1164<
1165    typename InputT,
1166    typename InputPolicy,
1167    typename OwnershipPolicy,
1168    typename CheckingPolicy,
1169    typename StoragePolicy
1170>
1171inline
1172bool operator>(
1173        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1174                        StoragePolicy>& x,
1175        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1176                        StoragePolicy>& y)
1177{
1178    return y < x;
1179}
1180
1181template
1182<
1183    typename InputT,
1184    typename InputPolicy,
1185    typename OwnershipPolicy,
1186    typename CheckingPolicy,
1187    typename StoragePolicy
1188>
1189inline
1190bool operator>=(
1191        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1192                        StoragePolicy>& x,
1193        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1194                        StoragePolicy>& y)
1195{
1196    return !(x < y);
1197}
1198
1199template
1200<
1201    typename InputT,
1202    typename InputPolicy,
1203    typename OwnershipPolicy,
1204    typename CheckingPolicy,
1205    typename StoragePolicy
1206>
1207inline
1208bool operator<=(
1209        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1210                        StoragePolicy>& x,
1211        const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1212                        StoragePolicy>& y)
1213{
1214    return !(y < x);
1215}
1216
1217///// Generator function
1218template <typename InputT>
1219inline multi_pass<InputT>
1220make_multi_pass(InputT i)
1221{
1222    return multi_pass<InputT>(i);
1223}
1224
1225// this could be a template typedef, since such a thing doesn't
1226// exist in C++, we'll use inheritance to accomplish the same thing.
1227
1228template <typename InputT, std::size_t N>
1229class look_ahead :
1230    public multi_pass<
1231        InputT,
1232        multi_pass_policies::input_iterator,
1233        multi_pass_policies::first_owner,
1234        multi_pass_policies::no_check,
1235        multi_pass_policies::fixed_size_queue<N> >
1236{
1237        typedef multi_pass<
1238            InputT,
1239            multi_pass_policies::input_iterator,
1240            multi_pass_policies::first_owner,
1241            multi_pass_policies::no_check,
1242            multi_pass_policies::fixed_size_queue<N> > base_t;
1243    public:
1244        look_ahead()
1245            : base_t() {}
1246
1247        explicit look_ahead(InputT x)
1248            : base_t(x) {}
1249
1250        look_ahead(look_ahead const& x)
1251            : base_t(x) {}
1252
1253#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1254        look_ahead(int)         // workaround for a bug in the library
1255            : base_t() {}       // shipped with gcc 3.1
1256#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
1257
1258    // default generated operators destructor and assignment operator are okay.
1259};
1260
1261template
1262<
1263    typename InputT,
1264    typename InputPolicy,
1265    typename OwnershipPolicy,
1266    typename CheckingPolicy,
1267    typename StoragePolicy
1268>
1269void swap(
1270    multi_pass<
1271        InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1272    > &x,
1273    multi_pass<
1274        InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
1275    > &y)
1276{
1277    x.swap(y);
1278}
1279
1280namespace impl {
1281
1282    template <typename T>
1283    inline void mp_swap(T& t1, T& t2)
1284    {
1285        using std::swap;
1286        using boost::spirit::swap;
1287        swap(t1, t2);
1288    }
1289}
1290
1291}} // namespace boost::spirit
1292
1293#endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
1294
1295
Note: See TracBrowser for help on using the repository browser.