Line data Source code
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 0 : ref_counted()
49 0 : : 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 0 : bool release()
66 : {
67 0 : if (!--*count)
68 : {
69 0 : delete count;
70 0 : count = 0;
71 0 : 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 0 : bool unique() const
86 : {
87 0 : 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 0 : ~illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {}
154 :
155 : virtual const char*
156 0 : what() const BOOST_NOEXCEPT_OR_NOTHROW
157 0 : { 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 0 : buf_id_check()
172 0 : : shared_buf_id(new unsigned long(0))
173 0 : , 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 0 : void destroy()
183 : {
184 0 : delete shared_buf_id;
185 0 : 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 0 : inner()
255 0 : : queuedElements(new queue_type)
256 0 : , queuePosition(0)
257 0 : {}
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 0 : static typename MultiPassT::reference dereference(MultiPassT const& mp)
283 : {
284 0 : if (mp.queuePosition == mp.queuedElements->size())
285 : {
286 : // check if this is the only iterator
287 0 : if (mp.unique())
288 : {
289 : // free up the memory used by the queue.
290 0 : if (mp.queuedElements->size() > 0)
291 : {
292 0 : mp.queuedElements->clear();
293 0 : mp.queuePosition = 0;
294 : }
295 : }
296 0 : return mp.get_input();
297 : }
298 : else
299 : {
300 0 : 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 0 : static void increment(MultiPassT& mp)
309 : {
310 0 : if (mp.queuePosition == mp.queuedElements->size())
311 : {
312 : // check if this is the only iterator
313 0 : if (mp.unique())
314 : {
315 : // free up the memory used by the queue.
316 0 : if (mp.queuedElements->size() > 0)
317 : {
318 0 : mp.queuedElements->clear();
319 0 : mp.queuePosition = 0;
320 : }
321 : }
322 : else
323 : {
324 0 : mp.queuedElements->push_back(mp.get_input());
325 0 : ++mp.queuePosition;
326 : }
327 0 : mp.advance_input();
328 : }
329 : else
330 : {
331 0 : ++mp.queuePosition;
332 : }
333 :
334 0 : }
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 0 : static bool is_eof(MultiPassT const& mp)
346 : {
347 0 : return mp.queuePosition == mp.queuedElements->size() &&
348 0 : mp.input_at_eof();
349 : }
350 :
351 : // called by operator==
352 0 : bool equal_to(inner const& x) const
353 : {
354 0 : 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 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
853 : multi_pass()
854 : : OP()
855 : , CHP()
856 : , SP()
857 0 : , IP()
858 : {
859 0 : }
860 :
861 : template
862 : <
863 : typename InputT,
864 : typename InputPolicy,
865 : typename OwnershipPolicy,
866 : typename CheckingPolicy,
867 : typename StoragePolicy
868 : >
869 : inline
870 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
871 : multi_pass(InputT input)
872 : : OP()
873 : , CHP()
874 : , SP()
875 0 : , IP(input)
876 : {
877 0 : }
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 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
915 : ~multi_pass()
916 : {
917 0 : if (OP::release())
918 : {
919 0 : CHP::destroy();
920 0 : SP::destroy();
921 0 : IP::destroy();
922 : }
923 0 : }
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 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
994 : operator*() const
995 : {
996 0 : CHP::check_if_valid();
997 0 : 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 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1012 : operator->() const
1013 : {
1014 0 : 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 0 : multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
1104 : operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
1105 : StoragePolicy>& y) const
1106 : {
1107 0 : bool is_eof_ = SP::is_eof(*this);
1108 0 : bool y_is_eof_ = SP::is_eof(y);
1109 :
1110 0 : if (is_eof_ && y_is_eof_)
1111 : {
1112 : return true; // both are EOF
1113 : }
1114 0 : else if (is_eof_ ^ y_is_eof_)
1115 : {
1116 : return false; // one is EOF, one isn't
1117 : }
1118 0 : else if (!IP::same_input(y))
1119 : {
1120 : return false;
1121 : }
1122 : else
1123 : {
1124 0 : 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 0 : 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 0 : 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 :
|