1 // Copyright (c) 2001 Daniel C. Nuffer 2 // Copyright (c) 2001-2011 Hartmut Kaiser 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(BOOST_SPIRIT_BUFFERING_ITERATOR_INPUT_ITERATOR_POLICY_MAR_04_2010_1224AM) 8 #define BOOST_SPIRIT_BUFFERING_ITERATOR_INPUT_ITERATOR_POLICY_MAR_04_2010_1224AM 9 10 #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp> 11 #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp> 12 #include <boost/spirit/home/support/iterators/detail/input_iterator_policy.hpp> 13 #include <boost/assert.hpp> 14 #include <iterator> // for std::iterator_traits 15 16 namespace boost { namespace spirit { namespace iterator_policies 17 { 18 /////////////////////////////////////////////////////////////////////////// 19 // class input_iterator 20 // 21 // Implementation of the InputPolicy used by multi_pass, this is different 22 // from the input_iterator policy only as it is buffering the last input 23 // character to allow returning it by reference. This is needed for 24 // wrapping iterators not buffering the last item (such as the 25 // std::istreambuf_iterator). Unfortunately there is no way to 26 // automatically figure this out at compile time. 27 // 28 // The buffering_input_iterator encapsulates an input iterator of type T 29 /////////////////////////////////////////////////////////////////////////// 30 struct buffering_input_iterator 31 { 32 /////////////////////////////////////////////////////////////////////// 33 template <typename T> 34 class unique // : public detail::default_input_policy 35 { 36 private: 37 typedef 38 typename std::iterator_traits<T>::value_type 39 result_type; 40 41 public: 42 typedef 43 typename std::iterator_traits<T>::difference_type 44 difference_type; 45 typedef 46 typename std::iterator_traits<T>::difference_type 47 distance_type; 48 typedef 49 typename std::iterator_traits<T>::pointer 50 pointer; 51 typedef result_type& reference; 52 typedef result_type value_type; 53 54 protected: unique()55 unique() {} unique(T)56 explicit unique(T) {} 57 swap(unique &)58 void swap(unique&) {} 59 60 public: 61 template <typename MultiPass> destroy(MultiPass &)62 static void destroy(MultiPass&) {} 63 64 template <typename MultiPass> get_input(MultiPass & mp)65 static typename MultiPass::reference get_input(MultiPass& mp) 66 { 67 return mp.shared()->get_input(); 68 } 69 70 template <typename MultiPass> advance_input(MultiPass & mp)71 static void advance_input(MultiPass& mp) 72 { 73 BOOST_ASSERT(0 != mp.shared()); 74 mp.shared()->advance_input(); 75 } 76 77 // test, whether we reached the end of the underlying stream 78 template <typename MultiPass> input_at_eof(MultiPass const & mp)79 static bool input_at_eof(MultiPass const& mp) 80 { 81 static T const end_iter; 82 return mp.shared()->input_ == end_iter; 83 } 84 85 template <typename MultiPass> input_is_valid(MultiPass const & mp,value_type const &)86 static bool input_is_valid(MultiPass const& mp, value_type const&) 87 { 88 return mp.shared()->input_is_valid_; 89 } 90 91 // no unique data elements 92 }; 93 94 /////////////////////////////////////////////////////////////////////// 95 template <typename T> 96 struct shared 97 { 98 typedef 99 typename std::iterator_traits<T>::value_type 100 result_type; 101 sharedboost::spirit::iterator_policies::buffering_input_iterator::shared102 explicit shared(T const& input) 103 : input_(input), curtok_(0), input_is_valid_(false) {} 104 advance_inputboost::spirit::iterator_policies::buffering_input_iterator::shared105 void advance_input() 106 { 107 ++input_; 108 input_is_valid_ = false; 109 } 110 get_inputboost::spirit::iterator_policies::buffering_input_iterator::shared111 result_type& get_input() 112 { 113 if (!input_is_valid_) { 114 curtok_ = *input_; 115 input_is_valid_ = true; 116 } 117 return curtok_; 118 } 119 120 T input_; 121 result_type curtok_; 122 bool input_is_valid_; 123 }; 124 }; 125 126 }}} 127 128 #endif 129