]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
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_ITERATOR_ISTREAM_MAY_05_2007_0110PM) | |
8 | #define BOOST_SPIRIT_ITERATOR_ISTREAM_MAY_05_2007_0110PM | |
9 | ||
10 | #if defined(_MSC_VER) | |
11 | #pragma once | |
12 | #endif | |
13 | ||
14 | #include <boost/iostreams/stream.hpp> | |
92f5a8d4 | 15 | #include <iterator> // for std::iterator_traits, std::distance |
7c673cae FG |
16 | |
17 | /////////////////////////////////////////////////////////////////////////////// | |
18 | namespace boost { namespace spirit { namespace qi { namespace detail | |
19 | { | |
20 | /////////////////////////////////////////////////////////////////////////// | |
21 | template <typename Iterator> | |
92f5a8d4 | 22 | struct base_iterator_source |
7c673cae | 23 | { |
92f5a8d4 | 24 | typedef typename std::iterator_traits<Iterator>::value_type char_type; |
7c673cae FG |
25 | typedef boost::iostreams::seekable_device_tag category; |
26 | ||
92f5a8d4 | 27 | base_iterator_source (Iterator const& first_, Iterator const& last_) |
7c673cae FG |
28 | : first(first_), last(last_), pos(0) |
29 | {} | |
30 | ||
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 | |
33 | // end-of-sequence. | |
34 | std::streamsize read (char_type* s, std::streamsize n) | |
35 | { | |
36 | if (first == last) | |
37 | return -1; | |
38 | ||
39 | std::streamsize bytes_read = 0; | |
40 | while (n--) { | |
41 | *s = *first; | |
42 | ++s; ++bytes_read; | |
43 | if (++first == last) | |
44 | break; | |
45 | } | |
46 | ||
47 | pos += bytes_read; | |
48 | return bytes_read; | |
49 | } | |
50 | ||
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) | |
56 | { | |
57 | BOOST_ASSERT(false); // not supported | |
58 | return -1; | |
59 | } | |
60 | ||
61 | std::streampos seek(boost::iostreams::stream_offset, std::ios_base::seekdir way) | |
62 | { | |
92f5a8d4 | 63 | (void)way; |
7c673cae FG |
64 | BOOST_ASSERT(way == std::ios_base::cur); // only support queries |
65 | return pos; // return current position | |
66 | } | |
67 | ||
68 | Iterator first; | |
69 | Iterator const& last; | |
70 | std::streamsize pos; | |
71 | ||
7c673cae | 72 | // silence MSVC warning C4512: assignment operator could not be generated |
92f5a8d4 TL |
73 | BOOST_DELETED_FUNCTION(base_iterator_source& operator= (base_iterator_source const&)) |
74 | }; | |
75 | ||
76 | template <typename Iterator, typename Enable = void> | |
77 | struct iterator_source : base_iterator_source<Iterator> | |
78 | { | |
79 | typedef base_iterator_source<Iterator> base_type; | |
80 | ||
81 | iterator_source (Iterator const& first_, Iterator const& last_) | |
82 | : base_type(first_, last_) {} | |
83 | }; | |
84 | ||
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< | |
89 | Iterator, | |
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> | |
93 | { | |
94 | typedef base_iterator_source<Iterator> base_type; | |
95 | ||
96 | iterator_source (Iterator const& first_, Iterator const& last_) | |
97 | : base_type(first_, last_) {} | |
98 | ||
99 | typedef typename base_type::char_type char_type; | |
100 | using base_type::first; | |
101 | using base_type::last; | |
102 | using base_type::pos; | |
103 | ||
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 | |
106 | // end-of-sequence. | |
107 | std::streamsize read (char_type* s, std::streamsize n) | |
108 | { | |
109 | if (first == last) | |
110 | return -1; | |
111 | ||
112 | n = (std::min)(static_cast<std::streamsize>(last - first), n); | |
113 | ||
114 | typedef typename std::iterator_traits<Iterator>::difference_type diff_type; | |
115 | ||
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); | |
119 | pos += n; | |
120 | ||
121 | return n; | |
122 | } | |
7c673cae FG |
123 | }; |
124 | ||
125 | }}}} | |
126 | ||
127 | #endif |