// Copyright (c) 2001, Daniel C. Nuffer // Copyright (c) 2001-2011 Hartmut Kaiser // http://spirit.sourceforge.net/ // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM) #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM #include #include #include #include #include #include #include namespace boost { namespace spirit { /////////////////////////////////////////////////////////////////////////// // The default multi_pass instantiation uses a ref-counted std_deque scheme. /////////////////////////////////////////////////////////////////////////// template class multi_pass : private boost::base_from_member< typename Policies::BOOST_NESTED_TEMPLATE shared*> , public Policies::BOOST_NESTED_TEMPLATE unique #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) , typename iterator_base_creator::type #endif { private: // unique and shared data types typedef typename Policies::BOOST_NESTED_TEMPLATE unique policies_base_type; typedef typename Policies::BOOST_NESTED_TEMPLATE shared shared_data_type; typedef boost::base_from_member member_base; // define the types the standard embedded iterator typedefs are taken // from #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) typedef typename iterator_base_creator::type iterator_type; #else typedef typename policies_base_type::input_policy iterator_type; #endif public: // standard iterator typedefs typedef std::forward_iterator_tag iterator_category; typedef typename iterator_type::value_type value_type; typedef typename iterator_type::difference_type difference_type; typedef typename iterator_type::distance_type distance_type; typedef typename iterator_type::reference reference; typedef typename iterator_type::pointer pointer; multi_pass() : member_base(static_cast(0)) {} explicit multi_pass(T& input) : member_base(new shared_data_type(input)), policies_base_type(input) {} explicit multi_pass(T const& input) : member_base(new shared_data_type(input)), policies_base_type(input) {} multi_pass(multi_pass const& x) : member_base(x.member), policies_base_type(x) { policies_base_type::clone(*this); } #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514) // The standard library shipped with gcc-3.1 has a bug in // bits/basic_string.tcc. It tries to use iter::iter(0) to // construct an iterator. Ironically, this happens in sanity // checking code that isn't required by the standard. // The workaround is to provide an additional constructor that // ignores its int argument and behaves like the default constructor. multi_pass(int) : member_base(static_cast(0)) {} #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514) ~multi_pass() { if (policies_base_type::release(*this)) { policies_base_type::destroy(*this); delete this->member; } } multi_pass& operator=(multi_pass const& x) { if (this != &x) { multi_pass temp(x); temp.swap(*this); } return *this; } void swap(multi_pass& x) { boost::swap(this->member, x.member); this->policies_base_type::swap(x); } reference operator*() const { policies_base_type::docheck(*this); return policies_base_type::dereference(*this); } pointer operator->() const { return &(operator*()); } multi_pass& operator++() { policies_base_type::docheck(*this); policies_base_type::increment(*this); return *this; } multi_pass operator++(int) { multi_pass tmp(*this); ++*this; return tmp; } void clear_queue(BOOST_SCOPED_ENUM(traits::clear_mode) mode = traits::clear_mode::clear_if_enabled) { if (mode == traits::clear_mode::clear_always || !inhibit_clear_queue()) policies_base_type::clear_queue(*this); } bool inhibit_clear_queue() const { return this->member->inhibit_clear_queue_; } void inhibit_clear_queue(bool flag) { this->member->inhibit_clear_queue_ = flag; } bool operator==(multi_pass const& y) const { if (is_eof()) return y.is_eof(); if (y.is_eof()) return false; return policies_base_type::equal_to(*this, y); } bool operator<(multi_pass const& y) const { return policies_base_type::less_than(*this, y); } bool operator!=(multi_pass const& y) { return !(*this == y); } bool operator>(multi_pass const& y) { return y < *this; } bool operator>=(multi_pass const& y) { return !(*this < y); } bool operator<=(multi_pass const& y) { return !(y < *this); } // allow access to base member shared_data_type* shared() const { return this->member; } private: // helper functions bool is_eof() const { return (0 == this->member) || policies_base_type::is_eof(*this); } }; /////////////////////////////////////////////////////////////////////////// // Generator function /////////////////////////////////////////////////////////////////////////// template inline multi_pass make_multi_pass(T& i) { return multi_pass(i); } template inline multi_pass make_multi_pass(T const& i) { return multi_pass(i); } /////////////////////////////////////////////////////////////////////////// template inline multi_pass make_default_multi_pass(T& i) { return multi_pass(i); } template inline multi_pass make_default_multi_pass(T const& i) { return multi_pass(i); } /////////////////////////////////////////////////////////////////////////// template inline void swap(multi_pass &x, multi_pass &y) { x.swap(y); } /////////////////////////////////////////////////////////////////////////// // define special functions allowing to integrate any multi_pass iterator // with expectation points namespace traits { template void clear_queue(multi_pass& mp , BOOST_SCOPED_ENUM(traits::clear_mode) mode) { mp.clear_queue(mode); } template void inhibit_clear_queue(multi_pass& mp, bool flag) { mp.inhibit_clear_queue(flag); } template bool inhibit_clear_queue(multi_pass& mp) { return mp.inhibit_clear_queue(); } } }} // namespace boost::spirit #endif