// // detail/buffer_sequence_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP #define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include namespace boost { namespace asio { namespace detail { class buffer_sequence_adapter_base { protected: #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) typedef WSABUF native_buffer_type; static void init_native_buffer(WSABUF& buf, const boost::asio::mutable_buffer& buffer) { buf.buf = boost::asio::buffer_cast(buffer); buf.len = static_cast(boost::asio::buffer_size(buffer)); } static void init_native_buffer(WSABUF& buf, const boost::asio::const_buffer& buffer) { buf.buf = const_cast(boost::asio::buffer_cast(buffer)); buf.len = static_cast(boost::asio::buffer_size(buffer)); } #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) typedef iovec native_buffer_type; static void init_iov_base(void*& base, void* addr) { base = addr; } template static void init_iov_base(T& base, void* addr) { base = static_cast(addr); } static void init_native_buffer(iovec& iov, const boost::asio::mutable_buffer& buffer) { init_iov_base(iov.iov_base, boost::asio::buffer_cast(buffer)); iov.iov_len = boost::asio::buffer_size(buffer); } static void init_native_buffer(iovec& iov, const boost::asio::const_buffer& buffer) { init_iov_base(iov.iov_base, const_cast( boost::asio::buffer_cast(buffer))); iov.iov_len = boost::asio::buffer_size(buffer); } #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) }; // Helper class to translate buffers into the native buffer representation. template class buffer_sequence_adapter : buffer_sequence_adapter_base { public: explicit buffer_sequence_adapter(const Buffers& buffer_sequence) : count_(0), total_buffer_size_(0) { typename Buffers::const_iterator iter = buffer_sequence.begin(); typename Buffers::const_iterator end = buffer_sequence.end(); for (; iter != end && count_ < max_buffers; ++iter, ++count_) { Buffer buffer(*iter); init_native_buffer(buffers_[count_], buffer); total_buffer_size_ += boost::asio::buffer_size(buffer); } } native_buffer_type* buffers() { return buffers_; } std::size_t count() const { return count_; } bool all_empty() const { return total_buffer_size_ == 0; } static bool all_empty(const Buffers& buffer_sequence) { typename Buffers::const_iterator iter = buffer_sequence.begin(); typename Buffers::const_iterator end = buffer_sequence.end(); std::size_t i = 0; for (; iter != end && i < max_buffers; ++iter, ++i) if (boost::asio::buffer_size(Buffer(*iter)) > 0) return false; return true; } static void validate(const Buffers& buffer_sequence) { typename Buffers::const_iterator iter = buffer_sequence.begin(); typename Buffers::const_iterator end = buffer_sequence.end(); for (; iter != end; ++iter) { Buffer buffer(*iter); boost::asio::buffer_cast(buffer); } } static Buffer first(const Buffers& buffer_sequence) { typename Buffers::const_iterator iter = buffer_sequence.begin(); typename Buffers::const_iterator end = buffer_sequence.end(); for (; iter != end; ++iter) { Buffer buffer(*iter); if (boost::asio::buffer_size(buffer) != 0) return buffer; } return Buffer(); } private: // The maximum number of buffers to support in a single operation. enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; native_buffer_type buffers_[max_buffers]; std::size_t count_; std::size_t total_buffer_size_; }; template class buffer_sequence_adapter : buffer_sequence_adapter_base { public: explicit buffer_sequence_adapter( const boost::asio::mutable_buffers_1& buffer_sequence) { init_native_buffer(buffer_, Buffer(buffer_sequence)); total_buffer_size_ = boost::asio::buffer_size(buffer_sequence); } native_buffer_type* buffers() { return &buffer_; } std::size_t count() const { return 1; } bool all_empty() const { return total_buffer_size_ == 0; } static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence) { return boost::asio::buffer_size(buffer_sequence) == 0; } static void validate(const boost::asio::mutable_buffers_1& buffer_sequence) { boost::asio::buffer_cast(buffer_sequence); } static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence) { return Buffer(buffer_sequence); } private: native_buffer_type buffer_; std::size_t total_buffer_size_; }; template class buffer_sequence_adapter : buffer_sequence_adapter_base { public: explicit buffer_sequence_adapter( const boost::asio::const_buffers_1& buffer_sequence) { init_native_buffer(buffer_, Buffer(buffer_sequence)); total_buffer_size_ = boost::asio::buffer_size(buffer_sequence); } native_buffer_type* buffers() { return &buffer_; } std::size_t count() const { return 1; } bool all_empty() const { return total_buffer_size_ == 0; } static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence) { return boost::asio::buffer_size(buffer_sequence) == 0; } static void validate(const boost::asio::const_buffers_1& buffer_sequence) { boost::asio::buffer_cast(buffer_sequence); } static Buffer first(const boost::asio::const_buffers_1& buffer_sequence) { return Buffer(buffer_sequence); } private: native_buffer_type buffer_; std::size_t total_buffer_size_; }; template class buffer_sequence_adapter > : buffer_sequence_adapter_base { public: explicit buffer_sequence_adapter( const boost::array& buffer_sequence) { init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) + boost::asio::buffer_size(buffer_sequence[1]); } native_buffer_type* buffers() { return buffers_; } std::size_t count() const { return 2; } bool all_empty() const { return total_buffer_size_ == 0; } static bool all_empty(const boost::array& buffer_sequence) { return boost::asio::buffer_size(buffer_sequence[0]) == 0 && boost::asio::buffer_size(buffer_sequence[1]) == 0; } static void validate(const boost::array& buffer_sequence) { boost::asio::buffer_cast(buffer_sequence[0]); boost::asio::buffer_cast(buffer_sequence[1]); } static Buffer first(const boost::array& buffer_sequence) { return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 ? buffer_sequence[0] : buffer_sequence[1]); } private: native_buffer_type buffers_[2]; std::size_t total_buffer_size_; }; #if defined(BOOST_ASIO_HAS_STD_ARRAY) template class buffer_sequence_adapter > : buffer_sequence_adapter_base { public: explicit buffer_sequence_adapter( const std::array& buffer_sequence) { init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) + boost::asio::buffer_size(buffer_sequence[1]); } native_buffer_type* buffers() { return buffers_; } std::size_t count() const { return 2; } bool all_empty() const { return total_buffer_size_ == 0; } static bool all_empty(const std::array& buffer_sequence) { return boost::asio::buffer_size(buffer_sequence[0]) == 0 && boost::asio::buffer_size(buffer_sequence[1]) == 0; } static void validate(const std::array& buffer_sequence) { boost::asio::buffer_cast(buffer_sequence[0]); boost::asio::buffer_cast(buffer_sequence[1]); } static Buffer first(const std::array& buffer_sequence) { return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 ? buffer_sequence[0] : buffer_sequence[1]); } private: native_buffer_type buffers_[2]; std::size_t total_buffer_size_; }; #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) } // namespace detail } // namespace asio } // namespace boost #include #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP