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