// 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 |