source: NonGTP/Boost/boost/spirit/iterator/multi_pass.hpp @ 857

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