// 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 <boost/config.hpp> | |
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp> | |
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp> | |
#include <boost/spirit/home/support/iterators/detail/combine_policies.hpp> | |
#include <boost/limits.hpp> | |
#include <boost/detail/workaround.hpp> | |
#include <boost/utility/base_from_member.hpp> | |
namespace boost { namespace spirit | |
{ | |
/////////////////////////////////////////////////////////////////////////// | |
// The default multi_pass instantiation uses a ref-counted std_deque scheme. | |
/////////////////////////////////////////////////////////////////////////// | |
template<typename T, typename Policies> | |
class multi_pass | |
: private boost::base_from_member< | |
typename Policies::BOOST_NESTED_TEMPLATE shared<T>*> | |
, public Policies::BOOST_NESTED_TEMPLATE unique<T> | |
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | |
, typename iterator_base_creator<T, typename Policies::input_policy>::type | |
#endif | |
{ | |
private: | |
// unique and shared data types | |
typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T> | |
policies_base_type; | |
typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T> | |
shared_data_type; | |
typedef boost::base_from_member<shared_data_type*> 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<Input, T>::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((shared_data_type*)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((shared_data_type*)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 <typename Policies, typename T> | |
inline multi_pass<T, Policies> | |
make_multi_pass(T& i) | |
{ | |
return multi_pass<T, Policies>(i); | |
} | |
template <typename Policies, typename T> | |
inline multi_pass<T, Policies> | |
make_multi_pass(T const& i) | |
{ | |
return multi_pass<T, Policies>(i); | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename T> | |
inline multi_pass<T> | |
make_default_multi_pass(T& i) | |
{ | |
return multi_pass<T>(i); | |
} | |
template <typename T> | |
inline multi_pass<T> | |
make_default_multi_pass(T const& i) | |
{ | |
return multi_pass<T>(i); | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
template <typename T, typename Policies> | |
inline void | |
swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y) | |
{ | |
x.swap(y); | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
// define special functions allowing to integrate any multi_pass iterator | |
// with expectation points | |
namespace traits | |
{ | |
template <typename T, typename Policies> | |
void clear_queue(multi_pass<T, Policies>& mp | |
, BOOST_SCOPED_ENUM(traits::clear_mode) mode) | |
{ | |
mp.clear_queue(mode); | |
} | |
template <typename T, typename Policies> | |
void inhibit_clear_queue(multi_pass<T, Policies>& mp, bool flag) | |
{ | |
mp.inhibit_clear_queue(flag); | |
} | |
template <typename T, typename Policies> | |
bool inhibit_clear_queue(multi_pass<T, Policies>& mp) | |
{ | |
return mp.inhibit_clear_queue(); | |
} | |
} | |
}} // namespace boost::spirit | |
#endif | |