1 /*=============================================================================
2 Copyright (c) 2001-2011 Hartmut Kaiser
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_ITERATOR_ISTREAM_MAY_05_2007_0110PM)
8 #define BOOST_SPIRIT_ITERATOR_ISTREAM_MAY_05_2007_0110PM
14 #include <boost/iostreams/stream.hpp>
15 #include <iterator> // for std::iterator_traits, std::distance
17 ///////////////////////////////////////////////////////////////////////////////
18 namespace boost { namespace spirit { namespace qi { namespace detail
20 ///////////////////////////////////////////////////////////////////////////
21 template <typename Iterator>
22 struct base_iterator_source
24 typedef typename std::iterator_traits<Iterator>::value_type char_type;
25 typedef boost::iostreams::seekable_device_tag category;
27 base_iterator_source (Iterator const& first_, Iterator const& last_)
28 : first(first_), last(last_), pos(0)
31 // Read up to n characters from the input sequence into the buffer s,
32 // returning the number of characters read, or -1 to indicate
34 std::streamsize read (char_type* s, std::streamsize n)
39 std::streamsize bytes_read = 0;
51 // Write is implemented only to satisfy the requirements of a
52 // boost::iostreams::seekable_device. We need to have see support to
53 // be able to figure out how many characters have been actually
54 // consumed by the stream.
55 std::streamsize write(const char_type*, std::streamsize)
57 BOOST_ASSERT(false); // not supported
61 std::streampos seek(boost::iostreams::stream_offset, std::ios_base::seekdir way)
64 BOOST_ASSERT(way == std::ios_base::cur); // only support queries
65 return pos; // return current position
72 // silence MSVC warning C4512: assignment operator could not be generated
73 BOOST_DELETED_FUNCTION(base_iterator_source& operator= (base_iterator_source const&))
76 template <typename Iterator, typename Enable = void>
77 struct iterator_source : base_iterator_source<Iterator>
79 typedef base_iterator_source<Iterator> base_type;
81 iterator_source (Iterator const& first_, Iterator const& last_)
82 : base_type(first_, last_) {}
85 // Specialization for random-access iterators. This also allows compilers
86 // to fully optimize the case when the source range is contiguous
87 template <typename Iterator>
88 struct iterator_source<
90 typename boost::enable_if_c<boost::is_convertible<
91 typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>::value>::type
92 > : base_iterator_source<Iterator>
94 typedef base_iterator_source<Iterator> base_type;
96 iterator_source (Iterator const& first_, Iterator const& last_)
97 : base_type(first_, last_) {}
99 typedef typename base_type::char_type char_type;
100 using base_type::first;
101 using base_type::last;
102 using base_type::pos;
104 // Read up to n characters from the input sequence into the buffer s,
105 // returning the number of characters read, or -1 to indicate
107 std::streamsize read (char_type* s, std::streamsize n)
112 n = (std::min)(static_cast<std::streamsize>(last - first), n);
114 typedef typename std::iterator_traits<Iterator>::difference_type diff_type;
116 // copy_n is only part of c++11, so emulate it
117 std::copy(first, first + static_cast<diff_type>(n), s);
118 first += static_cast<diff_type>(n);