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.
mutable_buffer()71   mutable_buffer()
72     : data_(0),
73       size_(0)
74   {
75   }
76 
77   /// Construct a buffer to represent a given memory range.
mutable_buffer(void * data,std::size_t size)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 
buffer_cast_helper(const mutable_buffer & b)98 inline void* buffer_cast_helper(const mutable_buffer& b)
99 {
100   return b.data_;
101 }
102 
buffer_size_helper(const mutable_buffer & b)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.
mutable_buffers_1(void * data,std::size_t size)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.
mutable_buffers_1(const mutable_buffer & b)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.
begin() const135   const_iterator begin() const
136   {
137     return this;
138   }
139 
140   /// Get a random-access iterator for one past the last element.
end() const141   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.
const_buffer()170   const_buffer()
171     : data_(0),
172       size_(0)
173   {
174   }
175 
176   /// Construct a buffer to represent a given memory range.
const_buffer(const void * data,std::size_t size)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.
const_buffer(const mutable_buffer & b)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 
buffer_cast_helper(const const_buffer & b)204 inline const void* buffer_cast_helper(const const_buffer& b)
205 {
206   return b.data_;
207 }
208 
buffer_size_helper(const const_buffer & b)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.
const_buffers_1(const void * data,std::size_t size)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.
const_buffers_1(const const_buffer & b)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.
begin() const241   const_iterator begin() const
242   {
243     return this;
244   }
245 
246   /// Get a random-access iterator for one past the last element.
end() const247   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.
begin() const265   const_iterator begin() const
266   {
267     return &buf_;
268   }
269 
270   /// Get a random-access iterator for one past the last element.
end() const271   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.
buffer_size(const mutable_buffer & b)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.
buffer_size(const mutable_buffers_1 & b)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.
buffer_size(const const_buffer & b)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.
buffer_size(const const_buffers_1 & b)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>
buffer_size(const BufferSequence & b)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>
buffer_cast(const mutable_buffer & b)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>
buffer_cast(const const_buffer & b)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  */
operator +(const mutable_buffer & b,std::size_t start)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  */
operator +(std::size_t start,const mutable_buffer & b)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  */
operator +(const const_buffer & b,std::size_t start)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  */
operator +(std::size_t start,const const_buffer & b)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  */
buffer(const mutable_buffer & b)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  */
buffer(const mutable_buffer & b,std::size_t max_size_in_bytes)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  */
buffer(const const_buffer & b)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  */
buffer(const const_buffer & b,std::size_t max_size_in_bytes)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  */
buffer(void * data,std::size_t size_in_bytes)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  */
buffer(const void * data,std::size_t size_in_bytes)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>
buffer(PodType (& data)[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>
buffer(PodType (& data)[N],std::size_t max_size_in_bytes)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>
buffer(const PodType (& data)[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>
buffer(const PodType (& data)[N],std::size_t max_size_in_bytes)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
buffer(boost::array<PodType,N> & data)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
buffer(boost::array<PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(boost::array<PodType,N> & data)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>
buffer(boost::array<PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(boost::array<const PodType,N> & data)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>
buffer(boost::array<const PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(const boost::array<PodType,N> & data)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>
buffer(const boost::array<PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(std::array<PodType,N> & data)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>
buffer(std::array<PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(std::array<const PodType,N> & data)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>
buffer(std::array<const PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(const std::array<PodType,N> & data)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>
buffer(const std::array<PodType,N> & data,std::size_t max_size_in_bytes)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>
buffer(std::vector<PodType,Allocator> & data)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>
buffer(std::vector<PodType,Allocator> & data,std::size_t max_size_in_bytes)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>
buffer(const std::vector<PodType,Allocator> & data)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>
buffer(const std::vector<PodType,Allocator> & data,std::size_t max_size_in_bytes)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>
buffer(const std::basic_string<Elem,Traits,Allocator> & data)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>
buffer(const std::basic_string<Elem,Traits,Allocator> & data,std::size_t max_size_in_bytes)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  */
buffer_copy(const mutable_buffer & target,const const_buffer & source)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  */
buffer_copy(const mutable_buffer & target,const const_buffers_1 & source)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  */
buffer_copy(const mutable_buffer & target,const mutable_buffer & source)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  */
buffer_copy(const mutable_buffer & target,const mutable_buffers_1 & source)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>
buffer_copy(const mutable_buffer & target,const ConstBufferSequence & source)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  */
buffer_copy(const mutable_buffers_1 & target,const const_buffer & source)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  */
buffer_copy(const mutable_buffers_1 & target,const const_buffers_1 & source)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  */
buffer_copy(const mutable_buffers_1 & target,const mutable_buffer & source)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  */
buffer_copy(const mutable_buffers_1 & target,const mutable_buffers_1 & source)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>
buffer_copy(const mutable_buffers_1 & target,const ConstBufferSequence & source)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>
buffer_copy(const MutableBufferSequence & target,const const_buffer & source)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>
buffer_copy(const MutableBufferSequence & target,const const_buffers_1 & source)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>
buffer_copy(const MutableBufferSequence & target,const mutable_buffer & source)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>
buffer_copy(const MutableBufferSequence & target,const mutable_buffers_1 & source)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>
buffer_copy(const MutableBufferSequence & target,const ConstBufferSequence & source)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  */
buffer_copy(const mutable_buffer & target,const const_buffer & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffer & target,const const_buffers_1 & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffer & target,const mutable_buffer & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffer & target,const mutable_buffers_1 & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const mutable_buffer & target,const ConstBufferSequence & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffers_1 & target,const const_buffer & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffers_1 & target,const const_buffers_1 & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffers_1 & target,const mutable_buffer & source,std::size_t max_bytes_to_copy)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  */
buffer_copy(const mutable_buffers_1 & target,const mutable_buffers_1 & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const mutable_buffers_1 & target,const ConstBufferSequence & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const MutableBufferSequence & target,const const_buffer & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const MutableBufferSequence & target,const const_buffers_1 & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const MutableBufferSequence & target,const mutable_buffer & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const MutableBufferSequence & target,const mutable_buffers_1 & source,std::size_t max_bytes_to_copy)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>
buffer_copy(const MutableBufferSequence & target,const ConstBufferSequence & source,std::size_t max_bytes_to_copy)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