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