Home | History | Annotate | Download | only in detail
      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 
     33   static void init_iov_base(void*& base, void* addr)
     34   {
     35     base = addr;
     36   }
     37 
     38   template <typename T>
     39   static void init_iov_base(T& base, void* addr)
     40   {
     41     base = static_cast<T>(addr);
     42   }
     43 
     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 
     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:
     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 
     79   native_buffer_type* buffers()
     80   {
     81     return buffers_;
     82   }
     83 
     84   std::size_t count() const
     85   {
     86     return count_;
     87   }
     88 
     89   bool all_empty() const
     90   {
     91     return total_buffer_size_ == 0;
     92   }
     93 
     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 
    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 
    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:
    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 
    147   native_buffer_type* buffers()
    148   {
    149     return &buffer_;
    150   }
    151 
    152   std::size_t count() const
    153   {
    154     return 1;
    155   }
    156 
    157   bool all_empty() const
    158   {
    159     return total_buffer_size_ == 0;
    160   }
    161 
    162   static bool all_empty(const asio::mutable_buffers_1& buffer_sequence)
    163   {
    164     return asio::buffer_size(buffer_sequence) == 0;
    165   }
    166 
    167   static void validate(const asio::mutable_buffers_1& buffer_sequence)
    168   {
    169     asio::buffer_cast<const void*>(buffer_sequence);
    170   }
    171 
    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:
    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 
    194   native_buffer_type* buffers()
    195   {
    196     return &buffer_;
    197   }
    198 
    199   std::size_t count() const
    200   {
    201     return 1;
    202   }
    203 
    204   bool all_empty() const
    205   {
    206     return total_buffer_size_ == 0;
    207   }
    208 
    209   static bool all_empty(const asio::const_buffers_1& buffer_sequence)
    210   {
    211     return asio::buffer_size(buffer_sequence) == 0;
    212   }
    213 
    214   static void validate(const asio::const_buffers_1& buffer_sequence)
    215   {
    216     asio::buffer_cast<const void*>(buffer_sequence);
    217   }
    218 
    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:
    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 
    243   native_buffer_type* buffers()
    244   {
    245     return buffers_;
    246   }
    247 
    248   std::size_t count() const
    249   {
    250     return 2;
    251   }
    252 
    253   bool all_empty() const
    254   {
    255     return total_buffer_size_ == 0;
    256   }
    257 
    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 
    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 
    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:
    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 
    296   native_buffer_type* buffers()
    297   {
    298     return buffers_;
    299   }
    300 
    301   std::size_t count() const
    302   {
    303     return 2;
    304   }
    305 
    306   bool all_empty() const
    307   {
    308     return total_buffer_size_ == 0;
    309   }
    310 
    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 
    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 
    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