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
25namespace boost {
26namespace asio {
27namespace detail {
28
29class buffer_sequence_adapter_base
30{
31protected:
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.
99template <typename Buffer, typename Buffers>
100class buffer_sequence_adapter
101 : buffer_sequence_adapter_base
102{
103public:
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
167private:
168 native_buffer_type buffers_[max_buffers];
169 std::size_t count_;
170 std::size_t total_buffer_size_;
171};
172
173template <typename Buffer>
174class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
175 : buffer_sequence_adapter_base
176{
177public:
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
215private:
216 native_buffer_type buffer_;
217 std::size_t total_buffer_size_;
218};
219
220template <typename Buffer>
221class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1>
222 : buffer_sequence_adapter_base
223{
224public:
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
262private:
263 native_buffer_type buffer_;
264 std::size_t total_buffer_size_;
265};
266
267template <typename Buffer, typename Elem>
268class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
269 : buffer_sequence_adapter_base
270{
271public:
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
314private:
315 native_buffer_type buffers_[2];
316 std::size_t total_buffer_size_;
317};
318
319#if defined(BOOST_ASIO_HAS_STD_ARRAY)
320
321template <typename Buffer, typename Elem>
322class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
323 : buffer_sequence_adapter_base
324{
325public:
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
368private:
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

source code of boost/boost/asio/detail/buffer_sequence_adapter.hpp