PageRenderTime 68ms CodeModel.GetById 5ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/spirit/home/classic/iterator/multi_pass.hpp

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