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