blob: 5f5bba028f0034b17d67beddace48c093d1109d6 [file] [log] [blame]
// Copyright (c) 2001 Daniel C. Nuffer
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// 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_BUFFERING_ITERATOR_INPUT_ITERATOR_POLICY_MAR_04_2010_1224AM)
#define BOOST_SPIRIT_BUFFERING_ITERATOR_INPUT_ITERATOR_POLICY_MAR_04_2010_1224AM
#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/input_iterator_policy.hpp>
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
#include <boost/assert.hpp>
namespace boost { namespace spirit { namespace iterator_policies
{
///////////////////////////////////////////////////////////////////////////
// class input_iterator
//
// Implementation of the InputPolicy used by multi_pass, this is different
// from the input_iterator policy only as it is buffering the last input
// character to allow returning it by reference. This is needed for
// wrapping iterators not buffering the last item (such as the
// std::istreambuf_iterator). Unfortunately there is no way to
// automatically figure this out at compile time.
//
// The buffering_input_iterator encapsulates an input iterator of type T
///////////////////////////////////////////////////////////////////////////
struct buffering_input_iterator
{
///////////////////////////////////////////////////////////////////////
template <typename T>
class unique // : public detail::default_input_policy
{
private:
typedef
typename boost::detail::iterator_traits<T>::value_type
result_type;
public:
typedef
typename boost::detail::iterator_traits<T>::difference_type
difference_type;
typedef
typename boost::detail::iterator_traits<T>::difference_type
distance_type;
typedef
typename boost::detail::iterator_traits<T>::pointer
pointer;
typedef
typename boost::detail::iterator_traits<T>::reference
reference;
typedef result_type value_type;
protected:
unique() {}
explicit unique(T x) {}
void swap(unique&) {}
public:
template <typename MultiPass>
static void destroy(MultiPass&) {}
template <typename MultiPass>
static typename MultiPass::reference get_input(MultiPass& mp)
{
return mp.shared()->get_input();
}
template <typename MultiPass>
static void advance_input(MultiPass& mp)
{
BOOST_ASSERT(0 != mp.shared());
mp.shared()->advance_input();
}
// test, whether we reached the end of the underlying stream
template <typename MultiPass>
static bool input_at_eof(MultiPass const& mp)
{
static T const end_iter;
return mp.shared()->input_ == end_iter;
}
template <typename MultiPass>
static bool input_is_valid(MultiPass const& mp, value_type const& t)
{
return mp.shared()->input_is_valid_;
}
// no unique data elements
};
///////////////////////////////////////////////////////////////////////
template <typename T>
struct shared
{
typedef
typename boost::detail::iterator_traits<T>::value_type
result_type;
explicit shared(T const& input)
: input_(input), curtok_(0), input_is_valid_(false) {}
void advance_input()
{
++input_;
input_is_valid_ = false;
}
result_type& get_input()
{
if (!input_is_valid_) {
curtok_ = *input_;
input_is_valid_ = true;
}
return curtok_;
}
T input_;
result_type curtok_;
bool input_is_valid_;
};
};
}}}
#endif