Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/iostreams/detail/adapter/range_adapter.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) | |
2 // (C) Copyright 2003-2007 Jonathan Turkanis | |
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) | |
5 | |
6 // See http://www.boost.org/libs/iostreams for documentation. | |
7 | |
8 #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED | |
9 #define BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED | |
10 | |
11 #if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
12 # pragma once | |
13 #endif | |
14 | |
15 #include <algorithm> // min. | |
16 #include <boost/assert.hpp> | |
17 #include <cstddef> // ptrdiff_t. | |
18 #include <iosfwd> // streamsize, streamoff. | |
19 #include <boost/detail/iterator.hpp> // boost::iterator_traits. | |
20 #include <boost/iostreams/categories.hpp> | |
21 #include <boost/iostreams/detail/error.hpp> | |
22 #include <boost/iostreams/positioning.hpp> | |
23 #include <boost/mpl/if.hpp> | |
24 #include <boost/throw_exception.hpp> | |
25 #include <boost/type_traits/is_convertible.hpp> | |
26 #include <boost/utility/enable_if.hpp> | |
27 | |
28 // Must come last. | |
29 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC. | |
30 | |
31 namespace boost { namespace iostreams { namespace detail { | |
32 | |
33 // Used for simulated tag dispatch. | |
34 template<typename Traversal> struct range_adapter_impl; | |
35 | |
36 // | |
37 // Template name: range_adapter | |
38 // Description: Device based on an instance of boost::iterator_range. | |
39 // Template parameters: | |
40 // Mode - A mode tag. | |
41 // Range - An instance of iterator_range. | |
42 // | |
43 template<typename Mode, typename Range> | |
44 class range_adapter { | |
45 private: | |
46 typedef typename Range::iterator iterator; | |
47 typedef boost::detail::iterator_traits<iterator> iter_traits; | |
48 typedef typename iter_traits::iterator_category iter_cat; | |
49 public: | |
50 typedef typename Range::value_type char_type; | |
51 struct category : Mode, device_tag { }; | |
52 typedef typename | |
53 mpl::if_< | |
54 is_convertible< | |
55 iter_cat, | |
56 std::random_access_iterator_tag | |
57 >, | |
58 std::random_access_iterator_tag, | |
59 std::forward_iterator_tag | |
60 >::type tag; | |
61 typedef range_adapter_impl<tag> impl; | |
62 | |
63 explicit range_adapter(const Range& rng); | |
64 range_adapter(iterator first, iterator last); | |
65 std::streamsize read(char_type* s, std::streamsize n); | |
66 std::streamsize write(const char_type* s, std::streamsize n); | |
67 std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); | |
68 private: | |
69 iterator first_, cur_, last_; | |
70 }; | |
71 | |
72 //------------------Implementation of range_adapter---------------------------// | |
73 | |
74 template<typename Mode, typename Range> | |
75 range_adapter<Mode, Range>::range_adapter(const Range& rng) | |
76 : first_(rng.begin()), cur_(rng.begin()), last_(rng.end()) { } | |
77 | |
78 template<typename Mode, typename Range> | |
79 range_adapter<Mode, Range>::range_adapter(iterator first, iterator last) | |
80 : first_(first), cur_(first), last_(last) { } | |
81 | |
82 template<typename Mode, typename Range> | |
83 inline std::streamsize range_adapter<Mode, Range>::read | |
84 (char_type* s, std::streamsize n) | |
85 { return impl::read(cur_, last_, s, n); } | |
86 | |
87 template<typename Mode, typename Range> | |
88 inline std::streamsize range_adapter<Mode, Range>::write | |
89 (const char_type* s, std::streamsize n) | |
90 { return impl::write(cur_, last_, s, n); } | |
91 | |
92 | |
93 template<typename Mode, typename Range> | |
94 std::streampos range_adapter<Mode, Range>::seek | |
95 (stream_offset off, BOOST_IOS::seekdir way) | |
96 { | |
97 impl::seek(first_, cur_, last_, off, way); | |
98 return offset_to_position(cur_ - first_); | |
99 } | |
100 | |
101 //------------------Implementation of range_adapter_impl----------------------// | |
102 | |
103 template<> | |
104 struct range_adapter_impl<std::forward_iterator_tag> { | |
105 template<typename Iter, typename Ch> | |
106 static std::streamsize read | |
107 (Iter& cur, Iter& last, Ch* s,std::streamsize n) | |
108 { | |
109 std::streamsize rem = n; // No. of chars remaining. | |
110 while (cur != last && rem-- > 0) *s++ = *cur++; | |
111 return n - rem != 0 ? n - rem : -1; | |
112 } | |
113 | |
114 template<typename Iter, typename Ch> | |
115 static std::streamsize write | |
116 (Iter& cur, Iter& last, const Ch* s, std::streamsize n) | |
117 { | |
118 while (cur != last && n-- > 0) *cur++ = *s++; | |
119 if (cur == last && n > 0) | |
120 boost::throw_exception(write_area_exhausted()); | |
121 return n; | |
122 } | |
123 }; | |
124 | |
125 template<> | |
126 struct range_adapter_impl<std::random_access_iterator_tag> { | |
127 template<typename Iter, typename Ch> | |
128 static std::streamsize read | |
129 (Iter& cur, Iter& last, Ch* s,std::streamsize n) | |
130 { | |
131 std::streamsize result = | |
132 (std::min)(static_cast<std::streamsize>(last - cur), n); | |
133 if (result) | |
134 std::copy(cur, cur + result, s); | |
135 cur += result; | |
136 return result != 0 ? result : -1; | |
137 } | |
138 | |
139 template<typename Iter, typename Ch> | |
140 static std::streamsize write | |
141 (Iter& cur, Iter& last, const Ch* s, std::streamsize n) | |
142 { | |
143 std::streamsize count = | |
144 (std::min)(static_cast<std::streamsize>(last - cur), n); | |
145 std::copy(s, s + count, cur); | |
146 cur += count; | |
147 if (count < n) | |
148 boost::throw_exception(write_area_exhausted()); | |
149 return n; | |
150 } | |
151 | |
152 template<typename Iter> | |
153 static void seek | |
154 ( Iter& first, Iter& cur, Iter& last, stream_offset off, | |
155 BOOST_IOS::seekdir way ) | |
156 { | |
157 using namespace std; | |
158 switch (way) { | |
159 case BOOST_IOS::beg: | |
160 if (off > last - first || off < 0) | |
161 boost::throw_exception(bad_seek()); | |
162 cur = first + off; | |
163 break; | |
164 case BOOST_IOS::cur: | |
165 { | |
166 std::ptrdiff_t newoff = cur - first + off; | |
167 if (newoff > last - first || newoff < 0) | |
168 boost::throw_exception(bad_seek()); | |
169 cur += off; | |
170 break; | |
171 } | |
172 case BOOST_IOS::end: | |
173 if (last - first + off < 0 || off > 0) | |
174 boost::throw_exception(bad_seek()); | |
175 cur = last + off; | |
176 break; | |
177 default: | |
178 BOOST_ASSERT(0); | |
179 } | |
180 } | |
181 }; | |
182 | |
183 } } } // End namespaces detail, iostreams, boost. | |
184 | |
185 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC. | |
186 | |
187 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED //---------------// |