blob: 6587a7efbab4a8560f9a17b60437fcfc49a4edc9 [file] [log] [blame]
// 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