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