2 // detail/buffer_sequence_adapter.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
12 #define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
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>
23 #include <boost/asio/detail/push_options.hpp>
29 class buffer_sequence_adapter_base
32 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
33 // The maximum number of buffers to support in a single operation.
34 enum { max_buffers = 1 };
36 typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;
38 BOOST_ASIO_DECL static void init_native_buffer(
39 native_buffer_type& buf,
40 const boost::asio::mutable_buffer& buffer);
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 };
49 typedef WSABUF native_buffer_type;
51 static void init_native_buffer(WSABUF& buf,
52 const boost::asio::mutable_buffer& buffer)
54 buf.buf = boost::asio::buffer_cast<char*>(buffer);
55 buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer));
58 static void init_native_buffer(WSABUF& buf,
59 const boost::asio::const_buffer& buffer)
61 buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer));
62 buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer));
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 };
68 typedef iovec native_buffer_type;
70 static void init_iov_base(void*& base, void* addr)
76 static void init_iov_base(T& base, void* addr)
78 base = static_cast<T>(addr);
81 static void init_native_buffer(iovec& iov,
82 const boost::asio::mutable_buffer& buffer)
84 init_iov_base(iov.iov_base, boost::asio::buffer_cast<void*>(buffer));
85 iov.iov_len = boost::asio::buffer_size(buffer);
88 static void init_native_buffer(iovec& iov,
89 const boost::asio::const_buffer& buffer)
91 init_iov_base(iov.iov_base, const_cast<void*>(
92 boost::asio::buffer_cast<const void*>(buffer)));
93 iov.iov_len = boost::asio::buffer_size(buffer);
95 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
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
104 explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
105 : count_(0), total_buffer_size_(0)
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_)
111 Buffer buffer(*iter);
112 init_native_buffer(buffers_[count_], buffer);
113 total_buffer_size_ += boost::asio::buffer_size(buffer);
117 native_buffer_type* buffers()
122 std::size_t count() const
127 bool all_empty() const
129 return total_buffer_size_ == 0;
132 static bool all_empty(const Buffers& buffer_sequence)
134 typename Buffers::const_iterator iter = buffer_sequence.begin();
135 typename Buffers::const_iterator end = buffer_sequence.end();
137 for (; iter != end && i < max_buffers; ++iter, ++i)
138 if (boost::asio::buffer_size(Buffer(*iter)) > 0)
143 static void validate(const Buffers& buffer_sequence)
145 typename Buffers::const_iterator iter = buffer_sequence.begin();
146 typename Buffers::const_iterator end = buffer_sequence.end();
147 for (; iter != end; ++iter)
149 Buffer buffer(*iter);
150 boost::asio::buffer_cast<const void*>(buffer);
154 static Buffer first(const Buffers& buffer_sequence)
156 typename Buffers::const_iterator iter = buffer_sequence.begin();
157 typename Buffers::const_iterator end = buffer_sequence.end();
158 for (; iter != end; ++iter)
160 Buffer buffer(*iter);
161 if (boost::asio::buffer_size(buffer) != 0)
168 native_buffer_type buffers_[max_buffers];
170 std::size_t total_buffer_size_;
173 template <typename Buffer>
174 class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
175 : buffer_sequence_adapter_base
178 explicit buffer_sequence_adapter(
179 const boost::asio::mutable_buffers_1& buffer_sequence)
181 init_native_buffer(buffer_, Buffer(buffer_sequence));
182 total_buffer_size_ = boost::asio::buffer_size(buffer_sequence);
185 native_buffer_type* buffers()
190 std::size_t count() const
195 bool all_empty() const
197 return total_buffer_size_ == 0;
200 static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence)
202 return boost::asio::buffer_size(buffer_sequence) == 0;
205 static void validate(const boost::asio::mutable_buffers_1& buffer_sequence)
207 boost::asio::buffer_cast<const void*>(buffer_sequence);
210 static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence)
212 return Buffer(buffer_sequence);
216 native_buffer_type buffer_;
217 std::size_t total_buffer_size_;
220 template <typename Buffer>
221 class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1>
222 : buffer_sequence_adapter_base
225 explicit buffer_sequence_adapter(
226 const boost::asio::const_buffers_1& buffer_sequence)
228 init_native_buffer(buffer_, Buffer(buffer_sequence));
229 total_buffer_size_ = boost::asio::buffer_size(buffer_sequence);
232 native_buffer_type* buffers()
237 std::size_t count() const
242 bool all_empty() const
244 return total_buffer_size_ == 0;
247 static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence)
249 return boost::asio::buffer_size(buffer_sequence) == 0;
252 static void validate(const boost::asio::const_buffers_1& buffer_sequence)
254 boost::asio::buffer_cast<const void*>(buffer_sequence);
257 static Buffer first(const boost::asio::const_buffers_1& buffer_sequence)
259 return Buffer(buffer_sequence);
263 native_buffer_type buffer_;
264 std::size_t total_buffer_size_;
267 template <typename Buffer, typename Elem>
268 class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
269 : buffer_sequence_adapter_base
272 explicit buffer_sequence_adapter(
273 const boost::array<Elem, 2>& buffer_sequence)
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]);
281 native_buffer_type* buffers()
286 std::size_t count() const
291 bool all_empty() const
293 return total_buffer_size_ == 0;
296 static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)
298 return boost::asio::buffer_size(buffer_sequence[0]) == 0
299 && boost::asio::buffer_size(buffer_sequence[1]) == 0;
302 static void validate(const boost::array<Elem, 2>& buffer_sequence)
304 boost::asio::buffer_cast<const void*>(buffer_sequence[0]);
305 boost::asio::buffer_cast<const void*>(buffer_sequence[1]);
308 static Buffer first(const boost::array<Elem, 2>& buffer_sequence)
310 return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0
311 ? buffer_sequence[0] : buffer_sequence[1]);
315 native_buffer_type buffers_[2];
316 std::size_t total_buffer_size_;
319 #if defined(BOOST_ASIO_HAS_STD_ARRAY)
321 template <typename Buffer, typename Elem>
322 class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >
323 : buffer_sequence_adapter_base
326 explicit buffer_sequence_adapter(
327 const std::array<Elem, 2>& buffer_sequence)
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]);
335 native_buffer_type* buffers()
340 std::size_t count() const
345 bool all_empty() const
347 return total_buffer_size_ == 0;
350 static bool all_empty(const std::array<Elem, 2>& buffer_sequence)
352 return boost::asio::buffer_size(buffer_sequence[0]) == 0
353 && boost::asio::buffer_size(buffer_sequence[1]) == 0;
356 static void validate(const std::array<Elem, 2>& buffer_sequence)
358 boost::asio::buffer_cast<const void*>(buffer_sequence[0]);
359 boost::asio::buffer_cast<const void*>(buffer_sequence[1]);
362 static Buffer first(const std::array<Elem, 2>& buffer_sequence)
364 return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0
365 ? buffer_sequence[0] : buffer_sequence[1]);
369 native_buffer_type buffers_[2];
370 std::size_t total_buffer_size_;
373 #endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
375 } // namespace detail
379 #include <boost/asio/detail/pop_options.hpp>
381 #if defined(BOOST_ASIO_HEADER_ONLY)
382 # include <boost/asio/detail/impl/buffer_sequence_adapter.ipp>
383 #endif // defined(BOOST_ASIO_HEADER_ONLY)
385 #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP