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