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 ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP 12 #define ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP 13 14 15 #include "asio/detail/config.hpp" 16 #include "asio/buffer.hpp" 17 #include "asio/detail/array_fwd.hpp" 18 #include "asio/detail/socket_types.hpp" 19 20 #include "asio/detail/push_options.hpp" 21 22 namespace asio { 23 namespace detail { 24 25 class buffer_sequence_adapter_base 26 { 27 protected: 28 // The maximum number of buffers to support in a single operation. 29 enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; 30 31 typedef iovec native_buffer_type; 32 init_iov_base(void * & base,void * addr)33 static void init_iov_base(void*& base, void* addr) 34 { 35 base = addr; 36 } 37 38 template <typename T> init_iov_base(T & base,void * addr)39 static void init_iov_base(T& base, void* addr) 40 { 41 base = static_cast<T>(addr); 42 } 43 init_native_buffer(iovec & iov,const asio::mutable_buffer & buffer)44 static void init_native_buffer(iovec& iov, 45 const asio::mutable_buffer& buffer) 46 { 47 init_iov_base(iov.iov_base, asio::buffer_cast<void*>(buffer)); 48 iov.iov_len = asio::buffer_size(buffer); 49 } 50 init_native_buffer(iovec & iov,const asio::const_buffer & buffer)51 static void init_native_buffer(iovec& iov, 52 const asio::const_buffer& buffer) 53 { 54 init_iov_base(iov.iov_base, const_cast<void*>( 55 asio::buffer_cast<const void*>(buffer))); 56 iov.iov_len = asio::buffer_size(buffer); 57 } 58 }; 59 60 // Helper class to translate buffers into the native buffer representation. 61 template <typename Buffer, typename Buffers> 62 class buffer_sequence_adapter 63 : buffer_sequence_adapter_base 64 { 65 public: buffer_sequence_adapter(const Buffers & buffer_sequence)66 explicit buffer_sequence_adapter(const Buffers& buffer_sequence) 67 : count_(0), total_buffer_size_(0) 68 { 69 typename Buffers::const_iterator iter = buffer_sequence.begin(); 70 typename Buffers::const_iterator end = buffer_sequence.end(); 71 for (; iter != end && count_ < max_buffers; ++iter, ++count_) 72 { 73 Buffer buffer(*iter); 74 init_native_buffer(buffers_[count_], buffer); 75 total_buffer_size_ += asio::buffer_size(buffer); 76 } 77 } 78 buffers()79 native_buffer_type* buffers() 80 { 81 return buffers_; 82 } 83 count() const84 std::size_t count() const 85 { 86 return count_; 87 } 88 all_empty() const89 bool all_empty() const 90 { 91 return total_buffer_size_ == 0; 92 } 93 all_empty(const Buffers & buffer_sequence)94 static bool all_empty(const Buffers& buffer_sequence) 95 { 96 typename Buffers::const_iterator iter = buffer_sequence.begin(); 97 typename Buffers::const_iterator end = buffer_sequence.end(); 98 std::size_t i = 0; 99 for (; iter != end && i < max_buffers; ++iter, ++i) 100 if (asio::buffer_size(Buffer(*iter)) > 0) 101 return false; 102 return true; 103 } 104 validate(const Buffers & buffer_sequence)105 static void validate(const Buffers& buffer_sequence) 106 { 107 typename Buffers::const_iterator iter = buffer_sequence.begin(); 108 typename Buffers::const_iterator end = buffer_sequence.end(); 109 for (; iter != end; ++iter) 110 { 111 Buffer buffer(*iter); 112 asio::buffer_cast<const void*>(buffer); 113 } 114 } 115 first(const Buffers & buffer_sequence)116 static Buffer first(const Buffers& buffer_sequence) 117 { 118 typename Buffers::const_iterator iter = buffer_sequence.begin(); 119 typename Buffers::const_iterator end = buffer_sequence.end(); 120 for (; iter != end; ++iter) 121 { 122 Buffer buffer(*iter); 123 if (asio::buffer_size(buffer) != 0) 124 return buffer; 125 } 126 return Buffer(); 127 } 128 129 private: 130 native_buffer_type buffers_[max_buffers]; 131 std::size_t count_; 132 std::size_t total_buffer_size_; 133 }; 134 135 template <typename Buffer> 136 class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1> 137 : buffer_sequence_adapter_base 138 { 139 public: buffer_sequence_adapter(const asio::mutable_buffers_1 & buffer_sequence)140 explicit buffer_sequence_adapter( 141 const asio::mutable_buffers_1& buffer_sequence) 142 { 143 init_native_buffer(buffer_, Buffer(buffer_sequence)); 144 total_buffer_size_ = asio::buffer_size(buffer_sequence); 145 } 146 buffers()147 native_buffer_type* buffers() 148 { 149 return &buffer_; 150 } 151 count() const152 std::size_t count() const 153 { 154 return 1; 155 } 156 all_empty() const157 bool all_empty() const 158 { 159 return total_buffer_size_ == 0; 160 } 161 all_empty(const asio::mutable_buffers_1 & buffer_sequence)162 static bool all_empty(const asio::mutable_buffers_1& buffer_sequence) 163 { 164 return asio::buffer_size(buffer_sequence) == 0; 165 } 166 validate(const asio::mutable_buffers_1 & buffer_sequence)167 static void validate(const asio::mutable_buffers_1& buffer_sequence) 168 { 169 asio::buffer_cast<const void*>(buffer_sequence); 170 } 171 first(const asio::mutable_buffers_1 & buffer_sequence)172 static Buffer first(const asio::mutable_buffers_1& buffer_sequence) 173 { 174 return Buffer(buffer_sequence); 175 } 176 177 private: 178 native_buffer_type buffer_; 179 std::size_t total_buffer_size_; 180 }; 181 182 template <typename Buffer> 183 class buffer_sequence_adapter<Buffer, asio::const_buffers_1> 184 : buffer_sequence_adapter_base 185 { 186 public: buffer_sequence_adapter(const asio::const_buffers_1 & buffer_sequence)187 explicit buffer_sequence_adapter( 188 const asio::const_buffers_1& buffer_sequence) 189 { 190 init_native_buffer(buffer_, Buffer(buffer_sequence)); 191 total_buffer_size_ = asio::buffer_size(buffer_sequence); 192 } 193 buffers()194 native_buffer_type* buffers() 195 { 196 return &buffer_; 197 } 198 count() const199 std::size_t count() const 200 { 201 return 1; 202 } 203 all_empty() const204 bool all_empty() const 205 { 206 return total_buffer_size_ == 0; 207 } 208 all_empty(const asio::const_buffers_1 & buffer_sequence)209 static bool all_empty(const asio::const_buffers_1& buffer_sequence) 210 { 211 return asio::buffer_size(buffer_sequence) == 0; 212 } 213 validate(const asio::const_buffers_1 & buffer_sequence)214 static void validate(const asio::const_buffers_1& buffer_sequence) 215 { 216 asio::buffer_cast<const void*>(buffer_sequence); 217 } 218 first(const asio::const_buffers_1 & buffer_sequence)219 static Buffer first(const asio::const_buffers_1& buffer_sequence) 220 { 221 return Buffer(buffer_sequence); 222 } 223 224 private: 225 native_buffer_type buffer_; 226 std::size_t total_buffer_size_; 227 }; 228 229 template <typename Buffer, typename Elem> 230 class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > 231 : buffer_sequence_adapter_base 232 { 233 public: buffer_sequence_adapter(const boost::array<Elem,2> & buffer_sequence)234 explicit buffer_sequence_adapter( 235 const boost::array<Elem, 2>& buffer_sequence) 236 { 237 init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); 238 init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); 239 total_buffer_size_ = asio::buffer_size(buffer_sequence[0]) 240 + asio::buffer_size(buffer_sequence[1]); 241 } 242 buffers()243 native_buffer_type* buffers() 244 { 245 return buffers_; 246 } 247 count() const248 std::size_t count() const 249 { 250 return 2; 251 } 252 all_empty() const253 bool all_empty() const 254 { 255 return total_buffer_size_ == 0; 256 } 257 all_empty(const boost::array<Elem,2> & buffer_sequence)258 static bool all_empty(const boost::array<Elem, 2>& buffer_sequence) 259 { 260 return asio::buffer_size(buffer_sequence[0]) == 0 261 && asio::buffer_size(buffer_sequence[1]) == 0; 262 } 263 validate(const boost::array<Elem,2> & buffer_sequence)264 static void validate(const boost::array<Elem, 2>& buffer_sequence) 265 { 266 asio::buffer_cast<const void*>(buffer_sequence[0]); 267 asio::buffer_cast<const void*>(buffer_sequence[1]); 268 } 269 first(const boost::array<Elem,2> & buffer_sequence)270 static Buffer first(const boost::array<Elem, 2>& buffer_sequence) 271 { 272 return Buffer(asio::buffer_size(buffer_sequence[0]) != 0 273 ? buffer_sequence[0] : buffer_sequence[1]); 274 } 275 276 private: 277 native_buffer_type buffers_[2]; 278 std::size_t total_buffer_size_; 279 }; 280 281 282 template <typename Buffer, typename Elem> 283 class buffer_sequence_adapter<Buffer, std::array<Elem, 2> > 284 : buffer_sequence_adapter_base 285 { 286 public: buffer_sequence_adapter(const std::array<Elem,2> & buffer_sequence)287 explicit buffer_sequence_adapter( 288 const std::array<Elem, 2>& buffer_sequence) 289 { 290 init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); 291 init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); 292 total_buffer_size_ = asio::buffer_size(buffer_sequence[0]) 293 + asio::buffer_size(buffer_sequence[1]); 294 } 295 buffers()296 native_buffer_type* buffers() 297 { 298 return buffers_; 299 } 300 count() const301 std::size_t count() const 302 { 303 return 2; 304 } 305 all_empty() const306 bool all_empty() const 307 { 308 return total_buffer_size_ == 0; 309 } 310 all_empty(const std::array<Elem,2> & buffer_sequence)311 static bool all_empty(const std::array<Elem, 2>& buffer_sequence) 312 { 313 return asio::buffer_size(buffer_sequence[0]) == 0 314 && asio::buffer_size(buffer_sequence[1]) == 0; 315 } 316 validate(const std::array<Elem,2> & buffer_sequence)317 static void validate(const std::array<Elem, 2>& buffer_sequence) 318 { 319 asio::buffer_cast<const void*>(buffer_sequence[0]); 320 asio::buffer_cast<const void*>(buffer_sequence[1]); 321 } 322 first(const std::array<Elem,2> & buffer_sequence)323 static Buffer first(const std::array<Elem, 2>& buffer_sequence) 324 { 325 return Buffer(asio::buffer_size(buffer_sequence[0]) != 0 326 ? buffer_sequence[0] : buffer_sequence[1]); 327 } 328 329 private: 330 native_buffer_type buffers_[2]; 331 std::size_t total_buffer_size_; 332 }; 333 334 335 } // namespace detail 336 } // namespace asio 337 338 #include "asio/detail/pop_options.hpp" 339 340 # include "asio/detail/impl/buffer_sequence_adapter.ipp" 341 342 #endif // ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP 343