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
36namespace asio {
37
38class mutable_buffer;
39class const_buffer;
40
41namespace detail {
42void* buffer_cast_helper(const mutable_buffer&);
43const void* buffer_cast_helper(const const_buffer&);
44std::size_t buffer_size_helper(const mutable_buffer&);
45std::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 */
67class mutable_buffer
68{
69public:
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
85private:
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
96namespace detail {
97
98inline void* buffer_cast_helper(const mutable_buffer& b)
99{
100  return b.data_;
101}
102
103inline 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.
112class mutable_buffers_1
113  : public mutable_buffer
114{
115public:
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 */
166class const_buffer
167{
168public:
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
191private:
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
202namespace detail {
203
204inline const void* buffer_cast_helper(const const_buffer& b)
205{
206  return b.data_;
207}
208
209inline 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.
218class const_buffers_1
219  : public const_buffer
220{
221public:
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.
255class null_buffers
256{
257public:
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
276private:
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.
288inline 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.
294inline 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.
300inline 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.
306inline 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 */
316template <typename BufferSequence>
317inline 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.
354template <typename PointerToPodType>
355inline 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.
361template <typename PointerToPodType>
362inline 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 */
373inline 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 */
387inline 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 */
401inline 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 */
415inline 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 */
592inline 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 */
604inline 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 */
618inline 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 */
630inline 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 */
644inline 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 */
653inline 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 */
666template <typename PodType, std::size_t N>
667inline 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 */
679template <typename PodType, std::size_t N>
680inline 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 */
696template <typename PodType, std::size_t N>
697inline 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 */
709template <typename PodType, std::size_t N>
710inline 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
733namespace detail {
734
735template <bool IsConst>
736struct buffer_types_base;
737
738template <>
739struct buffer_types_base<false>
740{
741  typedef mutable_buffer buffer_type;
742  typedef mutable_buffers_1 container_type;
743};
744
745template <>
746struct buffer_types_base<true>
747{
748  typedef const_buffer buffer_type;
749  typedef const_buffers_1 container_type;
750};
751
752template <typename PodType>
753struct buffer_types
754  : public buffer_types_base<is_const<PodType>::value>
755{
756};
757
758} // namespace detail
759
760template <typename PodType, std::size_t N>
761inline typename detail::buffer_types<PodType>::container_type
762buffer(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
772template <typename PodType, std::size_t N>
773inline typename detail::buffer_types<PodType>::container_type
774buffer(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 */
795template <typename PodType, std::size_t N>
796inline 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 */
809template <typename PodType, std::size_t N>
810inline 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 */
826template <typename PodType, std::size_t N>
827inline 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 */
840template <typename PodType, std::size_t N>
841inline 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 */
859template <typename PodType, std::size_t N>
860inline 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 */
873template <typename PodType, std::size_t N>
874inline 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 */
891template <typename PodType, std::size_t N>
892inline 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 */
905template <typename PodType, std::size_t N>
906inline 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 */
922template <typename PodType, std::size_t N>
923inline 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 */
936template <typename PodType, std::size_t N>
937inline 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 */
953template <typename PodType, std::size_t N>
954inline 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 */
967template <typename PodType, std::size_t N>
968inline 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 */
988template <typename PodType, typename Allocator>
989inline 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 */
1006template <typename PodType, typename Allocator>
1007inline 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 */
1027template <typename PodType, typename Allocator>
1028inline 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 */
1046template <typename PodType, typename Allocator>
1047inline 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 */
1064template <typename Elem, typename Traits, typename Allocator>
1065inline 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 */
1082template <typename Elem, typename Traits, typename Allocator>
1083inline 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 */
1143inline 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 */
1173inline 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 */
1199inline 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 */
1225inline 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 */
1250template <typename ConstBufferSequence>
1251std::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 */
1290inline 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 */
1315inline 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 */
1342inline 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 */
1369inline 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 */
1395template <typename ConstBufferSequence>
1396inline 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 */
1421template <typename MutableBufferSequence>
1422std::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 */
1461template <typename MutableBufferSequence>
1462inline 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 */
1488template <typename MutableBufferSequence>
1489inline 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 */
1515template <typename MutableBufferSequence>
1516inline 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 */
1541template <typename MutableBufferSequence, typename ConstBufferSequence>
1542std::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 */
1609inline 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 */
1638inline 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 */
1668inline 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 */
1698inline 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 */
1728template <typename ConstBufferSequence>
1729inline 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 */
1758inline 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 */
1787inline 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 */
1817inline 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 */
1847inline 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 */
1877template <typename ConstBufferSequence>
1878inline 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 */
1908template <typename MutableBufferSequence>
1909inline 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 */
1939template <typename MutableBufferSequence>
1940inline 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 */
1971template <typename MutableBufferSequence>
1972inline 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 */
2003template <typename MutableBufferSequence>
2004inline 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 */
2034template <typename MutableBufferSequence, typename ConstBufferSequence>
2035std::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