| // |
| // detail/buffer_sequence_adapter.hpp |
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2010 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 <boost/asio/detail/config.hpp> |
| #include <boost/asio/buffer.hpp> |
| #include <boost/asio/detail/socket_types.hpp> |
| |
| #include <boost/asio/detail/push_options.hpp> |
| |
| 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<char*>(buffer); |
| buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer)); |
| } |
| |
| static void init_native_buffer(WSABUF& buf, |
| const boost::asio::const_buffer& buffer) |
| { |
| buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer)); |
| buf.len = static_cast<ULONG>(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 <typename T> |
| static void init_iov_base(T& base, void* addr) |
| { |
| base = static_cast<T>(addr); |
| } |
| |
| static void init_native_buffer(iovec& iov, |
| const boost::asio::mutable_buffer& buffer) |
| { |
| init_iov_base(iov.iov_base, boost::asio::buffer_cast<void*>(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<void*>( |
| boost::asio::buffer_cast<const void*>(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 <typename Buffer, typename Buffers> |
| class buffer_sequence_adapter |
| : buffer_sequence_adapter_base |
| { |
| public: |
| explicit buffer_sequence_adapter(const Buffers& buffers) |
| : count_(0), total_buffer_size_(0) |
| { |
| typename Buffers::const_iterator iter = buffers.begin(); |
| typename Buffers::const_iterator end = buffers.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& buffers) |
| { |
| typename Buffers::const_iterator iter = buffers.begin(); |
| typename Buffers::const_iterator end = buffers.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& buffers) |
| { |
| typename Buffers::const_iterator iter = buffers.begin(); |
| typename Buffers::const_iterator end = buffers.end(); |
| for (; iter != end; ++iter) |
| { |
| Buffer buffer(*iter); |
| boost::asio::buffer_cast<const void*>(buffer); |
| } |
| } |
| |
| static Buffer first(const Buffers& buffers) |
| { |
| typename Buffers::const_iterator iter = buffers.begin(); |
| typename Buffers::const_iterator end = buffers.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 <typename Buffer> |
| class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1> |
| : buffer_sequence_adapter_base |
| { |
| public: |
| explicit buffer_sequence_adapter( |
| const boost::asio::mutable_buffers_1& buffers) |
| { |
| init_native_buffer(buffer_, Buffer(buffers)); |
| total_buffer_size_ = boost::asio::buffer_size(buffers); |
| } |
| |
| 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& buffers) |
| { |
| return boost::asio::buffer_size(buffers) == 0; |
| } |
| |
| static void validate(const boost::asio::mutable_buffers_1& buffers) |
| { |
| boost::asio::buffer_cast<const void*>(buffers); |
| } |
| |
| static Buffer first(const boost::asio::mutable_buffers_1& buffers) |
| { |
| return Buffer(buffers); |
| } |
| |
| private: |
| native_buffer_type buffer_; |
| std::size_t total_buffer_size_; |
| }; |
| |
| template <typename Buffer> |
| class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1> |
| : buffer_sequence_adapter_base |
| { |
| public: |
| explicit buffer_sequence_adapter( |
| const boost::asio::const_buffers_1& buffers) |
| { |
| init_native_buffer(buffer_, Buffer(buffers)); |
| total_buffer_size_ = boost::asio::buffer_size(buffers); |
| } |
| |
| 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& buffers) |
| { |
| return boost::asio::buffer_size(buffers) == 0; |
| } |
| |
| static void validate(const boost::asio::const_buffers_1& buffers) |
| { |
| boost::asio::buffer_cast<const void*>(buffers); |
| } |
| |
| static Buffer first(const boost::asio::const_buffers_1& buffers) |
| { |
| return Buffer(buffers); |
| } |
| |
| private: |
| native_buffer_type buffer_; |
| std::size_t total_buffer_size_; |
| }; |
| |
| } // namespace detail |
| } // namespace asio |
| } // namespace boost |
| |
| #include <boost/asio/detail/pop_options.hpp> |
| |
| #endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP |