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