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
60namespace boost {
61namespace asio {
62
63class mutable_buffer;
64class const_buffer;
65
66namespace detail {
67void* buffer_cast_helper(const mutable_buffer&);
68const void* buffer_cast_helper(const const_buffer&);
69std::size_t buffer_size_helper(const mutable_buffer&);
70std::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 */
92class mutable_buffer
93{
94public:
95 /// Construct an empty buffer.
96 mutable_buffer()
97 : data_(0),
98 size_(0)
99 {
100 }
101
102 /// Construct a buffer to represent a given memory range.
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)
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
118 const boost::asio::detail::function<void()>& get_debug_check() const
119 {
120 return debug_check_;
121 }
122#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
123
124private:
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
138namespace detail {
139
140inline 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
149inline 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.
158class mutable_buffers_1
159 : public mutable_buffer
160{
161public:
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.
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.
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.
181 const_iterator begin() const
182 {
183 return this;
184 }
185
186 /// Get a random-access iterator for one past the last element.
187 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 */
212class const_buffer
213{
214public:
215 /// Construct an empty buffer.
216 const_buffer()
217 : data_(0),
218 size_(0)
219 {
220 }
221
222 /// Construct a buffer to represent a given memory range.
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.
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)
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
248 const boost::asio::detail::function<void()>& get_debug_check() const
249 {
250 return debug_check_;
251 }
252#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
253
254private:
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
268namespace detail {
269
270inline 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
279inline 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.
288class const_buffers_1
289 : public const_buffer
290{
291public:
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.
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.
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.
311 const_iterator begin() const
312 {
313 return this;
314 }
315
316 /// Get a random-access iterator for one past the last element.
317 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.
325class null_buffers
326{
327public:
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.
335 const_iterator begin() const
336 {
337 return &buf_;
338 }
339
340 /// Get a random-access iterator for one past the last element.
341 const_iterator end() const
342 {
343 return &buf_;
344 }
345
346private:
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.
358inline 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.
364inline 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.
370inline 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.
376inline 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 */
386template <typename BufferSequence>
387inline 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.
424template <typename PointerToPodType>
425inline 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.
431template <typename PointerToPodType>
432inline 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 */
443inline 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 */
460inline 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 */
477inline 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 */
494inline 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)
508namespace detail {
509
510template <typename Iterator>
511class buffer_debug_check
512{
513public:
514 buffer_debug_check(Iterator iter)
515 : iter_(iter)
516 {
517 }
518
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
529 void operator()()
530 {
531 *iter_;
532 }
533
534private:
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 */
707inline 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 */
719inline 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 */
736inline 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 */
748inline 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 */
765inline 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 */
774inline 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 */
787template <typename PodType, std::size_t N>
788inline 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 */
800template <typename PodType, std::size_t N>
801inline 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 */
817template <typename PodType, std::size_t N>
818inline 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 */
830template <typename PodType, std::size_t N>
831inline 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
854namespace detail {
855
856template <bool IsConst>
857struct buffer_types_base;
858
859template <>
860struct buffer_types_base<false>
861{
862 typedef mutable_buffer buffer_type;
863 typedef mutable_buffers_1 container_type;
864};
865
866template <>
867struct buffer_types_base<true>
868{
869 typedef const_buffer buffer_type;
870 typedef const_buffers_1 container_type;
871};
872
873template <typename PodType>
874struct buffer_types
875 : public buffer_types_base<is_const<PodType>::value>
876{
877};
878
879} // namespace detail
880
881template <typename PodType, std::size_t N>
882inline typename detail::buffer_types<PodType>::container_type
883buffer(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
893template <typename PodType, std::size_t N>
894inline typename detail::buffer_types<PodType>::container_type
895buffer(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 */
916template <typename PodType, std::size_t N>
917inline 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 */
930template <typename PodType, std::size_t N>
931inline 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 */
947template <typename PodType, std::size_t N>
948inline 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 */
961template <typename PodType, std::size_t N>
962inline 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 */
980template <typename PodType, std::size_t N>
981inline 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 */
994template <typename PodType, std::size_t N>
995inline 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 */
1013template <typename PodType, std::size_t N>
1014inline 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 */
1027template <typename PodType, std::size_t N>
1028inline 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 */
1044template <typename PodType, std::size_t N>
1045inline 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 */
1058template <typename PodType, std::size_t N>
1059inline 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 */
1075template <typename PodType, std::size_t N>
1076inline 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 */
1089template <typename PodType, std::size_t N>
1090inline 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 */
1111template <typename PodType, typename Allocator>
1112inline 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 */
1134template <typename PodType, typename Allocator>
1135inline 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 */
1160template <typename PodType, typename Allocator>
1161inline 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 */
1184template <typename PodType, typename Allocator>
1185inline 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 */
1207template <typename Elem, typename Traits, typename Allocator>
1208inline 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 */
1230template <typename Elem, typename Traits, typename Allocator>
1231inline 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 */
1296inline 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 */
1326inline 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 */
1352inline 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 */
1378inline 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 */
1403template <typename ConstBufferSequence>
1404std::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 */
1443inline 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 */
1468inline 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 */
1495inline 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 */
1522inline 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 */
1548template <typename ConstBufferSequence>
1549inline 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 */
1574template <typename MutableBufferSequence>
1575std::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 */
1614template <typename MutableBufferSequence>
1615inline 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 */
1641template <typename MutableBufferSequence>
1642inline 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 */
1668template <typename MutableBufferSequence>
1669inline 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 */
1694template <typename MutableBufferSequence, typename ConstBufferSequence>
1695std::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 */
1762inline 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 */
1791inline 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 */
1821inline 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 */
1851inline 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 */
1881template <typename ConstBufferSequence>
1882inline 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 */
1911inline 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 */
1940inline 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 */
1970inline 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 */
2000inline 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 */
2030template <typename ConstBufferSequence>
2031inline 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 */
2061template <typename MutableBufferSequence>
2062inline 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 */
2092template <typename MutableBufferSequence>
2093inline 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 */
2124template <typename MutableBufferSequence>
2125inline 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 */
2156template <typename MutableBufferSequence>
2157inline 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 */
2187template <typename MutableBufferSequence, typename ConstBufferSequence>
2188std::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