]> git.proxmox.com Git - ceph.git/blob - 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
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
28 namespace boost { namespace spirit {
29
30 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
31
32 namespace impl {
33 template <typename T>
34 inline void mp_swap(T& t1, T& t2);
35 }
36
37 namespace 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 ///////////////////////////////////////////////////////////////////////////////
47 class 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 ///////////////////////////////////////////////////////////////////////////////
108 class 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 ///////////////////////////////////////////////////////////////////////////////
150 class illegal_backtracking : public std::exception
151 {
152 public:
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 ///////////////////////////////////////////////////////////////////////////////
170 class 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 ///////////////////////////////////////////////////////////////////////////////
222 class 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 ///////////////////////////////////////////////////////////////////////////////
242 class std_deque
243 {
244 public:
245
246 template <typename ValueT>
247 class 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 ///////////////////////////////////////////////////////////////////////////////
380 template < std::size_t N>
381 class fixed_size_queue
382 {
383 public:
384
385 template <typename ValueT>
386 class 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 ///////////////////////////////////////////////////////////////////////////////
486 class input_iterator
487 {
488 public:
489
490 template <typename InputT>
491 class 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 ///////////////////////////////////////////////////////////////////////////////
600 class lex_input
601 {
602 public:
603
604 template <typename InputT>
605 class 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 ///////////////////////////////////////////////////////////////////////////////
674 class functor_input
675 {
676 public:
677
678 template <typename FunctorT>
679 class 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
761 namespace 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.
768 template <typename InputPolicyT, typename InputT>
769 struct 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.
790 template
791 <
792 typename InputT,
793 typename InputPolicy,
794 typename OwnershipPolicy,
795 typename CheckingPolicy,
796 typename StoragePolicy
797 >
798 class 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
850 template
851 <
852 typename InputT,
853 typename InputPolicy,
854 typename OwnershipPolicy,
855 typename CheckingPolicy,
856 typename StoragePolicy
857 >
858 inline
859 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
860 multi_pass()
861 : OP()
862 , CHP()
863 , SP()
864 , IP()
865 {
866 }
867
868 template
869 <
870 typename InputT,
871 typename InputPolicy,
872 typename OwnershipPolicy,
873 typename CheckingPolicy,
874 typename StoragePolicy
875 >
876 inline
877 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
878 multi_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.
893 template
894 <
895 typename InputT,
896 typename InputPolicy,
897 typename OwnershipPolicy,
898 typename CheckingPolicy,
899 typename StoragePolicy
900 >
901 inline
902 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
903 multi_pass(int)
904 : OP()
905 , CHP()
906 , SP()
907 , IP()
908 {
909 }
910 #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
911
912 template
913 <
914 typename InputT,
915 typename InputPolicy,
916 typename OwnershipPolicy,
917 typename CheckingPolicy,
918 typename StoragePolicy
919 >
920 inline
921 multi_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
932 template
933 <
934 typename InputT,
935 typename InputPolicy,
936 typename OwnershipPolicy,
937 typename CheckingPolicy,
938 typename StoragePolicy
939 >
940 inline
941 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
942 multi_pass(
943 multi_pass const& x)
944 : OP(x)
945 , CHP(x)
946 , SP(x)
947 , IP(x)
948 {
949 OP::clone();
950 }
951
952 template
953 <
954 typename InputT,
955 typename InputPolicy,
956 typename OwnershipPolicy,
957 typename CheckingPolicy,
958 typename StoragePolicy
959 >
960 inline
961 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
962 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
963 operator=(
964 multi_pass const& x)
965 {
966 multi_pass temp(x);
967 temp.swap(*this);
968 return *this;
969 }
970
971 template
972 <
973 typename InputT,
974 typename InputPolicy,
975 typename OwnershipPolicy,
976 typename CheckingPolicy,
977 typename StoragePolicy
978 >
979 inline void
980 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
981 swap(multi_pass& x)
982 {
983 OP::swap(x);
984 CHP::swap(x);
985 SP::swap(x);
986 IP::swap(x);
987 }
988
989 template
990 <
991 typename InputT,
992 typename InputPolicy,
993 typename OwnershipPolicy,
994 typename CheckingPolicy,
995 typename StoragePolicy
996 >
997 inline
998 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
999 reference
1000 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1001 operator*() const
1002 {
1003 CHP::check_if_valid();
1004 return SP::dereference(*this);
1005 }
1006
1007 template
1008 <
1009 typename InputT,
1010 typename InputPolicy,
1011 typename OwnershipPolicy,
1012 typename CheckingPolicy,
1013 typename StoragePolicy
1014 >
1015 inline
1016 typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1017 pointer
1018 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1019 operator->() const
1020 {
1021 return &(operator*());
1022 }
1023
1024 template
1025 <
1026 typename InputT,
1027 typename InputPolicy,
1028 typename OwnershipPolicy,
1029 typename CheckingPolicy,
1030 typename StoragePolicy
1031 >
1032 inline
1033 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
1034 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1035 operator++()
1036 {
1037 CHP::check_if_valid();
1038 SP::increment(*this);
1039 return *this;
1040 }
1041
1042 template
1043 <
1044 typename InputT,
1045 typename InputPolicy,
1046 typename OwnershipPolicy,
1047 typename CheckingPolicy,
1048 typename StoragePolicy
1049 >
1050 inline
1051 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
1052 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1053 operator++(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
1069 template
1070 <
1071 typename InputT,
1072 typename InputPolicy,
1073 typename OwnershipPolicy,
1074 typename CheckingPolicy,
1075 typename StoragePolicy
1076 >
1077 inline void
1078 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1079 clear_queue()
1080 {
1081 SP::clear_queue();
1082 CHP::clear_queue();
1083 }
1084
1085 template
1086 <
1087 typename InputT,
1088 typename InputPolicy,
1089 typename OwnershipPolicy,
1090 typename CheckingPolicy,
1091 typename StoragePolicy
1092 >
1093 inline bool
1094 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1095 is_eof() const
1096 {
1097 return SP::is_eof(*this);
1098 }
1099
1100 ///// Comparisons
1101 template
1102 <
1103 typename InputT,
1104 typename InputPolicy,
1105 typename OwnershipPolicy,
1106 typename CheckingPolicy,
1107 typename StoragePolicy
1108 >
1109 inline bool
1110 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1111 operator==(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
1135 template
1136 <
1137 typename InputT,
1138 typename InputPolicy,
1139 typename OwnershipPolicy,
1140 typename CheckingPolicy,
1141 typename StoragePolicy
1142 >
1143 inline bool
1144 multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1145 operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1146 StoragePolicy>& y) const
1147 {
1148 return SP::less_than(y);
1149 }
1150
1151 template
1152 <
1153 typename InputT,
1154 typename InputPolicy,
1155 typename OwnershipPolicy,
1156 typename CheckingPolicy,
1157 typename StoragePolicy
1158 >
1159 inline
1160 bool 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
1169 template
1170 <
1171 typename InputT,
1172 typename InputPolicy,
1173 typename OwnershipPolicy,
1174 typename CheckingPolicy,
1175 typename StoragePolicy
1176 >
1177 inline
1178 bool 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
1187 template
1188 <
1189 typename InputT,
1190 typename InputPolicy,
1191 typename OwnershipPolicy,
1192 typename CheckingPolicy,
1193 typename StoragePolicy
1194 >
1195 inline
1196 bool 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
1205 template
1206 <
1207 typename InputT,
1208 typename InputPolicy,
1209 typename OwnershipPolicy,
1210 typename CheckingPolicy,
1211 typename StoragePolicy
1212 >
1213 inline
1214 bool 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
1224 template <typename InputT>
1225 inline 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>
1228 make_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
1238 template <typename InputT, std::size_t N>
1239 class 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
1271 template
1272 <
1273 typename InputT,
1274 typename InputPolicy,
1275 typename OwnershipPolicy,
1276 typename CheckingPolicy,
1277 typename StoragePolicy
1278 >
1279 void 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
1290 namespace 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
1301 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
1302
1303 }} // namespace BOOST_SPIRIT_CLASSIC_NS
1304
1305 #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
1306
1307