1 | // |
2 | // detail/buffer_sequence_adapter.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
9 | // |
10 | |
11 | #ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP |
12 | #define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <boost/asio/buffer.hpp> |
20 | #include <boost/asio/detail/array_fwd.hpp> |
21 | #include <boost/asio/detail/socket_types.hpp> |
22 | |
23 | #include <boost/asio/detail/push_options.hpp> |
24 | |
25 | namespace boost { |
26 | namespace asio { |
27 | namespace detail { |
28 | |
29 | class buffer_sequence_adapter_base |
30 | { |
31 | protected: |
32 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
33 | // The maximum number of buffers to support in a single operation. |
34 | enum { max_buffers = 1 }; |
35 | |
36 | typedef Windows::Storage::Streams::IBuffer^ native_buffer_type; |
37 | |
38 | BOOST_ASIO_DECL static void init_native_buffer( |
39 | native_buffer_type& buf, |
40 | const boost::asio::mutable_buffer& buffer); |
41 | |
42 | BOOST_ASIO_DECL static void init_native_buffer( |
43 | native_buffer_type& buf, |
44 | const boost::asio::const_buffer& buffer); |
45 | #elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) |
46 | // The maximum number of buffers to support in a single operation. |
47 | enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; |
48 | |
49 | typedef WSABUF native_buffer_type; |
50 | |
51 | static void init_native_buffer(WSABUF& buf, |
52 | const boost::asio::mutable_buffer& buffer) |
53 | { |
54 | buf.buf = boost::asio::buffer_cast<char*>(buffer); |
55 | buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer)); |
56 | } |
57 | |
58 | static void init_native_buffer(WSABUF& buf, |
59 | const boost::asio::const_buffer& buffer) |
60 | { |
61 | buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer)); |
62 | buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer)); |
63 | } |
64 | #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) |
65 | // The maximum number of buffers to support in a single operation. |
66 | enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; |
67 | |
68 | typedef iovec native_buffer_type; |
69 | |
70 | static void init_iov_base(void*& base, void* addr) |
71 | { |
72 | base = addr; |
73 | } |
74 | |
75 | template <typename T> |
76 | static void init_iov_base(T& base, void* addr) |
77 | { |
78 | base = static_cast<T>(addr); |
79 | } |
80 | |
81 | static void init_native_buffer(iovec& iov, |
82 | const boost::asio::mutable_buffer& buffer) |
83 | { |
84 | init_iov_base(base&: iov.iov_base, addr: boost::asio::buffer_cast<void*>(b: buffer)); |
85 | iov.iov_len = boost::asio::buffer_size(b: buffer); |
86 | } |
87 | |
88 | static void init_native_buffer(iovec& iov, |
89 | const boost::asio::const_buffer& buffer) |
90 | { |
91 | init_iov_base(base&: iov.iov_base, addr: const_cast<void*>( |
92 | boost::asio::buffer_cast<const void*>(b: buffer))); |
93 | iov.iov_len = boost::asio::buffer_size(b: buffer); |
94 | } |
95 | #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) |
96 | }; |
97 | |
98 | // Helper class to translate buffers into the native buffer representation. |
99 | template <typename Buffer, typename Buffers> |
100 | class buffer_sequence_adapter |
101 | : buffer_sequence_adapter_base |
102 | { |
103 | public: |
104 | explicit buffer_sequence_adapter(const Buffers& buffer_sequence) |
105 | : count_(0), total_buffer_size_(0) |
106 | { |
107 | typename Buffers::const_iterator iter = buffer_sequence.begin(); |
108 | typename Buffers::const_iterator end = buffer_sequence.end(); |
109 | for (; iter != end && count_ < max_buffers; ++iter, ++count_) |
110 | { |
111 | Buffer buffer(*iter); |
112 | init_native_buffer(buffers_[count_], buffer); |
113 | total_buffer_size_ += boost::asio::buffer_size(buffer); |
114 | } |
115 | } |
116 | |
117 | native_buffer_type* buffers() |
118 | { |
119 | return buffers_; |
120 | } |
121 | |
122 | std::size_t count() const |
123 | { |
124 | return count_; |
125 | } |
126 | |
127 | bool all_empty() const |
128 | { |
129 | return total_buffer_size_ == 0; |
130 | } |
131 | |
132 | static bool all_empty(const Buffers& buffer_sequence) |
133 | { |
134 | typename Buffers::const_iterator iter = buffer_sequence.begin(); |
135 | typename Buffers::const_iterator end = buffer_sequence.end(); |
136 | std::size_t i = 0; |
137 | for (; iter != end && i < max_buffers; ++iter, ++i) |
138 | if (boost::asio::buffer_size(Buffer(*iter)) > 0) |
139 | return false; |
140 | return true; |
141 | } |
142 | |
143 | static void validate(const Buffers& buffer_sequence) |
144 | { |
145 | typename Buffers::const_iterator iter = buffer_sequence.begin(); |
146 | typename Buffers::const_iterator end = buffer_sequence.end(); |
147 | for (; iter != end; ++iter) |
148 | { |
149 | Buffer buffer(*iter); |
150 | boost::asio::buffer_cast<const void*>(buffer); |
151 | } |
152 | } |
153 | |
154 | static Buffer first(const Buffers& buffer_sequence) |
155 | { |
156 | typename Buffers::const_iterator iter = buffer_sequence.begin(); |
157 | typename Buffers::const_iterator end = buffer_sequence.end(); |
158 | for (; iter != end; ++iter) |
159 | { |
160 | Buffer buffer(*iter); |
161 | if (boost::asio::buffer_size(buffer) != 0) |
162 | return buffer; |
163 | } |
164 | return Buffer(); |
165 | } |
166 | |
167 | private: |
168 | native_buffer_type buffers_[max_buffers]; |
169 | std::size_t count_; |
170 | std::size_t total_buffer_size_; |
171 | }; |
172 | |
173 | template <typename Buffer> |
174 | class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1> |
175 | : buffer_sequence_adapter_base |
176 | { |
177 | public: |
178 | explicit buffer_sequence_adapter( |
179 | const boost::asio::mutable_buffers_1& buffer_sequence) |
180 | { |
181 | init_native_buffer(buffer_, Buffer(buffer_sequence)); |
182 | total_buffer_size_ = boost::asio::buffer_size(b: buffer_sequence); |
183 | } |
184 | |
185 | native_buffer_type* buffers() |
186 | { |
187 | return &buffer_; |
188 | } |
189 | |
190 | std::size_t count() const |
191 | { |
192 | return 1; |
193 | } |
194 | |
195 | bool all_empty() const |
196 | { |
197 | return total_buffer_size_ == 0; |
198 | } |
199 | |
200 | static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence) |
201 | { |
202 | return boost::asio::buffer_size(b: buffer_sequence) == 0; |
203 | } |
204 | |
205 | static void validate(const boost::asio::mutable_buffers_1& buffer_sequence) |
206 | { |
207 | boost::asio::buffer_cast<const void*>(b: buffer_sequence); |
208 | } |
209 | |
210 | static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence) |
211 | { |
212 | return Buffer(buffer_sequence); |
213 | } |
214 | |
215 | private: |
216 | native_buffer_type buffer_; |
217 | std::size_t total_buffer_size_; |
218 | }; |
219 | |
220 | template <typename Buffer> |
221 | class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1> |
222 | : buffer_sequence_adapter_base |
223 | { |
224 | public: |
225 | explicit buffer_sequence_adapter( |
226 | const boost::asio::const_buffers_1& buffer_sequence) |
227 | { |
228 | init_native_buffer(buffer_, Buffer(buffer_sequence)); |
229 | total_buffer_size_ = boost::asio::buffer_size(b: buffer_sequence); |
230 | } |
231 | |
232 | native_buffer_type* buffers() |
233 | { |
234 | return &buffer_; |
235 | } |
236 | |
237 | std::size_t count() const |
238 | { |
239 | return 1; |
240 | } |
241 | |
242 | bool all_empty() const |
243 | { |
244 | return total_buffer_size_ == 0; |
245 | } |
246 | |
247 | static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence) |
248 | { |
249 | return boost::asio::buffer_size(b: buffer_sequence) == 0; |
250 | } |
251 | |
252 | static void validate(const boost::asio::const_buffers_1& buffer_sequence) |
253 | { |
254 | boost::asio::buffer_cast<const void*>(b: buffer_sequence); |
255 | } |
256 | |
257 | static Buffer first(const boost::asio::const_buffers_1& buffer_sequence) |
258 | { |
259 | return Buffer(buffer_sequence); |
260 | } |
261 | |
262 | private: |
263 | native_buffer_type buffer_; |
264 | std::size_t total_buffer_size_; |
265 | }; |
266 | |
267 | template <typename Buffer, typename Elem> |
268 | class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > |
269 | : buffer_sequence_adapter_base |
270 | { |
271 | public: |
272 | explicit buffer_sequence_adapter( |
273 | const boost::array<Elem, 2>& buffer_sequence) |
274 | { |
275 | init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); |
276 | init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); |
277 | total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) |
278 | + boost::asio::buffer_size(buffer_sequence[1]); |
279 | } |
280 | |
281 | native_buffer_type* buffers() |
282 | { |
283 | return buffers_; |
284 | } |
285 | |
286 | std::size_t count() const |
287 | { |
288 | return 2; |
289 | } |
290 | |
291 | bool all_empty() const |
292 | { |
293 | return total_buffer_size_ == 0; |
294 | } |
295 | |
296 | static bool all_empty(const boost::array<Elem, 2>& buffer_sequence) |
297 | { |
298 | return boost::asio::buffer_size(buffer_sequence[0]) == 0 |
299 | && boost::asio::buffer_size(buffer_sequence[1]) == 0; |
300 | } |
301 | |
302 | static void validate(const boost::array<Elem, 2>& buffer_sequence) |
303 | { |
304 | boost::asio::buffer_cast<const void*>(buffer_sequence[0]); |
305 | boost::asio::buffer_cast<const void*>(buffer_sequence[1]); |
306 | } |
307 | |
308 | static Buffer first(const boost::array<Elem, 2>& buffer_sequence) |
309 | { |
310 | return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 |
311 | ? buffer_sequence[0] : buffer_sequence[1]); |
312 | } |
313 | |
314 | private: |
315 | native_buffer_type buffers_[2]; |
316 | std::size_t total_buffer_size_; |
317 | }; |
318 | |
319 | #if defined(BOOST_ASIO_HAS_STD_ARRAY) |
320 | |
321 | template <typename Buffer, typename Elem> |
322 | class buffer_sequence_adapter<Buffer, std::array<Elem, 2> > |
323 | : buffer_sequence_adapter_base |
324 | { |
325 | public: |
326 | explicit buffer_sequence_adapter( |
327 | const std::array<Elem, 2>& buffer_sequence) |
328 | { |
329 | init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); |
330 | init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); |
331 | total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) |
332 | + boost::asio::buffer_size(buffer_sequence[1]); |
333 | } |
334 | |
335 | native_buffer_type* buffers() |
336 | { |
337 | return buffers_; |
338 | } |
339 | |
340 | std::size_t count() const |
341 | { |
342 | return 2; |
343 | } |
344 | |
345 | bool all_empty() const |
346 | { |
347 | return total_buffer_size_ == 0; |
348 | } |
349 | |
350 | static bool all_empty(const std::array<Elem, 2>& buffer_sequence) |
351 | { |
352 | return boost::asio::buffer_size(buffer_sequence[0]) == 0 |
353 | && boost::asio::buffer_size(buffer_sequence[1]) == 0; |
354 | } |
355 | |
356 | static void validate(const std::array<Elem, 2>& buffer_sequence) |
357 | { |
358 | boost::asio::buffer_cast<const void*>(buffer_sequence[0]); |
359 | boost::asio::buffer_cast<const void*>(buffer_sequence[1]); |
360 | } |
361 | |
362 | static Buffer first(const std::array<Elem, 2>& buffer_sequence) |
363 | { |
364 | return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 |
365 | ? buffer_sequence[0] : buffer_sequence[1]); |
366 | } |
367 | |
368 | private: |
369 | native_buffer_type buffers_[2]; |
370 | std::size_t total_buffer_size_; |
371 | }; |
372 | |
373 | #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) |
374 | |
375 | } // namespace detail |
376 | } // namespace asio |
377 | } // namespace boost |
378 | |
379 | #include <boost/asio/detail/pop_options.hpp> |
380 | |
381 | #if defined(BOOST_ASIO_HEADER_ONLY) |
382 | # include <boost/asio/detail/impl/buffer_sequence_adapter.ipp> |
383 | #endif // defined(BOOST_ASIO_HEADER_ONLY) |
384 | |
385 | #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP |
386 | |