Home | History | Annotate | Download | only in asio
      1 //
      2 // buffer.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_BUFFER_HPP
     12 #define ASIO_BUFFER_HPP
     13 
     14 
     15 #include "asio/detail/config.hpp"
     16 #include <cstddef>
     17 #include <cstring>
     18 #include <string>
     19 #include <vector>
     20 #include "asio/detail/array_fwd.hpp"
     21 
     22 
     23 #if defined(__GNUC__)
     24 # if defined(_GLIBCXX_DEBUG)
     25 # endif // defined(_GLIBCXX_DEBUG)
     26 #endif // defined(__GNUC__)
     27 
     28 
     29 
     30 #if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
     31 # include "asio/detail/type_traits.hpp"
     32 #endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
     33 
     34 #include "asio/detail/push_options.hpp"
     35 
     36 namespace asio {
     37 
     38 class mutable_buffer;
     39 class const_buffer;
     40 
     41 namespace detail {
     42 void* buffer_cast_helper(const mutable_buffer&);
     43 const void* buffer_cast_helper(const const_buffer&);
     44 std::size_t buffer_size_helper(const mutable_buffer&);
     45 std::size_t buffer_size_helper(const const_buffer&);
     46 } // namespace detail
     47 
     48 /// Holds a buffer that can be modified.
     49 /**
     50  * The mutable_buffer class provides a safe representation of a buffer that can
     51  * be modified. It does not own the underlying data, and so is cheap to copy or
     52  * assign.
     53  *
     54  * @par Accessing Buffer Contents
     55  *
     56  * The contents of a buffer may be accessed using the @ref buffer_size
     57  * and @ref buffer_cast functions:
     58  *
     59  * @code asio::mutable_buffer b1 = ...;
     60  * std::size_t s1 = asio::buffer_size(b1);
     61  * unsigned char* p1 = asio::buffer_cast<unsigned char*>(b1);
     62  * @endcode
     63  *
     64  * The asio::buffer_cast function permits violations of type safety, so
     65  * uses of it in application code should be carefully considered.
     66  */
     67 class mutable_buffer
     68 {
     69 public:
     70   /// Construct an empty buffer.
     71   mutable_buffer()
     72     : data_(0),
     73       size_(0)
     74   {
     75   }
     76 
     77   /// Construct a buffer to represent a given memory range.
     78   mutable_buffer(void* data, std::size_t size)
     79     : data_(data),
     80       size_(size)
     81   {
     82   }
     83 
     84 
     85 private:
     86   friend void* asio::detail::buffer_cast_helper(
     87       const mutable_buffer& b);
     88   friend std::size_t asio::detail::buffer_size_helper(
     89       const mutable_buffer& b);
     90 
     91   void* data_;
     92   std::size_t size_;
     93 
     94 };
     95 
     96 namespace detail {
     97 
     98 inline void* buffer_cast_helper(const mutable_buffer& b)
     99 {
    100   return b.data_;
    101 }
    102 
    103 inline std::size_t buffer_size_helper(const mutable_buffer& b)
    104 {
    105   return b.size_;
    106 }
    107 
    108 } // namespace detail
    109 
    110 /// Adapts a single modifiable buffer so that it meets the requirements of the
    111 /// MutableBufferSequence concept.
    112 class mutable_buffers_1
    113   : public mutable_buffer
    114 {
    115 public:
    116   /// The type for each element in the list of buffers.
    117   typedef mutable_buffer value_type;
    118 
    119   /// A random-access iterator type that may be used to read elements.
    120   typedef const mutable_buffer* const_iterator;
    121 
    122   /// Construct to represent a given memory range.
    123   mutable_buffers_1(void* data, std::size_t size)
    124     : mutable_buffer(data, size)
    125   {
    126   }
    127 
    128   /// Construct to represent a single modifiable buffer.
    129   explicit mutable_buffers_1(const mutable_buffer& b)
    130     : mutable_buffer(b)
    131   {
    132   }
    133 
    134   /// Get a random-access iterator to the first element.
    135   const_iterator begin() const
    136   {
    137     return this;
    138   }
    139 
    140   /// Get a random-access iterator for one past the last element.
    141   const_iterator end() const
    142   {
    143     return begin() + 1;
    144   }
    145 };
    146 
    147 /// Holds a buffer that cannot be modified.
    148 /**
    149  * The const_buffer class provides a safe representation of a buffer that cannot
    150  * be modified. It does not own the underlying data, and so is cheap to copy or
    151  * assign.
    152  *
    153  * @par Accessing Buffer Contents
    154  *
    155  * The contents of a buffer may be accessed using the @ref buffer_size
    156  * and @ref buffer_cast functions:
    157  *
    158  * @code asio::const_buffer b1 = ...;
    159  * std::size_t s1 = asio::buffer_size(b1);
    160  * const unsigned char* p1 = asio::buffer_cast<const unsigned char*>(b1);
    161  * @endcode
    162  *
    163  * The asio::buffer_cast function permits violations of type safety, so
    164  * uses of it in application code should be carefully considered.
    165  */
    166 class const_buffer
    167 {
    168 public:
    169   /// Construct an empty buffer.
    170   const_buffer()
    171     : data_(0),
    172       size_(0)
    173   {
    174   }
    175 
    176   /// Construct a buffer to represent a given memory range.
    177   const_buffer(const void* data, std::size_t size)
    178     : data_(data),
    179       size_(size)
    180   {
    181   }
    182 
    183   /// Construct a non-modifiable buffer from a modifiable one.
    184   const_buffer(const mutable_buffer& b)
    185     : data_(asio::detail::buffer_cast_helper(b)),
    186       size_(asio::detail::buffer_size_helper(b))
    187   {
    188   }
    189 
    190 
    191 private:
    192   friend const void* asio::detail::buffer_cast_helper(
    193       const const_buffer& b);
    194   friend std::size_t asio::detail::buffer_size_helper(
    195       const const_buffer& b);
    196 
    197   const void* data_;
    198   std::size_t size_;
    199 
    200 };
    201 
    202 namespace detail {
    203 
    204 inline const void* buffer_cast_helper(const const_buffer& b)
    205 {
    206   return b.data_;
    207 }
    208 
    209 inline std::size_t buffer_size_helper(const const_buffer& b)
    210 {
    211   return b.size_;
    212 }
    213 
    214 } // namespace detail
    215 
    216 /// Adapts a single non-modifiable buffer so that it meets the requirements of
    217 /// the ConstBufferSequence concept.
    218 class const_buffers_1
    219   : public const_buffer
    220 {
    221 public:
    222   /// The type for each element in the list of buffers.
    223   typedef const_buffer value_type;
    224 
    225   /// A random-access iterator type that may be used to read elements.
    226   typedef const const_buffer* const_iterator;
    227 
    228   /// Construct to represent a given memory range.
    229   const_buffers_1(const void* data, std::size_t size)
    230     : const_buffer(data, size)
    231   {
    232   }
    233 
    234   /// Construct to represent a single non-modifiable buffer.
    235   explicit const_buffers_1(const const_buffer& b)
    236     : const_buffer(b)
    237   {
    238   }
    239 
    240   /// Get a random-access iterator to the first element.
    241   const_iterator begin() const
    242   {
    243     return this;
    244   }
    245 
    246   /// Get a random-access iterator for one past the last element.
    247   const_iterator end() const
    248   {
    249     return begin() + 1;
    250   }
    251 };
    252 
    253 /// An implementation of both the ConstBufferSequence and MutableBufferSequence
    254 /// concepts to represent a null buffer sequence.
    255 class null_buffers
    256 {
    257 public:
    258   /// The type for each element in the list of buffers.
    259   typedef mutable_buffer value_type;
    260 
    261   /// A random-access iterator type that may be used to read elements.
    262   typedef const mutable_buffer* const_iterator;
    263 
    264   /// Get a random-access iterator to the first element.
    265   const_iterator begin() const
    266   {
    267     return &buf_;
    268   }
    269 
    270   /// Get a random-access iterator for one past the last element.
    271   const_iterator end() const
    272   {
    273     return &buf_;
    274   }
    275 
    276 private:
    277   mutable_buffer buf_;
    278 };
    279 
    280 /** @defgroup buffer_size asio::buffer_size
    281  *
    282  * @brief The asio::buffer_size function determines the total number of
    283  * bytes in a buffer or buffer sequence.
    284  */
    285 /*@{*/
    286 
    287 /// Get the number of bytes in a modifiable buffer.
    288 inline std::size_t buffer_size(const mutable_buffer& b)
    289 {
    290   return detail::buffer_size_helper(b);
    291 }
    292 
    293 /// Get the number of bytes in a modifiable buffer.
    294 inline std::size_t buffer_size(const mutable_buffers_1& b)
    295 {
    296   return detail::buffer_size_helper(b);
    297 }
    298 
    299 /// Get the number of bytes in a non-modifiable buffer.
    300 inline std::size_t buffer_size(const const_buffer& b)
    301 {
    302   return detail::buffer_size_helper(b);
    303 }
    304 
    305 /// Get the number of bytes in a non-modifiable buffer.
    306 inline std::size_t buffer_size(const const_buffers_1& b)
    307 {
    308   return detail::buffer_size_helper(b);
    309 }
    310 
    311 /// Get the total number of bytes in a buffer sequence.
    312 /**
    313  * The @c BufferSequence template parameter may meet either of the @c
    314  * ConstBufferSequence or @c MutableBufferSequence type requirements.
    315  */
    316 template <typename BufferSequence>
    317 inline std::size_t buffer_size(const BufferSequence& b)
    318 {
    319   std::size_t total_buffer_size = 0;
    320 
    321   typename BufferSequence::const_iterator iter = b.begin();
    322   typename BufferSequence::const_iterator end = b.end();
    323   for (; iter != end; ++iter)
    324     total_buffer_size += detail::buffer_size_helper(*iter);
    325 
    326   return total_buffer_size;
    327 }
    328 
    329 /*@}*/
    330 
    331 /** @defgroup buffer_cast asio::buffer_cast
    332  *
    333  * @brief The asio::buffer_cast function is used to obtain a pointer to
    334  * the underlying memory region associated with a buffer.
    335  *
    336  * @par Examples:
    337  *
    338  * To access the memory of a non-modifiable buffer, use:
    339  * @code asio::const_buffer b1 = ...;
    340  * const unsigned char* p1 = asio::buffer_cast<const unsigned char*>(b1);
    341  * @endcode
    342  *
    343  * To access the memory of a modifiable buffer, use:
    344  * @code asio::mutable_buffer b2 = ...;
    345  * unsigned char* p2 = asio::buffer_cast<unsigned char*>(b2);
    346  * @endcode
    347  *
    348  * The asio::buffer_cast function permits violations of type safety, so
    349  * uses of it in application code should be carefully considered.
    350  */
    351 /*@{*/
    352 
    353 /// Cast a non-modifiable buffer to a specified pointer to POD type.
    354 template <typename PointerToPodType>
    355 inline PointerToPodType buffer_cast(const mutable_buffer& b)
    356 {
    357   return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
    358 }
    359 
    360 /// Cast a non-modifiable buffer to a specified pointer to POD type.
    361 template <typename PointerToPodType>
    362 inline PointerToPodType buffer_cast(const const_buffer& b)
    363 {
    364   return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
    365 }
    366 
    367 /*@}*/
    368 
    369 /// Create a new modifiable buffer that is offset from the start of another.
    370 /**
    371  * @relates mutable_buffer
    372  */
    373 inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
    374 {
    375   if (start > buffer_size(b))
    376     return mutable_buffer();
    377   char* new_data = buffer_cast<char*>(b) + start;
    378   std::size_t new_size = buffer_size(b) - start;
    379   return mutable_buffer(new_data, new_size
    380       );
    381 }
    382 
    383 /// Create a new modifiable buffer that is offset from the start of another.
    384 /**
    385  * @relates mutable_buffer
    386  */
    387 inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
    388 {
    389   if (start > buffer_size(b))
    390     return mutable_buffer();
    391   char* new_data = buffer_cast<char*>(b) + start;
    392   std::size_t new_size = buffer_size(b) - start;
    393   return mutable_buffer(new_data, new_size
    394       );
    395 }
    396 
    397 /// Create a new non-modifiable buffer that is offset from the start of another.
    398 /**
    399  * @relates const_buffer
    400  */
    401 inline const_buffer operator+(const const_buffer& b, std::size_t start)
    402 {
    403   if (start > buffer_size(b))
    404     return const_buffer();
    405   const char* new_data = buffer_cast<const char*>(b) + start;
    406   std::size_t new_size = buffer_size(b) - start;
    407   return const_buffer(new_data, new_size
    408       );
    409 }
    410 
    411 /// Create a new non-modifiable buffer that is offset from the start of another.
    412 /**
    413  * @relates const_buffer
    414  */
    415 inline const_buffer operator+(std::size_t start, const const_buffer& b)
    416 {
    417   if (start > buffer_size(b))
    418     return const_buffer();
    419   const char* new_data = buffer_cast<const char*>(b) + start;
    420   std::size_t new_size = buffer_size(b) - start;
    421   return const_buffer(new_data, new_size
    422       );
    423 }
    424 
    425 
    426 /** @defgroup buffer asio::buffer
    427  *
    428  * @brief The asio::buffer function is used to create a buffer object to
    429  * represent raw memory, an array of POD elements, a vector of POD elements,
    430  * or a std::string.
    431  *
    432  * A buffer object represents a contiguous region of memory as a 2-tuple
    433  * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*,
    434  * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a
    435  * tuple of the form <tt>{const void*, size_t}</tt> specifies a const
    436  * (non-modifiable) region of memory. These two forms correspond to the classes
    437  * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion
    438  * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the
    439  * opposite conversion is not permitted.
    440  *
    441  * The simplest use case involves reading or writing a single buffer of a
    442  * specified size:
    443  *
    444  * @code sock.send(asio::buffer(data, size)); @endcode
    445  *
    446  * In the above example, the return value of asio::buffer meets the
    447  * requirements of the ConstBufferSequence concept so that it may be directly
    448  * passed to the socket's write function. A buffer created for modifiable
    449  * memory also meets the requirements of the MutableBufferSequence concept.
    450  *
    451  * An individual buffer may be created from a builtin array, std::vector,
    452  * std::array or boost::array of POD elements. This helps prevent buffer
    453  * overruns by automatically determining the size of the buffer:
    454  *
    455  * @code char d1[128];
    456  * size_t bytes_transferred = sock.receive(asio::buffer(d1));
    457  *
    458  * std::vector<char> d2(128);
    459  * bytes_transferred = sock.receive(asio::buffer(d2));
    460  *
    461  * std::array<char, 128> d3;
    462  * bytes_transferred = sock.receive(asio::buffer(d3));
    463  *
    464  * boost::array<char, 128> d4;
    465  * bytes_transferred = sock.receive(asio::buffer(d4)); @endcode
    466  *
    467  * In all three cases above, the buffers created are exactly 128 bytes long.
    468  * Note that a vector is @e never automatically resized when creating or using
    469  * a buffer. The buffer size is determined using the vector's <tt>size()</tt>
    470  * member function, and not its capacity.
    471  *
    472  * @par Accessing Buffer Contents
    473  *
    474  * The contents of a buffer may be accessed using the @ref buffer_size and
    475  * @ref buffer_cast functions:
    476  *
    477  * @code asio::mutable_buffer b1 = ...;
    478  * std::size_t s1 = asio::buffer_size(b1);
    479  * unsigned char* p1 = asio::buffer_cast<unsigned char*>(b1);
    480  *
    481  * asio::const_buffer b2 = ...;
    482  * std::size_t s2 = asio::buffer_size(b2);
    483  * const void* p2 = asio::buffer_cast<const void*>(b2); @endcode
    484  *
    485  * The asio::buffer_cast function permits violations of type safety, so
    486  * uses of it in application code should be carefully considered.
    487  *
    488  * For convenience, the @ref buffer_size function also works on buffer
    489  * sequences (that is, types meeting the ConstBufferSequence or
    490  * MutableBufferSequence type requirements). In this case, the function returns
    491  * the total size of all buffers in the sequence.
    492  *
    493  * @par Buffer Copying
    494  *
    495  * The @ref buffer_copy function may be used to copy raw bytes between
    496  * individual buffers and buffer sequences.
    497  *
    498  * In particular, when used with the @ref buffer_size, the @ref buffer_copy
    499  * function can be used to linearise a sequence of buffers. For example:
    500  *
    501  * @code vector<const_buffer> buffers = ...;
    502  *
    503  * vector<unsigned char> data(asio::buffer_size(buffers));
    504  * asio::buffer_copy(asio::buffer(data), buffers); @endcode
    505  *
    506  * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
    507  * consequently it cannot be used to copy between overlapping memory regions.
    508  *
    509  * @par Buffer Invalidation
    510  *
    511  * A buffer object does not have any ownership of the memory it refers to. It
    512  * is the responsibility of the application to ensure the memory region remains
    513  * valid until it is no longer required for an I/O operation. When the memory
    514  * is no longer available, the buffer is said to have been invalidated.
    515  *
    516  * For the asio::buffer overloads that accept an argument of type
    517  * std::vector, the buffer objects returned are invalidated by any vector
    518  * operation that also invalidates all references, pointers and iterators
    519  * referring to the elements in the sequence (C++ Std, 23.2.4)
    520  *
    521  * For the asio::buffer overloads that accept an argument of type
    522  * std::basic_string, the buffer objects returned are invalidated according to
    523  * the rules defined for invalidation of references, pointers and iterators
    524  * referring to elements of the sequence (C++ Std, 21.3).
    525  *
    526  * @par Buffer Arithmetic
    527  *
    528  * Buffer objects may be manipulated using simple arithmetic in a safe way
    529  * which helps prevent buffer overruns. Consider an array initialised as
    530  * follows:
    531  *
    532  * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode
    533  *
    534  * A buffer object @c b1 created using:
    535  *
    536  * @code b1 = asio::buffer(a); @endcode
    537  *
    538  * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An
    539  * optional second argument to the asio::buffer function may be used to
    540  * limit the size, in bytes, of the buffer:
    541  *
    542  * @code b2 = asio::buffer(a, 3); @endcode
    543  *
    544  * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the
    545  * size argument exceeds the actual size of the array, the size of the buffer
    546  * object created will be limited to the array size.
    547  *
    548  * An offset may be applied to an existing buffer to create a new one:
    549  *
    550  * @code b3 = b1 + 2; @endcode
    551  *
    552  * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset
    553  * exceeds the size of the existing buffer, the newly created buffer will be
    554  * empty.
    555  *
    556  * Both an offset and size may be specified to create a buffer that corresponds
    557  * to a specific range of bytes within an existing buffer:
    558  *
    559  * @code b4 = asio::buffer(b1 + 1, 3); @endcode
    560  *
    561  * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.
    562  *
    563  * @par Buffers and Scatter-Gather I/O
    564  *
    565  * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
    566  * buffer objects may be assigned into a container that supports the
    567  * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
    568  *
    569  * @code
    570  * char d1[128];
    571  * std::vector<char> d2(128);
    572  * boost::array<char, 128> d3;
    573  *
    574  * boost::array<mutable_buffer, 3> bufs1 = {
    575  *   asio::buffer(d1),
    576  *   asio::buffer(d2),
    577  *   asio::buffer(d3) };
    578  * bytes_transferred = sock.receive(bufs1);
    579  *
    580  * std::vector<const_buffer> bufs2;
    581  * bufs2.push_back(asio::buffer(d1));
    582  * bufs2.push_back(asio::buffer(d2));
    583  * bufs2.push_back(asio::buffer(d3));
    584  * bytes_transferred = sock.send(bufs2); @endcode
    585  */
    586 /*@{*/
    587 
    588 /// Create a new modifiable buffer from an existing buffer.
    589 /**
    590  * @returns <tt>mutable_buffers_1(b)</tt>.
    591  */
    592 inline mutable_buffers_1 buffer(const mutable_buffer& b)
    593 {
    594   return mutable_buffers_1(b);
    595 }
    596 
    597 /// Create a new modifiable buffer from an existing buffer.
    598 /**
    599  * @returns A mutable_buffers_1 value equivalent to:
    600  * @code mutable_buffers_1(
    601  *     buffer_cast<void*>(b),
    602  *     min(buffer_size(b), max_size_in_bytes)); @endcode
    603  */
    604 inline mutable_buffers_1 buffer(const mutable_buffer& b,
    605     std::size_t max_size_in_bytes)
    606 {
    607   return mutable_buffers_1(
    608       mutable_buffer(buffer_cast<void*>(b),
    609         buffer_size(b) < max_size_in_bytes
    610         ? buffer_size(b) : max_size_in_bytes
    611         ));
    612 }
    613 
    614 /// Create a new non-modifiable buffer from an existing buffer.
    615 /**
    616  * @returns <tt>const_buffers_1(b)</tt>.
    617  */
    618 inline const_buffers_1 buffer(const const_buffer& b)
    619 {
    620   return const_buffers_1(b);
    621 }
    622 
    623 /// Create a new non-modifiable buffer from an existing buffer.
    624 /**
    625  * @returns A const_buffers_1 value equivalent to:
    626  * @code const_buffers_1(
    627  *     buffer_cast<const void*>(b),
    628  *     min(buffer_size(b), max_size_in_bytes)); @endcode
    629  */
    630 inline const_buffers_1 buffer(const const_buffer& b,
    631     std::size_t max_size_in_bytes)
    632 {
    633   return const_buffers_1(
    634       const_buffer(buffer_cast<const void*>(b),
    635         buffer_size(b) < max_size_in_bytes
    636         ? buffer_size(b) : max_size_in_bytes
    637         ));
    638 }
    639 
    640 /// Create a new modifiable buffer that represents the given memory range.
    641 /**
    642  * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>.
    643  */
    644 inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
    645 {
    646   return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
    647 }
    648 
    649 /// Create a new non-modifiable buffer that represents the given memory range.
    650 /**
    651  * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>.
    652  */
    653 inline const_buffers_1 buffer(const void* data,
    654     std::size_t size_in_bytes)
    655 {
    656   return const_buffers_1(const_buffer(data, size_in_bytes));
    657 }
    658 
    659 /// Create a new modifiable buffer that represents the given POD array.
    660 /**
    661  * @returns A mutable_buffers_1 value equivalent to:
    662  * @code mutable_buffers_1(
    663  *     static_cast<void*>(data),
    664  *     N * sizeof(PodType)); @endcode
    665  */
    666 template <typename PodType, std::size_t N>
    667 inline mutable_buffers_1 buffer(PodType (&data)[N])
    668 {
    669   return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
    670 }
    671 
    672 /// Create a new modifiable buffer that represents the given POD array.
    673 /**
    674  * @returns A mutable_buffers_1 value equivalent to:
    675  * @code mutable_buffers_1(
    676  *     static_cast<void*>(data),
    677  *     min(N * sizeof(PodType), max_size_in_bytes)); @endcode
    678  */
    679 template <typename PodType, std::size_t N>
    680 inline mutable_buffers_1 buffer(PodType (&data)[N],
    681     std::size_t max_size_in_bytes)
    682 {
    683   return mutable_buffers_1(
    684       mutable_buffer(data,
    685         N * sizeof(PodType) < max_size_in_bytes
    686         ? N * sizeof(PodType) : max_size_in_bytes));
    687 }
    688 
    689 /// Create a new non-modifiable buffer that represents the given POD array.
    690 /**
    691  * @returns A const_buffers_1 value equivalent to:
    692  * @code const_buffers_1(
    693  *     static_cast<const void*>(data),
    694  *     N * sizeof(PodType)); @endcode
    695  */
    696 template <typename PodType, std::size_t N>
    697 inline const_buffers_1 buffer(const PodType (&data)[N])
    698 {
    699   return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
    700 }
    701 
    702 /// Create a new non-modifiable buffer that represents the given POD array.
    703 /**
    704  * @returns A const_buffers_1 value equivalent to:
    705  * @code const_buffers_1(
    706  *     static_cast<const void*>(data),
    707  *     min(N * sizeof(PodType), max_size_in_bytes)); @endcode
    708  */
    709 template <typename PodType, std::size_t N>
    710 inline const_buffers_1 buffer(const PodType (&data)[N],
    711     std::size_t max_size_in_bytes)
    712 {
    713   return const_buffers_1(
    714       const_buffer(data,
    715         N * sizeof(PodType) < max_size_in_bytes
    716         ? N * sizeof(PodType) : max_size_in_bytes));
    717 }
    718 
    719 #if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
    720 
    721 // Borland C++ and Sun Studio think the overloads:
    722 //
    723 //   unspecified buffer(boost::array<PodType, N>& array ...);
    724 //
    725 // and
    726 //
    727 //   unspecified buffer(boost::array<const PodType, N>& array ...);
    728 //
    729 // are ambiguous. This will be worked around by using a buffer_types traits
    730 // class that contains typedefs for the appropriate buffer and container
    731 // classes, based on whether PodType is const or non-const.
    732 
    733 namespace detail {
    734 
    735 template <bool IsConst>
    736 struct buffer_types_base;
    737 
    738 template <>
    739 struct buffer_types_base<false>
    740 {
    741   typedef mutable_buffer buffer_type;
    742   typedef mutable_buffers_1 container_type;
    743 };
    744 
    745 template <>
    746 struct buffer_types_base<true>
    747 {
    748   typedef const_buffer buffer_type;
    749   typedef const_buffers_1 container_type;
    750 };
    751 
    752 template <typename PodType>
    753 struct buffer_types
    754   : public buffer_types_base<is_const<PodType>::value>
    755 {
    756 };
    757 
    758 } // namespace detail
    759 
    760 template <typename PodType, std::size_t N>
    761 inline typename detail::buffer_types<PodType>::container_type
    762 buffer(boost::array<PodType, N>& data)
    763 {
    764   typedef typename asio::detail::buffer_types<PodType>::buffer_type
    765     buffer_type;
    766   typedef typename asio::detail::buffer_types<PodType>::container_type
    767     container_type;
    768   return container_type(
    769       buffer_type(data.c_array(), data.size() * sizeof(PodType)));
    770 }
    771 
    772 template <typename PodType, std::size_t N>
    773 inline typename detail::buffer_types<PodType>::container_type
    774 buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
    775 {
    776   typedef typename asio::detail::buffer_types<PodType>::buffer_type
    777     buffer_type;
    778   typedef typename asio::detail::buffer_types<PodType>::container_type
    779     container_type;
    780   return container_type(
    781       buffer_type(data.c_array(),
    782         data.size() * sizeof(PodType) < max_size_in_bytes
    783         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    784 }
    785 
    786 #else // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
    787 
    788 /// Create a new modifiable buffer that represents the given POD array.
    789 /**
    790  * @returns A mutable_buffers_1 value equivalent to:
    791  * @code mutable_buffers_1(
    792  *     data.data(),
    793  *     data.size() * sizeof(PodType)); @endcode
    794  */
    795 template <typename PodType, std::size_t N>
    796 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
    797 {
    798   return mutable_buffers_1(
    799       mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
    800 }
    801 
    802 /// Create a new modifiable buffer that represents the given POD array.
    803 /**
    804  * @returns A mutable_buffers_1 value equivalent to:
    805  * @code mutable_buffers_1(
    806  *     data.data(),
    807  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    808  */
    809 template <typename PodType, std::size_t N>
    810 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
    811     std::size_t max_size_in_bytes)
    812 {
    813   return mutable_buffers_1(
    814       mutable_buffer(data.c_array(),
    815         data.size() * sizeof(PodType) < max_size_in_bytes
    816         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    817 }
    818 
    819 /// Create a new non-modifiable buffer that represents the given POD array.
    820 /**
    821  * @returns A const_buffers_1 value equivalent to:
    822  * @code const_buffers_1(
    823  *     data.data(),
    824  *     data.size() * sizeof(PodType)); @endcode
    825  */
    826 template <typename PodType, std::size_t N>
    827 inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
    828 {
    829   return const_buffers_1(
    830       const_buffer(data.data(), data.size() * sizeof(PodType)));
    831 }
    832 
    833 /// Create a new non-modifiable buffer that represents the given POD array.
    834 /**
    835  * @returns A const_buffers_1 value equivalent to:
    836  * @code const_buffers_1(
    837  *     data.data(),
    838  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    839  */
    840 template <typename PodType, std::size_t N>
    841 inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
    842     std::size_t max_size_in_bytes)
    843 {
    844   return const_buffers_1(
    845       const_buffer(data.data(),
    846         data.size() * sizeof(PodType) < max_size_in_bytes
    847         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    848 }
    849 
    850 #endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
    851 
    852 /// Create a new non-modifiable buffer that represents the given POD array.
    853 /**
    854  * @returns A const_buffers_1 value equivalent to:
    855  * @code const_buffers_1(
    856  *     data.data(),
    857  *     data.size() * sizeof(PodType)); @endcode
    858  */
    859 template <typename PodType, std::size_t N>
    860 inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
    861 {
    862   return const_buffers_1(
    863       const_buffer(data.data(), data.size() * sizeof(PodType)));
    864 }
    865 
    866 /// Create a new non-modifiable buffer that represents the given POD array.
    867 /**
    868  * @returns A const_buffers_1 value equivalent to:
    869  * @code const_buffers_1(
    870  *     data.data(),
    871  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    872  */
    873 template <typename PodType, std::size_t N>
    874 inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
    875     std::size_t max_size_in_bytes)
    876 {
    877   return const_buffers_1(
    878       const_buffer(data.data(),
    879         data.size() * sizeof(PodType) < max_size_in_bytes
    880         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    881 }
    882 
    883 
    884 /// Create a new modifiable buffer that represents the given POD array.
    885 /**
    886  * @returns A mutable_buffers_1 value equivalent to:
    887  * @code mutable_buffers_1(
    888  *     data.data(),
    889  *     data.size() * sizeof(PodType)); @endcode
    890  */
    891 template <typename PodType, std::size_t N>
    892 inline mutable_buffers_1 buffer(std::array<PodType, N>& data)
    893 {
    894   return mutable_buffers_1(
    895       mutable_buffer(data.data(), data.size() * sizeof(PodType)));
    896 }
    897 
    898 /// Create a new modifiable buffer that represents the given POD array.
    899 /**
    900  * @returns A mutable_buffers_1 value equivalent to:
    901  * @code mutable_buffers_1(
    902  *     data.data(),
    903  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    904  */
    905 template <typename PodType, std::size_t N>
    906 inline mutable_buffers_1 buffer(std::array<PodType, N>& data,
    907     std::size_t max_size_in_bytes)
    908 {
    909   return mutable_buffers_1(
    910       mutable_buffer(data.data(),
    911         data.size() * sizeof(PodType) < max_size_in_bytes
    912         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    913 }
    914 
    915 /// Create a new non-modifiable buffer that represents the given POD array.
    916 /**
    917  * @returns A const_buffers_1 value equivalent to:
    918  * @code const_buffers_1(
    919  *     data.data(),
    920  *     data.size() * sizeof(PodType)); @endcode
    921  */
    922 template <typename PodType, std::size_t N>
    923 inline const_buffers_1 buffer(std::array<const PodType, N>& data)
    924 {
    925   return const_buffers_1(
    926       const_buffer(data.data(), data.size() * sizeof(PodType)));
    927 }
    928 
    929 /// Create a new non-modifiable buffer that represents the given POD array.
    930 /**
    931  * @returns A const_buffers_1 value equivalent to:
    932  * @code const_buffers_1(
    933  *     data.data(),
    934  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    935  */
    936 template <typename PodType, std::size_t N>
    937 inline const_buffers_1 buffer(std::array<const PodType, N>& data,
    938     std::size_t max_size_in_bytes)
    939 {
    940   return const_buffers_1(
    941       const_buffer(data.data(),
    942         data.size() * sizeof(PodType) < max_size_in_bytes
    943         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    944 }
    945 
    946 /// Create a new non-modifiable buffer that represents the given POD array.
    947 /**
    948  * @returns A const_buffers_1 value equivalent to:
    949  * @code const_buffers_1(
    950  *     data.data(),
    951  *     data.size() * sizeof(PodType)); @endcode
    952  */
    953 template <typename PodType, std::size_t N>
    954 inline const_buffers_1 buffer(const std::array<PodType, N>& data)
    955 {
    956   return const_buffers_1(
    957       const_buffer(data.data(), data.size() * sizeof(PodType)));
    958 }
    959 
    960 /// Create a new non-modifiable buffer that represents the given POD array.
    961 /**
    962  * @returns A const_buffers_1 value equivalent to:
    963  * @code const_buffers_1(
    964  *     data.data(),
    965  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
    966  */
    967 template <typename PodType, std::size_t N>
    968 inline const_buffers_1 buffer(const std::array<PodType, N>& data,
    969     std::size_t max_size_in_bytes)
    970 {
    971   return const_buffers_1(
    972       const_buffer(data.data(),
    973         data.size() * sizeof(PodType) < max_size_in_bytes
    974         ? data.size() * sizeof(PodType) : max_size_in_bytes));
    975 }
    976 
    977 
    978 /// Create a new modifiable buffer that represents the given POD vector.
    979 /**
    980  * @returns A mutable_buffers_1 value equivalent to:
    981  * @code mutable_buffers_1(
    982  *     data.size() ? &data[0] : 0,
    983  *     data.size() * sizeof(PodType)); @endcode
    984  *
    985  * @note The buffer is invalidated by any vector operation that would also
    986  * invalidate iterators.
    987  */
    988 template <typename PodType, typename Allocator>
    989 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
    990 {
    991   return mutable_buffers_1(
    992       mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
    993         ));
    994 }
    995 
    996 /// Create a new modifiable buffer that represents the given POD vector.
    997 /**
    998  * @returns A mutable_buffers_1 value equivalent to:
    999  * @code mutable_buffers_1(
   1000  *     data.size() ? &data[0] : 0,
   1001  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
   1002  *
   1003  * @note The buffer is invalidated by any vector operation that would also
   1004  * invalidate iterators.
   1005  */
   1006 template <typename PodType, typename Allocator>
   1007 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
   1008     std::size_t max_size_in_bytes)
   1009 {
   1010   return mutable_buffers_1(
   1011       mutable_buffer(data.size() ? &data[0] : 0,
   1012         data.size() * sizeof(PodType) < max_size_in_bytes
   1013         ? data.size() * sizeof(PodType) : max_size_in_bytes
   1014         ));
   1015 }
   1016 
   1017 /// Create a new non-modifiable buffer that represents the given POD vector.
   1018 /**
   1019  * @returns A const_buffers_1 value equivalent to:
   1020  * @code const_buffers_1(
   1021  *     data.size() ? &data[0] : 0,
   1022  *     data.size() * sizeof(PodType)); @endcode
   1023  *
   1024  * @note The buffer is invalidated by any vector operation that would also
   1025  * invalidate iterators.
   1026  */
   1027 template <typename PodType, typename Allocator>
   1028 inline const_buffers_1 buffer(
   1029     const std::vector<PodType, Allocator>& data)
   1030 {
   1031   return const_buffers_1(
   1032       const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
   1033         ));
   1034 }
   1035 
   1036 /// Create a new non-modifiable buffer that represents the given POD vector.
   1037 /**
   1038  * @returns A const_buffers_1 value equivalent to:
   1039  * @code const_buffers_1(
   1040  *     data.size() ? &data[0] : 0,
   1041  *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
   1042  *
   1043  * @note The buffer is invalidated by any vector operation that would also
   1044  * invalidate iterators.
   1045  */
   1046 template <typename PodType, typename Allocator>
   1047 inline const_buffers_1 buffer(
   1048     const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
   1049 {
   1050   return const_buffers_1(
   1051       const_buffer(data.size() ? &data[0] : 0,
   1052         data.size() * sizeof(PodType) < max_size_in_bytes
   1053         ? data.size() * sizeof(PodType) : max_size_in_bytes
   1054         ));
   1055 }
   1056 
   1057 /// Create a new non-modifiable buffer that represents the given string.
   1058 /**
   1059  * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>.
   1060  *
   1061  * @note The buffer is invalidated by any non-const operation called on the
   1062  * given string object.
   1063  */
   1064 template <typename Elem, typename Traits, typename Allocator>
   1065 inline const_buffers_1 buffer(
   1066     const std::basic_string<Elem, Traits, Allocator>& data)
   1067 {
   1068   return const_buffers_1(const_buffer(data.data(), data.size() * sizeof(Elem)
   1069         ));
   1070 }
   1071 
   1072 /// Create a new non-modifiable buffer that represents the given string.
   1073 /**
   1074  * @returns A const_buffers_1 value equivalent to:
   1075  * @code const_buffers_1(
   1076  *     data.data(),
   1077  *     min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
   1078  *
   1079  * @note The buffer is invalidated by any non-const operation called on the
   1080  * given string object.
   1081  */
   1082 template <typename Elem, typename Traits, typename Allocator>
   1083 inline const_buffers_1 buffer(
   1084     const std::basic_string<Elem, Traits, Allocator>& data,
   1085     std::size_t max_size_in_bytes)
   1086 {
   1087   return const_buffers_1(
   1088       const_buffer(data.data(),
   1089         data.size() * sizeof(Elem) < max_size_in_bytes
   1090         ? data.size() * sizeof(Elem) : max_size_in_bytes
   1091         ));
   1092 }
   1093 
   1094 /*@}*/
   1095 
   1096 /** @defgroup buffer_copy asio::buffer_copy
   1097  *
   1098  * @brief The asio::buffer_copy function is used to copy bytes from a
   1099  * source buffer (or buffer sequence) to a target buffer (or buffer sequence).
   1100  *
   1101  * The @c buffer_copy function is available in two forms:
   1102  *
   1103  * @li A 2-argument form: @c buffer_copy(target, source)
   1104  *
   1105  * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
   1106 
   1107  * Both forms return the number of bytes actually copied. The number of bytes
   1108  * copied is the lesser of:
   1109  *
   1110  * @li @c buffer_size(target)
   1111  *
   1112  * @li @c buffer_size(source)
   1113  *
   1114  * @li @c If specified, @c max_bytes_to_copy.
   1115  *
   1116  * This prevents buffer overflow, regardless of the buffer sizes used in the
   1117  * copy operation.
   1118  *
   1119  * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
   1120  * consequently it cannot be used to copy between overlapping memory regions.
   1121  */
   1122 /*@{*/
   1123 
   1124 /// Copies bytes from a source buffer to a target buffer.
   1125 /**
   1126  * @param target A modifiable buffer representing the memory region to which
   1127  * the bytes will be copied.
   1128  *
   1129  * @param source A non-modifiable buffer representing the memory region from
   1130  * which the bytes will be copied.
   1131  *
   1132  * @returns The number of bytes copied.
   1133  *
   1134  * @note The number of bytes copied is the lesser of:
   1135  *
   1136  * @li @c buffer_size(target)
   1137  *
   1138  * @li @c buffer_size(source)
   1139  *
   1140  * This function is implemented in terms of @c memcpy, and consequently it
   1141  * cannot be used to copy between overlapping memory regions.
   1142  */
   1143 inline std::size_t buffer_copy(const mutable_buffer& target,
   1144     const const_buffer& source)
   1145 {
   1146   using namespace std; // For memcpy.
   1147   std::size_t target_size = buffer_size(target);
   1148   std::size_t source_size = buffer_size(source);
   1149   std::size_t n = target_size < source_size ? target_size : source_size;
   1150   memcpy(buffer_cast<void*>(target), buffer_cast<const void*>(source), n);
   1151   return n;
   1152 }
   1153 
   1154 /// Copies bytes from a source buffer to a target buffer.
   1155 /**
   1156  * @param target A modifiable buffer representing the memory region to which
   1157  * the bytes will be copied.
   1158  *
   1159  * @param source A non-modifiable buffer representing the memory region from
   1160  * which the bytes will be copied.
   1161  *
   1162  * @returns The number of bytes copied.
   1163  *
   1164  * @note The number of bytes copied is the lesser of:
   1165  *
   1166  * @li @c buffer_size(target)
   1167  *
   1168  * @li @c buffer_size(source)
   1169  *
   1170  * This function is implemented in terms of @c memcpy, and consequently it
   1171  * cannot be used to copy between overlapping memory regions.
   1172  */
   1173 inline std::size_t buffer_copy(const mutable_buffer& target,
   1174     const const_buffers_1& source)
   1175 {
   1176   return buffer_copy(target, static_cast<const const_buffer&>(source));
   1177 }
   1178 
   1179 /// Copies bytes from a source buffer to a target buffer.
   1180 /**
   1181  * @param target A modifiable buffer representing the memory region to which
   1182  * the bytes will be copied.
   1183  *
   1184  * @param source A modifiable buffer representing the memory region from which
   1185  * the bytes will be copied. The contents of the source buffer will not be
   1186  * modified.
   1187  *
   1188  * @returns The number of bytes copied.
   1189  *
   1190  * @note The number of bytes copied is the lesser of:
   1191  *
   1192  * @li @c buffer_size(target)
   1193  *
   1194  * @li @c buffer_size(source)
   1195  *
   1196  * This function is implemented in terms of @c memcpy, and consequently it
   1197  * cannot be used to copy between overlapping memory regions.
   1198  */
   1199 inline std::size_t buffer_copy(const mutable_buffer& target,
   1200     const mutable_buffer& source)
   1201 {
   1202   return buffer_copy(target, const_buffer(source));
   1203 }
   1204 
   1205 /// Copies bytes from a source buffer to a target buffer.
   1206 /**
   1207  * @param target A modifiable buffer representing the memory region to which
   1208  * the bytes will be copied.
   1209  *
   1210  * @param source A modifiable buffer representing the memory region from which
   1211  * the bytes will be copied. The contents of the source buffer will not be
   1212  * modified.
   1213  *
   1214  * @returns The number of bytes copied.
   1215  *
   1216  * @note The number of bytes copied is the lesser of:
   1217  *
   1218  * @li @c buffer_size(target)
   1219  *
   1220  * @li @c buffer_size(source)
   1221  *
   1222  * This function is implemented in terms of @c memcpy, and consequently it
   1223  * cannot be used to copy between overlapping memory regions.
   1224  */
   1225 inline std::size_t buffer_copy(const mutable_buffer& target,
   1226     const mutable_buffers_1& source)
   1227 {
   1228   return buffer_copy(target, const_buffer(source));
   1229 }
   1230 
   1231 /// Copies bytes from a source buffer sequence to a target buffer.
   1232 /**
   1233  * @param target A modifiable buffer representing the memory region to which
   1234  * the bytes will be copied.
   1235  *
   1236  * @param source A non-modifiable buffer sequence representing the memory
   1237  * regions from which the bytes will be copied.
   1238  *
   1239  * @returns The number of bytes copied.
   1240  *
   1241  * @note The number of bytes copied is the lesser of:
   1242  *
   1243  * @li @c buffer_size(target)
   1244  *
   1245  * @li @c buffer_size(source)
   1246  *
   1247  * This function is implemented in terms of @c memcpy, and consequently it
   1248  * cannot be used to copy between overlapping memory regions.
   1249  */
   1250 template <typename ConstBufferSequence>
   1251 std::size_t buffer_copy(const mutable_buffer& target,
   1252     const ConstBufferSequence& source)
   1253 {
   1254   std::size_t total_bytes_copied = 0;
   1255 
   1256   typename ConstBufferSequence::const_iterator source_iter = source.begin();
   1257   typename ConstBufferSequence::const_iterator source_end = source.end();
   1258 
   1259   for (mutable_buffer target_buffer(target);
   1260       buffer_size(target_buffer) && source_iter != source_end; ++source_iter)
   1261   {
   1262     const_buffer source_buffer(*source_iter);
   1263     std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
   1264     total_bytes_copied += bytes_copied;
   1265     target_buffer = target_buffer + bytes_copied;
   1266   }
   1267 
   1268   return total_bytes_copied;
   1269 }
   1270 
   1271 /// Copies bytes from a source buffer to a target buffer.
   1272 /**
   1273  * @param target A modifiable buffer representing the memory region to which
   1274  * the bytes will be copied.
   1275  *
   1276  * @param source A non-modifiable buffer representing the memory region from
   1277  * which the bytes will be copied.
   1278  *
   1279  * @returns The number of bytes copied.
   1280  *
   1281  * @note The number of bytes copied is the lesser of:
   1282  *
   1283  * @li @c buffer_size(target)
   1284  *
   1285  * @li @c buffer_size(source)
   1286  *
   1287  * This function is implemented in terms of @c memcpy, and consequently it
   1288  * cannot be used to copy between overlapping memory regions.
   1289  */
   1290 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1291     const const_buffer& source)
   1292 {
   1293   return buffer_copy(static_cast<const mutable_buffer&>(target), source);
   1294 }
   1295 
   1296 /// Copies bytes from a source buffer to a target buffer.
   1297 /**
   1298  * @param target A modifiable buffer representing the memory region to which
   1299  * the bytes will be copied.
   1300  *
   1301  * @param source A non-modifiable buffer representing the memory region from
   1302  * which the bytes will be copied.
   1303  *
   1304  * @returns The number of bytes copied.
   1305  *
   1306  * @note The number of bytes copied is the lesser of:
   1307  *
   1308  * @li @c buffer_size(target)
   1309  *
   1310  * @li @c buffer_size(source)
   1311  *
   1312  * This function is implemented in terms of @c memcpy, and consequently it
   1313  * cannot be used to copy between overlapping memory regions.
   1314  */
   1315 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1316     const const_buffers_1& source)
   1317 {
   1318   return buffer_copy(static_cast<const mutable_buffer&>(target),
   1319       static_cast<const const_buffer&>(source));
   1320 }
   1321 
   1322 /// Copies bytes from a source buffer to a target buffer.
   1323 /**
   1324  * @param target A modifiable buffer representing the memory region to which
   1325  * the bytes will be copied.
   1326  *
   1327  * @param source A modifiable buffer representing the memory region from which
   1328  * the bytes will be copied. The contents of the source buffer will not be
   1329  * modified.
   1330  *
   1331  * @returns The number of bytes copied.
   1332  *
   1333  * @note The number of bytes copied is the lesser of:
   1334  *
   1335  * @li @c buffer_size(target)
   1336  *
   1337  * @li @c buffer_size(source)
   1338  *
   1339  * This function is implemented in terms of @c memcpy, and consequently it
   1340  * cannot be used to copy between overlapping memory regions.
   1341  */
   1342 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1343     const mutable_buffer& source)
   1344 {
   1345   return buffer_copy(static_cast<const mutable_buffer&>(target),
   1346       const_buffer(source));
   1347 }
   1348 
   1349 /// Copies bytes from a source buffer to a target buffer.
   1350 /**
   1351  * @param target A modifiable buffer representing the memory region to which
   1352  * the bytes will be copied.
   1353  *
   1354  * @param source A modifiable buffer representing the memory region from which
   1355  * the bytes will be copied. The contents of the source buffer will not be
   1356  * modified.
   1357  *
   1358  * @returns The number of bytes copied.
   1359  *
   1360  * @note The number of bytes copied is the lesser of:
   1361  *
   1362  * @li @c buffer_size(target)
   1363  *
   1364  * @li @c buffer_size(source)
   1365  *
   1366  * This function is implemented in terms of @c memcpy, and consequently it
   1367  * cannot be used to copy between overlapping memory regions.
   1368  */
   1369 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1370     const mutable_buffers_1& source)
   1371 {
   1372   return buffer_copy(static_cast<const mutable_buffer&>(target),
   1373       const_buffer(source));
   1374 }
   1375 
   1376 /// Copies bytes from a source buffer sequence to a target buffer.
   1377 /**
   1378  * @param target A modifiable buffer representing the memory region to which
   1379  * the bytes will be copied.
   1380  *
   1381  * @param source A non-modifiable buffer sequence representing the memory
   1382  * regions from which the bytes will be copied.
   1383  *
   1384  * @returns The number of bytes copied.
   1385  *
   1386  * @note The number of bytes copied is the lesser of:
   1387  *
   1388  * @li @c buffer_size(target)
   1389  *
   1390  * @li @c buffer_size(source)
   1391  *
   1392  * This function is implemented in terms of @c memcpy, and consequently it
   1393  * cannot be used to copy between overlapping memory regions.
   1394  */
   1395 template <typename ConstBufferSequence>
   1396 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1397     const ConstBufferSequence& source)
   1398 {
   1399   return buffer_copy(static_cast<const mutable_buffer&>(target), source);
   1400 }
   1401 
   1402 /// Copies bytes from a source buffer to a target buffer sequence.
   1403 /**
   1404  * @param target A modifiable buffer sequence representing the memory regions to
   1405  * which the bytes will be copied.
   1406  *
   1407  * @param source A non-modifiable buffer representing the memory region from
   1408  * which the bytes will be copied.
   1409  *
   1410  * @returns The number of bytes copied.
   1411  *
   1412  * @note The number of bytes copied is the lesser of:
   1413  *
   1414  * @li @c buffer_size(target)
   1415  *
   1416  * @li @c buffer_size(source)
   1417  *
   1418  * This function is implemented in terms of @c memcpy, and consequently it
   1419  * cannot be used to copy between overlapping memory regions.
   1420  */
   1421 template <typename MutableBufferSequence>
   1422 std::size_t buffer_copy(const MutableBufferSequence& target,
   1423     const const_buffer& source)
   1424 {
   1425   std::size_t total_bytes_copied = 0;
   1426 
   1427   typename MutableBufferSequence::const_iterator target_iter = target.begin();
   1428   typename MutableBufferSequence::const_iterator target_end = target.end();
   1429 
   1430   for (const_buffer source_buffer(source);
   1431       buffer_size(source_buffer) && target_iter != target_end; ++target_iter)
   1432   {
   1433     mutable_buffer target_buffer(*target_iter);
   1434     std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
   1435     total_bytes_copied += bytes_copied;
   1436     source_buffer = source_buffer + bytes_copied;
   1437   }
   1438 
   1439   return total_bytes_copied;
   1440 }
   1441 
   1442 /// Copies bytes from a source buffer to a target buffer sequence.
   1443 /**
   1444  * @param target A modifiable buffer sequence representing the memory regions to
   1445  * which the bytes will be copied.
   1446  *
   1447  * @param source A non-modifiable buffer representing the memory region from
   1448  * which the bytes will be copied.
   1449  *
   1450  * @returns The number of bytes copied.
   1451  *
   1452  * @note The number of bytes copied is the lesser of:
   1453  *
   1454  * @li @c buffer_size(target)
   1455  *
   1456  * @li @c buffer_size(source)
   1457  *
   1458  * This function is implemented in terms of @c memcpy, and consequently it
   1459  * cannot be used to copy between overlapping memory regions.
   1460  */
   1461 template <typename MutableBufferSequence>
   1462 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1463     const const_buffers_1& source)
   1464 {
   1465   return buffer_copy(target, static_cast<const const_buffer&>(source));
   1466 }
   1467 
   1468 /// Copies bytes from a source buffer to a target buffer sequence.
   1469 /**
   1470  * @param target A modifiable buffer sequence representing the memory regions to
   1471  * which the bytes will be copied.
   1472  *
   1473  * @param source A modifiable buffer representing the memory region from which
   1474  * the bytes will be copied. The contents of the source buffer will not be
   1475  * modified.
   1476  *
   1477  * @returns The number of bytes copied.
   1478  *
   1479  * @note The number of bytes copied is the lesser of:
   1480  *
   1481  * @li @c buffer_size(target)
   1482  *
   1483  * @li @c buffer_size(source)
   1484  *
   1485  * This function is implemented in terms of @c memcpy, and consequently it
   1486  * cannot be used to copy between overlapping memory regions.
   1487  */
   1488 template <typename MutableBufferSequence>
   1489 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1490     const mutable_buffer& source)
   1491 {
   1492   return buffer_copy(target, const_buffer(source));
   1493 }
   1494 
   1495 /// Copies bytes from a source buffer to a target buffer sequence.
   1496 /**
   1497  * @param target A modifiable buffer sequence representing the memory regions to
   1498  * which the bytes will be copied.
   1499  *
   1500  * @param source A modifiable buffer representing the memory region from which
   1501  * the bytes will be copied. The contents of the source buffer will not be
   1502  * modified.
   1503  *
   1504  * @returns The number of bytes copied.
   1505  *
   1506  * @note The number of bytes copied is the lesser of:
   1507  *
   1508  * @li @c buffer_size(target)
   1509  *
   1510  * @li @c buffer_size(source)
   1511  *
   1512  * This function is implemented in terms of @c memcpy, and consequently it
   1513  * cannot be used to copy between overlapping memory regions.
   1514  */
   1515 template <typename MutableBufferSequence>
   1516 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1517     const mutable_buffers_1& source)
   1518 {
   1519   return buffer_copy(target, const_buffer(source));
   1520 }
   1521 
   1522 /// Copies bytes from a source buffer sequence to a target buffer sequence.
   1523 /**
   1524  * @param target A modifiable buffer sequence representing the memory regions to
   1525  * which the bytes will be copied.
   1526  *
   1527  * @param source A non-modifiable buffer sequence representing the memory
   1528  * regions from which the bytes will be copied.
   1529  *
   1530  * @returns The number of bytes copied.
   1531  *
   1532  * @note The number of bytes copied is the lesser of:
   1533  *
   1534  * @li @c buffer_size(target)
   1535  *
   1536  * @li @c buffer_size(source)
   1537  *
   1538  * This function is implemented in terms of @c memcpy, and consequently it
   1539  * cannot be used to copy between overlapping memory regions.
   1540  */
   1541 template <typename MutableBufferSequence, typename ConstBufferSequence>
   1542 std::size_t buffer_copy(const MutableBufferSequence& target,
   1543     const ConstBufferSequence& source)
   1544 {
   1545   std::size_t total_bytes_copied = 0;
   1546 
   1547   typename MutableBufferSequence::const_iterator target_iter = target.begin();
   1548   typename MutableBufferSequence::const_iterator target_end = target.end();
   1549   std::size_t target_buffer_offset = 0;
   1550 
   1551   typename ConstBufferSequence::const_iterator source_iter = source.begin();
   1552   typename ConstBufferSequence::const_iterator source_end = source.end();
   1553   std::size_t source_buffer_offset = 0;
   1554 
   1555   while (target_iter != target_end && source_iter != source_end)
   1556   {
   1557     mutable_buffer target_buffer =
   1558       mutable_buffer(*target_iter) + target_buffer_offset;
   1559 
   1560     const_buffer source_buffer =
   1561       const_buffer(*source_iter) + source_buffer_offset;
   1562 
   1563     std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
   1564     total_bytes_copied += bytes_copied;
   1565 
   1566     if (bytes_copied == buffer_size(target_buffer))
   1567     {
   1568       ++target_iter;
   1569       target_buffer_offset = 0;
   1570     }
   1571     else
   1572       target_buffer_offset += bytes_copied;
   1573 
   1574     if (bytes_copied == buffer_size(source_buffer))
   1575     {
   1576       ++source_iter;
   1577       source_buffer_offset = 0;
   1578     }
   1579     else
   1580       source_buffer_offset += bytes_copied;
   1581   }
   1582 
   1583   return total_bytes_copied;
   1584 }
   1585 
   1586 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1587 /**
   1588  * @param target A modifiable buffer representing the memory region to which
   1589  * the bytes will be copied.
   1590  *
   1591  * @param source A non-modifiable buffer representing the memory region from
   1592  * which the bytes will be copied.
   1593  *
   1594  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1595  *
   1596  * @returns The number of bytes copied.
   1597  *
   1598  * @note The number of bytes copied is the lesser of:
   1599  *
   1600  * @li @c buffer_size(target)
   1601  *
   1602  * @li @c buffer_size(source)
   1603  *
   1604  * @li @c max_bytes_to_copy
   1605  *
   1606  * This function is implemented in terms of @c memcpy, and consequently it
   1607  * cannot be used to copy between overlapping memory regions.
   1608  */
   1609 inline std::size_t buffer_copy(const mutable_buffer& target,
   1610     const const_buffer& source, std::size_t max_bytes_to_copy)
   1611 {
   1612   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1613 }
   1614 
   1615 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1616 /**
   1617  * @param target A modifiable buffer representing the memory region to which
   1618  * the bytes will be copied.
   1619  *
   1620  * @param source A non-modifiable buffer representing the memory region from
   1621  * which the bytes will be copied.
   1622  *
   1623  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1624  *
   1625  * @returns The number of bytes copied.
   1626  *
   1627  * @note The number of bytes copied is the lesser of:
   1628  *
   1629  * @li @c buffer_size(target)
   1630  *
   1631  * @li @c buffer_size(source)
   1632  *
   1633  * @li @c max_bytes_to_copy
   1634  *
   1635  * This function is implemented in terms of @c memcpy, and consequently it
   1636  * cannot be used to copy between overlapping memory regions.
   1637  */
   1638 inline std::size_t buffer_copy(const mutable_buffer& target,
   1639     const const_buffers_1& source, std::size_t max_bytes_to_copy)
   1640 {
   1641   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1642 }
   1643 
   1644 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1645 /**
   1646  * @param target A modifiable buffer representing the memory region to which
   1647  * the bytes will be copied.
   1648  *
   1649  * @param source A modifiable buffer representing the memory region from which
   1650  * the bytes will be copied. The contents of the source buffer will not be
   1651  * modified.
   1652  *
   1653  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1654  *
   1655  * @returns The number of bytes copied.
   1656  *
   1657  * @note The number of bytes copied is the lesser of:
   1658  *
   1659  * @li @c buffer_size(target)
   1660  *
   1661  * @li @c buffer_size(source)
   1662  *
   1663  * @li @c max_bytes_to_copy
   1664  *
   1665  * This function is implemented in terms of @c memcpy, and consequently it
   1666  * cannot be used to copy between overlapping memory regions.
   1667  */
   1668 inline std::size_t buffer_copy(const mutable_buffer& target,
   1669     const mutable_buffer& source, std::size_t max_bytes_to_copy)
   1670 {
   1671   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1672 }
   1673 
   1674 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1675 /**
   1676  * @param target A modifiable buffer representing the memory region to which
   1677  * the bytes will be copied.
   1678  *
   1679  * @param source A modifiable buffer representing the memory region from which
   1680  * the bytes will be copied. The contents of the source buffer will not be
   1681  * modified.
   1682  *
   1683  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1684  *
   1685  * @returns The number of bytes copied.
   1686  *
   1687  * @note The number of bytes copied is the lesser of:
   1688  *
   1689  * @li @c buffer_size(target)
   1690  *
   1691  * @li @c buffer_size(source)
   1692  *
   1693  * @li @c max_bytes_to_copy
   1694  *
   1695  * This function is implemented in terms of @c memcpy, and consequently it
   1696  * cannot be used to copy between overlapping memory regions.
   1697  */
   1698 inline std::size_t buffer_copy(const mutable_buffer& target,
   1699     const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
   1700 {
   1701   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1702 }
   1703 
   1704 /// Copies a limited number of bytes from a source buffer sequence to a target
   1705 /// buffer.
   1706 /**
   1707  * @param target A modifiable buffer representing the memory region to which
   1708  * the bytes will be copied.
   1709  *
   1710  * @param source A non-modifiable buffer sequence representing the memory
   1711  * regions from which the bytes will be copied.
   1712  *
   1713  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1714  *
   1715  * @returns The number of bytes copied.
   1716  *
   1717  * @note The number of bytes copied is the lesser of:
   1718  *
   1719  * @li @c buffer_size(target)
   1720  *
   1721  * @li @c buffer_size(source)
   1722  *
   1723  * @li @c max_bytes_to_copy
   1724  *
   1725  * This function is implemented in terms of @c memcpy, and consequently it
   1726  * cannot be used to copy between overlapping memory regions.
   1727  */
   1728 template <typename ConstBufferSequence>
   1729 inline std::size_t buffer_copy(const mutable_buffer& target,
   1730     const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
   1731 {
   1732   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1733 }
   1734 
   1735 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1736 /**
   1737  * @param target A modifiable buffer representing the memory region to which
   1738  * the bytes will be copied.
   1739  *
   1740  * @param source A non-modifiable buffer representing the memory region from
   1741  * which the bytes will be copied.
   1742  *
   1743  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1744  *
   1745  * @returns The number of bytes copied.
   1746  *
   1747  * @note The number of bytes copied is the lesser of:
   1748  *
   1749  * @li @c buffer_size(target)
   1750  *
   1751  * @li @c buffer_size(source)
   1752  *
   1753  * @li @c max_bytes_to_copy
   1754  *
   1755  * This function is implemented in terms of @c memcpy, and consequently it
   1756  * cannot be used to copy between overlapping memory regions.
   1757  */
   1758 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1759     const const_buffer& source, std::size_t max_bytes_to_copy)
   1760 {
   1761   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1762 }
   1763 
   1764 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1765 /**
   1766  * @param target A modifiable buffer representing the memory region to which
   1767  * the bytes will be copied.
   1768  *
   1769  * @param source A non-modifiable buffer representing the memory region from
   1770  * which the bytes will be copied.
   1771  *
   1772  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1773  *
   1774  * @returns The number of bytes copied.
   1775  *
   1776  * @note The number of bytes copied is the lesser of:
   1777  *
   1778  * @li @c buffer_size(target)
   1779  *
   1780  * @li @c buffer_size(source)
   1781  *
   1782  * @li @c max_bytes_to_copy
   1783  *
   1784  * This function is implemented in terms of @c memcpy, and consequently it
   1785  * cannot be used to copy between overlapping memory regions.
   1786  */
   1787 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1788     const const_buffers_1& source, std::size_t max_bytes_to_copy)
   1789 {
   1790   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1791 }
   1792 
   1793 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1794 /**
   1795  * @param target A modifiable buffer representing the memory region to which
   1796  * the bytes will be copied.
   1797  *
   1798  * @param source A modifiable buffer representing the memory region from which
   1799  * the bytes will be copied. The contents of the source buffer will not be
   1800  * modified.
   1801  *
   1802  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1803  *
   1804  * @returns The number of bytes copied.
   1805  *
   1806  * @note The number of bytes copied is the lesser of:
   1807  *
   1808  * @li @c buffer_size(target)
   1809  *
   1810  * @li @c buffer_size(source)
   1811  *
   1812  * @li @c max_bytes_to_copy
   1813  *
   1814  * This function is implemented in terms of @c memcpy, and consequently it
   1815  * cannot be used to copy between overlapping memory regions.
   1816  */
   1817 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1818     const mutable_buffer& source, std::size_t max_bytes_to_copy)
   1819 {
   1820   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1821 }
   1822 
   1823 /// Copies a limited number of bytes from a source buffer to a target buffer.
   1824 /**
   1825  * @param target A modifiable buffer representing the memory region to which
   1826  * the bytes will be copied.
   1827  *
   1828  * @param source A modifiable buffer representing the memory region from which
   1829  * the bytes will be copied. The contents of the source buffer will not be
   1830  * modified.
   1831  *
   1832  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1833  *
   1834  * @returns The number of bytes copied.
   1835  *
   1836  * @note The number of bytes copied is the lesser of:
   1837  *
   1838  * @li @c buffer_size(target)
   1839  *
   1840  * @li @c buffer_size(source)
   1841  *
   1842  * @li @c max_bytes_to_copy
   1843  *
   1844  * This function is implemented in terms of @c memcpy, and consequently it
   1845  * cannot be used to copy between overlapping memory regions.
   1846  */
   1847 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1848     const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
   1849 {
   1850   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1851 }
   1852 
   1853 /// Copies a limited number of bytes from a source buffer sequence to a target
   1854 /// buffer.
   1855 /**
   1856  * @param target A modifiable buffer representing the memory region to which
   1857  * the bytes will be copied.
   1858  *
   1859  * @param source A non-modifiable buffer sequence representing the memory
   1860  * regions from which the bytes will be copied.
   1861  *
   1862  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1863  *
   1864  * @returns The number of bytes copied.
   1865  *
   1866  * @note The number of bytes copied is the lesser of:
   1867  *
   1868  * @li @c buffer_size(target)
   1869  *
   1870  * @li @c buffer_size(source)
   1871  *
   1872  * @li @c max_bytes_to_copy
   1873  *
   1874  * This function is implemented in terms of @c memcpy, and consequently it
   1875  * cannot be used to copy between overlapping memory regions.
   1876  */
   1877 template <typename ConstBufferSequence>
   1878 inline std::size_t buffer_copy(const mutable_buffers_1& target,
   1879     const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
   1880 {
   1881   return buffer_copy(buffer(target, max_bytes_to_copy), source);
   1882 }
   1883 
   1884 /// Copies a limited number of bytes from a source buffer to a target buffer
   1885 /// sequence.
   1886 /**
   1887  * @param target A modifiable buffer sequence representing the memory regions to
   1888  * which the bytes will be copied.
   1889  *
   1890  * @param source A non-modifiable buffer representing the memory region from
   1891  * which the bytes will be copied.
   1892  *
   1893  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1894  *
   1895  * @returns The number of bytes copied.
   1896  *
   1897  * @note The number of bytes copied is the lesser of:
   1898  *
   1899  * @li @c buffer_size(target)
   1900  *
   1901  * @li @c buffer_size(source)
   1902  *
   1903  * @li @c max_bytes_to_copy
   1904  *
   1905  * This function is implemented in terms of @c memcpy, and consequently it
   1906  * cannot be used to copy between overlapping memory regions.
   1907  */
   1908 template <typename MutableBufferSequence>
   1909 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1910     const const_buffer& source, std::size_t max_bytes_to_copy)
   1911 {
   1912   return buffer_copy(target, buffer(source, max_bytes_to_copy));
   1913 }
   1914 
   1915 /// Copies a limited number of bytes from a source buffer to a target buffer
   1916 /// sequence.
   1917 /**
   1918  * @param target A modifiable buffer sequence representing the memory regions to
   1919  * which the bytes will be copied.
   1920  *
   1921  * @param source A non-modifiable buffer representing the memory region from
   1922  * which the bytes will be copied.
   1923  *
   1924  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1925  *
   1926  * @returns The number of bytes copied.
   1927  *
   1928  * @note The number of bytes copied is the lesser of:
   1929  *
   1930  * @li @c buffer_size(target)
   1931  *
   1932  * @li @c buffer_size(source)
   1933  *
   1934  * @li @c max_bytes_to_copy
   1935  *
   1936  * This function is implemented in terms of @c memcpy, and consequently it
   1937  * cannot be used to copy between overlapping memory regions.
   1938  */
   1939 template <typename MutableBufferSequence>
   1940 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1941     const const_buffers_1& source, std::size_t max_bytes_to_copy)
   1942 {
   1943   return buffer_copy(target, buffer(source, max_bytes_to_copy));
   1944 }
   1945 
   1946 /// Copies a limited number of bytes from a source buffer to a target buffer
   1947 /// sequence.
   1948 /**
   1949  * @param target A modifiable buffer sequence representing the memory regions to
   1950  * which the bytes will be copied.
   1951  *
   1952  * @param source A modifiable buffer representing the memory region from which
   1953  * the bytes will be copied. The contents of the source buffer will not be
   1954  * modified.
   1955  *
   1956  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1957  *
   1958  * @returns The number of bytes copied.
   1959  *
   1960  * @note The number of bytes copied is the lesser of:
   1961  *
   1962  * @li @c buffer_size(target)
   1963  *
   1964  * @li @c buffer_size(source)
   1965  *
   1966  * @li @c max_bytes_to_copy
   1967  *
   1968  * This function is implemented in terms of @c memcpy, and consequently it
   1969  * cannot be used to copy between overlapping memory regions.
   1970  */
   1971 template <typename MutableBufferSequence>
   1972 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   1973     const mutable_buffer& source, std::size_t max_bytes_to_copy)
   1974 {
   1975   return buffer_copy(target, buffer(source, max_bytes_to_copy));
   1976 }
   1977 
   1978 /// Copies a limited number of bytes from a source buffer to a target buffer
   1979 /// sequence.
   1980 /**
   1981  * @param target A modifiable buffer sequence representing the memory regions to
   1982  * which the bytes will be copied.
   1983  *
   1984  * @param source A modifiable buffer representing the memory region from which
   1985  * the bytes will be copied. The contents of the source buffer will not be
   1986  * modified.
   1987  *
   1988  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   1989  *
   1990  * @returns The number of bytes copied.
   1991  *
   1992  * @note The number of bytes copied is the lesser of:
   1993  *
   1994  * @li @c buffer_size(target)
   1995  *
   1996  * @li @c buffer_size(source)
   1997  *
   1998  * @li @c max_bytes_to_copy
   1999  *
   2000  * This function is implemented in terms of @c memcpy, and consequently it
   2001  * cannot be used to copy between overlapping memory regions.
   2002  */
   2003 template <typename MutableBufferSequence>
   2004 inline std::size_t buffer_copy(const MutableBufferSequence& target,
   2005     const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
   2006 {
   2007   return buffer_copy(target, buffer(source, max_bytes_to_copy));
   2008 }
   2009 
   2010 /// Copies a limited number of bytes from a source buffer sequence to a target
   2011 /// buffer sequence.
   2012 /**
   2013  * @param target A modifiable buffer sequence representing the memory regions to
   2014  * which the bytes will be copied.
   2015  *
   2016  * @param source A non-modifiable buffer sequence representing the memory
   2017  * regions from which the bytes will be copied.
   2018  *
   2019  * @param max_bytes_to_copy The maximum number of bytes to be copied.
   2020  *
   2021  * @returns The number of bytes copied.
   2022  *
   2023  * @note The number of bytes copied is the lesser of:
   2024  *
   2025  * @li @c buffer_size(target)
   2026  *
   2027  * @li @c buffer_size(source)
   2028  *
   2029  * @li @c max_bytes_to_copy
   2030  *
   2031  * This function is implemented in terms of @c memcpy, and consequently it
   2032  * cannot be used to copy between overlapping memory regions.
   2033  */
   2034 template <typename MutableBufferSequence, typename ConstBufferSequence>
   2035 std::size_t buffer_copy(const MutableBufferSequence& target,
   2036     const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
   2037 {
   2038   std::size_t total_bytes_copied = 0;
   2039 
   2040   typename MutableBufferSequence::const_iterator target_iter = target.begin();
   2041   typename MutableBufferSequence::const_iterator target_end = target.end();
   2042   std::size_t target_buffer_offset = 0;
   2043 
   2044   typename ConstBufferSequence::const_iterator source_iter = source.begin();
   2045   typename ConstBufferSequence::const_iterator source_end = source.end();
   2046   std::size_t source_buffer_offset = 0;
   2047 
   2048   while (total_bytes_copied != max_bytes_to_copy
   2049       && target_iter != target_end && source_iter != source_end)
   2050   {
   2051     mutable_buffer target_buffer =
   2052       mutable_buffer(*target_iter) + target_buffer_offset;
   2053 
   2054     const_buffer source_buffer =
   2055       const_buffer(*source_iter) + source_buffer_offset;
   2056 
   2057     std::size_t bytes_copied = buffer_copy(target_buffer,
   2058         source_buffer, max_bytes_to_copy - total_bytes_copied);
   2059     total_bytes_copied += bytes_copied;
   2060 
   2061     if (bytes_copied == buffer_size(target_buffer))
   2062     {
   2063       ++target_iter;
   2064       target_buffer_offset = 0;
   2065     }
   2066     else
   2067       target_buffer_offset += bytes_copied;
   2068 
   2069     if (bytes_copied == buffer_size(source_buffer))
   2070     {
   2071       ++source_iter;
   2072       source_buffer_offset = 0;
   2073     }
   2074     else
   2075       source_buffer_offset += bytes_copied;
   2076   }
   2077 
   2078   return total_bytes_copied;
   2079 }
   2080 
   2081 /*@}*/
   2082 
   2083 } // namespace asio
   2084 
   2085 #include "asio/detail/pop_options.hpp"
   2086 
   2087 #endif // ASIO_BUFFER_HPP
   2088