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(iov.iov_base, boost::asio::buffer_cast<void*>(buffer)); 85 iov.iov_len = boost::asio::buffer_size(buffer); 86 } 87 88 static void init_native_buffer(iovec& iov, 89 const boost::asio::const_buffer& buffer) 90 { 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); 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: buffer_sequence_adapter(const Buffers & buffer_sequence)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 buffers()117 native_buffer_type* buffers() 118 { 119 return buffers_; 120 } 121 count() const122 std::size_t count() const 123 { 124 return count_; 125 } 126 all_empty() const127 bool all_empty() const 128 { 129 return total_buffer_size_ == 0; 130 } 131 all_empty(const Buffers & buffer_sequence)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 validate(const Buffers & buffer_sequence)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 first(const Buffers & buffer_sequence)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: buffer_sequence_adapter(const boost::asio::mutable_buffers_1 & buffer_sequence)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(buffer_sequence); 183 } 184 buffers()185 native_buffer_type* buffers() 186 { 187 return &buffer_; 188 } 189 count() const190 std::size_t count() const 191 { 192 return 1; 193 } 194 all_empty() const195 bool all_empty() const 196 { 197 return total_buffer_size_ == 0; 198 } 199 all_empty(const boost::asio::mutable_buffers_1 & buffer_sequence)200 static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence) 201 { 202 return boost::asio::buffer_size(buffer_sequence) == 0; 203 } 204 validate(const boost::asio::mutable_buffers_1 & buffer_sequence)205 static void validate(const boost::asio::mutable_buffers_1& buffer_sequence) 206 { 207 boost::asio::buffer_cast<const void*>(buffer_sequence); 208 } 209 first(const boost::asio::mutable_buffers_1 & buffer_sequence)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: buffer_sequence_adapter(const boost::asio::const_buffers_1 & buffer_sequence)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(buffer_sequence); 230 } 231 buffers()232 native_buffer_type* buffers() 233 { 234 return &buffer_; 235 } 236 count() const237 std::size_t count() const 238 { 239 return 1; 240 } 241 all_empty() const242 bool all_empty() const 243 { 244 return total_buffer_size_ == 0; 245 } 246 all_empty(const boost::asio::const_buffers_1 & buffer_sequence)247 static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence) 248 { 249 return boost::asio::buffer_size(buffer_sequence) == 0; 250 } 251 validate(const boost::asio::const_buffers_1 & buffer_sequence)252 static void validate(const boost::asio::const_buffers_1& buffer_sequence) 253 { 254 boost::asio::buffer_cast<const void*>(buffer_sequence); 255 } 256 first(const boost::asio::const_buffers_1 & buffer_sequence)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: buffer_sequence_adapter(const boost::array<Elem,2> & buffer_sequence)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 buffers()281 native_buffer_type* buffers() 282 { 283 return buffers_; 284 } 285 count() const286 std::size_t count() const 287 { 288 return 2; 289 } 290 all_empty() const291 bool all_empty() const 292 { 293 return total_buffer_size_ == 0; 294 } 295 all_empty(const boost::array<Elem,2> & buffer_sequence)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 validate(const boost::array<Elem,2> & buffer_sequence)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 first(const boost::array<Elem,2> & buffer_sequence)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: buffer_sequence_adapter(const std::array<Elem,2> & buffer_sequence)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 buffers()335 native_buffer_type* buffers() 336 { 337 return buffers_; 338 } 339 count() const340 std::size_t count() const 341 { 342 return 2; 343 } 344 all_empty() const345 bool all_empty() const 346 { 347 return total_buffer_size_ == 0; 348 } 349 all_empty(const std::array<Elem,2> & buffer_sequence)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 validate(const std::array<Elem,2> & buffer_sequence)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 first(const std::array<Elem,2> & buffer_sequence)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