5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_BUFFER_HPP
12 #define BOOST_ASIO_BUFFER_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
23 #include <boost/asio/detail/array_fwd.hpp>
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)
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__)
41 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
42 # include <boost/asio/detail/function.hpp>
43 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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)
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)
58 #include <boost/asio/detail/push_options.hpp>
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&);
73 /// Holds a buffer that can be modified.
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
79 * @par Accessing Buffer Contents
81 * The contents of a buffer may be accessed using the @ref buffer_size
82 * and @ref buffer_cast functions:
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);
89 * The boost::asio::buffer_cast function permits violations of type safety, so
90 * uses of it in application code should be carefully considered.
95 /// Construct an empty buffer.
102 /// Construct a buffer to represent a given memory range.
103 mutable_buffer(void* data, std::size_t size)
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)
114 debug_check_(debug_check)
118 const boost::asio::detail::function<void()>& get_debug_check() const
122 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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);
133 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
134 boost::asio::detail::function<void()> debug_check_;
135 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
140 inline void* buffer_cast_helper(const mutable_buffer& b)
142 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
143 if (b.size_ && b.debug_check_)
145 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
149 inline std::size_t buffer_size_helper(const mutable_buffer& b)
154 } // namespace detail
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
162 /// The type for each element in the list of buffers.
163 typedef mutable_buffer value_type;
165 /// A random-access iterator type that may be used to read elements.
166 typedef const mutable_buffer* const_iterator;
168 /// Construct to represent a given memory range.
169 mutable_buffers_1(void* data, std::size_t size)
170 : mutable_buffer(data, size)
174 /// Construct to represent a single modifiable buffer.
175 explicit mutable_buffers_1(const mutable_buffer& b)
180 /// Get a random-access iterator to the first element.
181 const_iterator begin() const
186 /// Get a random-access iterator for one past the last element.
187 const_iterator end() const
193 /// Holds a buffer that cannot be modified.
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
199 * @par Accessing Buffer Contents
201 * The contents of a buffer may be accessed using the @ref buffer_size
202 * and @ref buffer_cast functions:
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);
209 * The boost::asio::buffer_cast function permits violations of type safety, so
210 * uses of it in application code should be carefully considered.
215 /// Construct an empty buffer.
222 /// Construct a buffer to represent a given memory range.
223 const_buffer(const void* data, std::size_t size)
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
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)
244 debug_check_(debug_check)
248 const boost::asio::detail::function<void()>& get_debug_check() const
252 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
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);
263 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
264 boost::asio::detail::function<void()> debug_check_;
265 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
270 inline const void* buffer_cast_helper(const const_buffer& b)
272 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
273 if (b.size_ && b.debug_check_)
275 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
279 inline std::size_t buffer_size_helper(const const_buffer& b)
284 } // namespace detail
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
292 /// The type for each element in the list of buffers.
293 typedef const_buffer value_type;
295 /// A random-access iterator type that may be used to read elements.
296 typedef const const_buffer* const_iterator;
298 /// Construct to represent a given memory range.
299 const_buffers_1(const void* data, std::size_t size)
300 : const_buffer(data, size)
304 /// Construct to represent a single non-modifiable buffer.
305 explicit const_buffers_1(const const_buffer& b)
310 /// Get a random-access iterator to the first element.
311 const_iterator begin() const
316 /// Get a random-access iterator for one past the last element.
317 const_iterator end() const
323 /// An implementation of both the ConstBufferSequence and MutableBufferSequence
324 /// concepts to represent a null buffer sequence.
328 /// The type for each element in the list of buffers.
329 typedef mutable_buffer value_type;
331 /// A random-access iterator type that may be used to read elements.
332 typedef const mutable_buffer* const_iterator;
334 /// Get a random-access iterator to the first element.
335 const_iterator begin() const
340 /// Get a random-access iterator for one past the last element.
341 const_iterator end() const
350 /** @defgroup buffer_size boost::asio::buffer_size
352 * @brief The boost::asio::buffer_size function determines the total number of
353 * bytes in a buffer or buffer sequence.
357 /// Get the number of bytes in a modifiable buffer.
358 inline std::size_t buffer_size(const mutable_buffer& b)
360 return detail::buffer_size_helper(b);
363 /// Get the number of bytes in a modifiable buffer.
364 inline std::size_t buffer_size(const mutable_buffers_1& b)
366 return detail::buffer_size_helper(b);
369 /// Get the number of bytes in a non-modifiable buffer.
370 inline std::size_t buffer_size(const const_buffer& b)
372 return detail::buffer_size_helper(b);
375 /// Get the number of bytes in a non-modifiable buffer.
376 inline std::size_t buffer_size(const const_buffers_1& b)
378 return detail::buffer_size_helper(b);
381 /// Get the total number of bytes in a buffer sequence.
383 * The @c BufferSequence template parameter may meet either of the @c
384 * ConstBufferSequence or @c MutableBufferSequence type requirements.
386 template <typename BufferSequence>
387 inline std::size_t buffer_size(const BufferSequence& b)
389 std::size_t total_buffer_size = 0;
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);
396 return total_buffer_size;
401 /** @defgroup buffer_cast boost::asio::buffer_cast
403 * @brief The boost::asio::buffer_cast function is used to obtain a pointer to
404 * the underlying memory region associated with a buffer.
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);
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);
418 * The boost::asio::buffer_cast function permits violations of type safety, so
419 * uses of it in application code should be carefully considered.
423 /// Cast a non-modifiable buffer to a specified pointer to POD type.
424 template <typename PointerToPodType>
425 inline PointerToPodType buffer_cast(const mutable_buffer& b)
427 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
430 /// Cast a non-modifiable buffer to a specified pointer to POD type.
431 template <typename PointerToPodType>
432 inline PointerToPodType buffer_cast(const const_buffer& b)
434 return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
439 /// Create a new modifiable buffer that is offset from the start of another.
441 * @relates mutable_buffer
443 inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
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
456 /// Create a new modifiable buffer that is offset from the start of another.
458 * @relates mutable_buffer
460 inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
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
473 /// Create a new non-modifiable buffer that is offset from the start of another.
475 * @relates const_buffer
477 inline const_buffer operator+(const const_buffer& b, std::size_t start)
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
490 /// Create a new non-modifiable buffer that is offset from the start of another.
492 * @relates const_buffer
494 inline const_buffer operator+(std::size_t start, const const_buffer& b)
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
507 #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
510 template <typename Iterator>
511 class buffer_debug_check
514 buffer_debug_check(Iterator iter)
519 ~buffer_debug_check()
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.
526 #endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400)
538 } // namespace detail
539 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
541 /** @defgroup buffer boost::asio::buffer
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,
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.
556 * The simplest use case involves reading or writing a single buffer of a
559 * @code sock.send(boost::asio::buffer(data, size)); @endcode
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.
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:
570 * @code char d1[128];
571 * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1));
573 * std::vector<char> d2(128);
574 * bytes_transferred = sock.receive(boost::asio::buffer(d2));
576 * std::array<char, 128> d3;
577 * bytes_transferred = sock.receive(boost::asio::buffer(d3));
579 * boost::array<char, 128> d4;
580 * bytes_transferred = sock.receive(boost::asio::buffer(d4)); @endcode
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.
587 * @par Accessing Buffer Contents
589 * The contents of a buffer may be accessed using the @ref buffer_size and
590 * @ref buffer_cast functions:
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);
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
600 * The boost::asio::buffer_cast function permits violations of type safety, so
601 * uses of it in application code should be carefully considered.
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.
608 * @par Buffer Copying
610 * The @ref buffer_copy function may be used to copy raw bytes between
611 * individual buffers and buffer sequences.
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:
616 * @code vector<const_buffer> buffers = ...;
618 * vector<unsigned char> data(boost::asio::buffer_size(buffers));
619 * boost::asio::buffer_copy(boost::asio::buffer(data), buffers); @endcode
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.
624 * @par Buffer Invalidation
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.
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)
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).
641 * @par Buffer Arithmetic
643 * Buffer objects may be manipulated using simple arithmetic in a safe way
644 * which helps prevent buffer overruns. Consider an array initialised as
647 * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode
649 * A buffer object @c b1 created using:
651 * @code b1 = boost::asio::buffer(a); @endcode
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:
657 * @code b2 = boost::asio::buffer(a, 3); @endcode
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.
663 * An offset may be applied to an existing buffer to create a new one:
665 * @code b3 = b1 + 2; @endcode
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
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:
674 * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode
676 * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.
678 * @par Buffers and Scatter-Gather I/O
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:
686 * std::vector<char> d2(128);
687 * boost::array<char, 128> d3;
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);
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
703 /// Create a new modifiable buffer from an existing buffer.
705 * @returns <tt>mutable_buffers_1(b)</tt>.
707 inline mutable_buffers_1 buffer(const mutable_buffer& b)
709 return mutable_buffers_1(b);
712 /// Create a new modifiable buffer from an existing buffer.
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
719 inline mutable_buffers_1 buffer(const mutable_buffer& b,
720 std::size_t max_size_in_bytes)
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
732 /// Create a new non-modifiable buffer from an existing buffer.
734 * @returns <tt>const_buffers_1(b)</tt>.
736 inline const_buffers_1 buffer(const const_buffer& b)
738 return const_buffers_1(b);
741 /// Create a new non-modifiable buffer from an existing buffer.
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
748 inline const_buffers_1 buffer(const const_buffer& b,
749 std::size_t max_size_in_bytes)
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
761 /// Create a new modifiable buffer that represents the given memory range.
763 * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>.
765 inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
767 return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
770 /// Create a new non-modifiable buffer that represents the given memory range.
772 * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>.
774 inline const_buffers_1 buffer(const void* data,
775 std::size_t size_in_bytes)
777 return const_buffers_1(const_buffer(data, size_in_bytes));
780 /// Create a new modifiable buffer that represents the given POD array.
782 * @returns A mutable_buffers_1 value equivalent to:
783 * @code mutable_buffers_1(
784 * static_cast<void*>(data),
785 * N * sizeof(PodType)); @endcode
787 template <typename PodType, std::size_t N>
788 inline mutable_buffers_1 buffer(PodType (&data)[N])
790 return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
793 /// Create a new modifiable buffer that represents the given POD array.
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
800 template <typename PodType, std::size_t N>
801 inline mutable_buffers_1 buffer(PodType (&data)[N],
802 std::size_t max_size_in_bytes)
804 return mutable_buffers_1(
806 N * sizeof(PodType) < max_size_in_bytes
807 ? N * sizeof(PodType) : max_size_in_bytes));
810 /// Create a new non-modifiable buffer that represents the given POD array.
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
817 template <typename PodType, std::size_t N>
818 inline const_buffers_1 buffer(const PodType (&data)[N])
820 return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
823 /// Create a new non-modifiable buffer that represents the given POD array.
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
830 template <typename PodType, std::size_t N>
831 inline const_buffers_1 buffer(const PodType (&data)[N],
832 std::size_t max_size_in_bytes)
834 return const_buffers_1(
836 N * sizeof(PodType) < max_size_in_bytes
837 ? N * sizeof(PodType) : max_size_in_bytes));
840 #if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
842 // Borland C++ and Sun Studio think the overloads:
844 // unspecified buffer(boost::array<PodType, N>& array ...);
848 // unspecified buffer(boost::array<const PodType, N>& array ...);
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.
856 template <bool IsConst>
857 struct buffer_types_base;
860 struct buffer_types_base<false>
862 typedef mutable_buffer buffer_type;
863 typedef mutable_buffers_1 container_type;
867 struct buffer_types_base<true>
869 typedef const_buffer buffer_type;
870 typedef const_buffers_1 container_type;
873 template <typename PodType>
875 : public buffer_types_base<is_const<PodType>::value>
879 } // namespace detail
881 template <typename PodType, std::size_t N>
882 inline typename detail::buffer_types<PodType>::container_type
883 buffer(boost::array<PodType, N>& data)
885 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
887 typedef typename boost::asio::detail::buffer_types<PodType>::container_type
889 return container_type(
890 buffer_type(data.c_array(), data.size() * sizeof(PodType)));
893 template <typename PodType, std::size_t N>
894 inline typename detail::buffer_types<PodType>::container_type
895 buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
897 typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
899 typedef typename boost::asio::detail::buffer_types<PodType>::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));
907 #else // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
909 /// Create a new modifiable buffer that represents the given POD array.
911 * @returns A mutable_buffers_1 value equivalent to:
912 * @code mutable_buffers_1(
914 * data.size() * sizeof(PodType)); @endcode
916 template <typename PodType, std::size_t N>
917 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
919 return mutable_buffers_1(
920 mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
923 /// Create a new modifiable buffer that represents the given POD array.
925 * @returns A mutable_buffers_1 value equivalent to:
926 * @code mutable_buffers_1(
928 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
930 template <typename PodType, std::size_t N>
931 inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
932 std::size_t max_size_in_bytes)
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));
940 /// Create a new non-modifiable buffer that represents the given POD array.
942 * @returns A const_buffers_1 value equivalent to:
943 * @code const_buffers_1(
945 * data.size() * sizeof(PodType)); @endcode
947 template <typename PodType, std::size_t N>
948 inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
950 return const_buffers_1(
951 const_buffer(data.data(), data.size() * sizeof(PodType)));
954 /// Create a new non-modifiable buffer that represents the given POD array.
956 * @returns A const_buffers_1 value equivalent to:
957 * @code const_buffers_1(
959 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
961 template <typename PodType, std::size_t N>
962 inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
963 std::size_t max_size_in_bytes)
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));
971 #endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
973 /// Create a new non-modifiable buffer that represents the given POD array.
975 * @returns A const_buffers_1 value equivalent to:
976 * @code const_buffers_1(
978 * data.size() * sizeof(PodType)); @endcode
980 template <typename PodType, std::size_t N>
981 inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
983 return const_buffers_1(
984 const_buffer(data.data(), data.size() * sizeof(PodType)));
987 /// Create a new non-modifiable buffer that represents the given POD array.
989 * @returns A const_buffers_1 value equivalent to:
990 * @code const_buffers_1(
992 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
994 template <typename PodType, std::size_t N>
995 inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
996 std::size_t max_size_in_bytes)
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));
1004 #if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1006 /// Create a new modifiable buffer that represents the given POD array.
1008 * @returns A mutable_buffers_1 value equivalent to:
1009 * @code mutable_buffers_1(
1011 * data.size() * sizeof(PodType)); @endcode
1013 template <typename PodType, std::size_t N>
1014 inline mutable_buffers_1 buffer(std::array<PodType, N>& data)
1016 return mutable_buffers_1(
1017 mutable_buffer(data.data(), data.size() * sizeof(PodType)));
1020 /// Create a new modifiable buffer that represents the given POD array.
1022 * @returns A mutable_buffers_1 value equivalent to:
1023 * @code mutable_buffers_1(
1025 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1027 template <typename PodType, std::size_t N>
1028 inline mutable_buffers_1 buffer(std::array<PodType, N>& data,
1029 std::size_t max_size_in_bytes)
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));
1037 /// Create a new non-modifiable buffer that represents the given POD array.
1039 * @returns A const_buffers_1 value equivalent to:
1040 * @code const_buffers_1(
1042 * data.size() * sizeof(PodType)); @endcode
1044 template <typename PodType, std::size_t N>
1045 inline const_buffers_1 buffer(std::array<const PodType, N>& data)
1047 return const_buffers_1(
1048 const_buffer(data.data(), data.size() * sizeof(PodType)));
1051 /// Create a new non-modifiable buffer that represents the given POD array.
1053 * @returns A const_buffers_1 value equivalent to:
1054 * @code const_buffers_1(
1056 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1058 template <typename PodType, std::size_t N>
1059 inline const_buffers_1 buffer(std::array<const PodType, N>& data,
1060 std::size_t max_size_in_bytes)
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));
1068 /// Create a new non-modifiable buffer that represents the given POD array.
1070 * @returns A const_buffers_1 value equivalent to:
1071 * @code const_buffers_1(
1073 * data.size() * sizeof(PodType)); @endcode
1075 template <typename PodType, std::size_t N>
1076 inline const_buffers_1 buffer(const std::array<PodType, N>& data)
1078 return const_buffers_1(
1079 const_buffer(data.data(), data.size() * sizeof(PodType)));
1082 /// Create a new non-modifiable buffer that represents the given POD array.
1084 * @returns A const_buffers_1 value equivalent to:
1085 * @code const_buffers_1(
1087 * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
1089 template <typename PodType, std::size_t N>
1090 inline const_buffers_1 buffer(const std::array<PodType, N>& data,
1091 std::size_t max_size_in_bytes)
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));
1099 #endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
1101 /// Create a new modifiable buffer that represents the given POD vector.
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
1108 * @note The buffer is invalidated by any vector operation that would also
1109 * invalidate iterators.
1111 template <typename PodType, typename Allocator>
1112 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
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
1120 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1124 /// Create a new modifiable buffer that represents the given POD vector.
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
1131 * @note The buffer is invalidated by any vector operation that would also
1132 * invalidate iterators.
1134 template <typename PodType, typename Allocator>
1135 inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
1136 std::size_t max_size_in_bytes)
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
1146 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1150 /// Create a new non-modifiable buffer that represents the given POD vector.
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
1157 * @note The buffer is invalidated by any vector operation that would also
1158 * invalidate iterators.
1160 template <typename PodType, typename Allocator>
1161 inline const_buffers_1 buffer(
1162 const std::vector<PodType, Allocator>& data)
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
1170 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1174 /// Create a new non-modifiable buffer that represents the given POD vector.
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
1181 * @note The buffer is invalidated by any vector operation that would also
1182 * invalidate iterators.
1184 template <typename PodType, typename Allocator>
1185 inline const_buffers_1 buffer(
1186 const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
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
1196 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1200 /// Create a new non-modifiable buffer that represents the given string.
1202 * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>.
1204 * @note The buffer is invalidated by any non-const operation called on the
1205 * given string object.
1207 template <typename Elem, typename Traits, typename Allocator>
1208 inline const_buffers_1 buffer(
1209 const std::basic_string<Elem, Traits, Allocator>& data)
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
1216 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1220 /// Create a new non-modifiable buffer that represents the given string.
1222 * @returns A const_buffers_1 value equivalent to:
1223 * @code const_buffers_1(
1225 * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
1227 * @note The buffer is invalidated by any non-const operation called on the
1228 * given string object.
1230 template <typename Elem, typename Traits, typename Allocator>
1231 inline const_buffers_1 buffer(
1232 const std::basic_string<Elem, Traits, Allocator>& data,
1233 std::size_t max_size_in_bytes)
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
1243 #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
1249 /** @defgroup buffer_copy boost::asio::buffer_copy
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).
1254 * The @c buffer_copy function is available in two forms:
1256 * @li A 2-argument form: @c buffer_copy(target, source)
1258 * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
1260 * Both forms return the number of bytes actually copied. The number of bytes
1261 * copied is the lesser of:
1263 * @li @c buffer_size(target)
1265 * @li @c buffer_size(source)
1267 * @li @c If specified, @c max_bytes_to_copy.
1269 * This prevents buffer overflow, regardless of the buffer sizes used in the
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.
1277 /// Copies bytes from a source buffer to a target buffer.
1279 * @param target A modifiable buffer representing the memory region to which
1280 * the bytes will be copied.
1282 * @param source A non-modifiable buffer representing the memory region from
1283 * which the bytes will be copied.
1285 * @returns The number of bytes copied.
1287 * @note The number of bytes copied is the lesser of:
1289 * @li @c buffer_size(target)
1291 * @li @c buffer_size(source)
1293 * This function is implemented in terms of @c memcpy, and consequently it
1294 * cannot be used to copy between overlapping memory regions.
1296 inline std::size_t buffer_copy(const mutable_buffer& target,
1297 const const_buffer& source)
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);
1307 /// Copies bytes from a source buffer to a target buffer.
1309 * @param target A modifiable buffer representing the memory region to which
1310 * the bytes will be copied.
1312 * @param source A non-modifiable buffer representing the memory region from
1313 * which the bytes will be copied.
1315 * @returns The number of bytes copied.
1317 * @note The number of bytes copied is the lesser of:
1319 * @li @c buffer_size(target)
1321 * @li @c buffer_size(source)
1323 * This function is implemented in terms of @c memcpy, and consequently it
1324 * cannot be used to copy between overlapping memory regions.
1326 inline std::size_t buffer_copy(const mutable_buffer& target,
1327 const const_buffers_1& source)
1329 return buffer_copy(target, static_cast<const const_buffer&>(source));
1332 /// Copies bytes from a source buffer to a target buffer.
1334 * @param target A modifiable buffer representing the memory region to which
1335 * the bytes will be copied.
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
1341 * @returns The number of bytes copied.
1343 * @note The number of bytes copied is the lesser of:
1345 * @li @c buffer_size(target)
1347 * @li @c buffer_size(source)
1349 * This function is implemented in terms of @c memcpy, and consequently it
1350 * cannot be used to copy between overlapping memory regions.
1352 inline std::size_t buffer_copy(const mutable_buffer& target,
1353 const mutable_buffer& source)
1355 return buffer_copy(target, const_buffer(source));
1358 /// Copies bytes from a source buffer to a target buffer.
1360 * @param target A modifiable buffer representing the memory region to which
1361 * the bytes will be copied.
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
1367 * @returns The number of bytes copied.
1369 * @note The number of bytes copied is the lesser of:
1371 * @li @c buffer_size(target)
1373 * @li @c buffer_size(source)
1375 * This function is implemented in terms of @c memcpy, and consequently it
1376 * cannot be used to copy between overlapping memory regions.
1378 inline std::size_t buffer_copy(const mutable_buffer& target,
1379 const mutable_buffers_1& source)
1381 return buffer_copy(target, const_buffer(source));
1384 /// Copies bytes from a source buffer sequence to a target buffer.
1386 * @param target A modifiable buffer representing the memory region to which
1387 * the bytes will be copied.
1389 * @param source A non-modifiable buffer sequence representing the memory
1390 * regions from which the bytes will be copied.
1392 * @returns The number of bytes copied.
1394 * @note The number of bytes copied is the lesser of:
1396 * @li @c buffer_size(target)
1398 * @li @c buffer_size(source)
1400 * This function is implemented in terms of @c memcpy, and consequently it
1401 * cannot be used to copy between overlapping memory regions.
1403 template <typename ConstBufferSequence>
1404 std::size_t buffer_copy(const mutable_buffer& target,
1405 const ConstBufferSequence& source)
1407 std::size_t total_bytes_copied = 0;
1409 typename ConstBufferSequence::const_iterator source_iter = source.begin();
1410 typename ConstBufferSequence::const_iterator source_end = source.end();
1412 for (mutable_buffer target_buffer(target);
1413 buffer_size(target_buffer) && source_iter != source_end; ++source_iter)
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;
1421 return total_bytes_copied;
1424 /// Copies bytes from a source buffer to a target buffer.
1426 * @param target A modifiable buffer representing the memory region to which
1427 * the bytes will be copied.
1429 * @param source A non-modifiable buffer representing the memory region from
1430 * which the bytes will be copied.
1432 * @returns The number of bytes copied.
1434 * @note The number of bytes copied is the lesser of:
1436 * @li @c buffer_size(target)
1438 * @li @c buffer_size(source)
1440 * This function is implemented in terms of @c memcpy, and consequently it
1441 * cannot be used to copy between overlapping memory regions.
1443 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1444 const const_buffer& source)
1446 return buffer_copy(static_cast<const mutable_buffer&>(target), source);
1449 /// Copies bytes from a source buffer to a target buffer.
1451 * @param target A modifiable buffer representing the memory region to which
1452 * the bytes will be copied.
1454 * @param source A non-modifiable buffer representing the memory region from
1455 * which the bytes will be copied.
1457 * @returns The number of bytes copied.
1459 * @note The number of bytes copied is the lesser of:
1461 * @li @c buffer_size(target)
1463 * @li @c buffer_size(source)
1465 * This function is implemented in terms of @c memcpy, and consequently it
1466 * cannot be used to copy between overlapping memory regions.
1468 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1469 const const_buffers_1& source)
1471 return buffer_copy(static_cast<const mutable_buffer&>(target),
1472 static_cast<const const_buffer&>(source));
1475 /// Copies bytes from a source buffer to a target buffer.
1477 * @param target A modifiable buffer representing the memory region to which
1478 * the bytes will be copied.
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
1484 * @returns The number of bytes copied.
1486 * @note The number of bytes copied is the lesser of:
1488 * @li @c buffer_size(target)
1490 * @li @c buffer_size(source)
1492 * This function is implemented in terms of @c memcpy, and consequently it
1493 * cannot be used to copy between overlapping memory regions.
1495 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1496 const mutable_buffer& source)
1498 return buffer_copy(static_cast<const mutable_buffer&>(target),
1499 const_buffer(source));
1502 /// Copies bytes from a source buffer to a target buffer.
1504 * @param target A modifiable buffer representing the memory region to which
1505 * the bytes will be copied.
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
1511 * @returns The number of bytes copied.
1513 * @note The number of bytes copied is the lesser of:
1515 * @li @c buffer_size(target)
1517 * @li @c buffer_size(source)
1519 * This function is implemented in terms of @c memcpy, and consequently it
1520 * cannot be used to copy between overlapping memory regions.
1522 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1523 const mutable_buffers_1& source)
1525 return buffer_copy(static_cast<const mutable_buffer&>(target),
1526 const_buffer(source));
1529 /// Copies bytes from a source buffer sequence to a target buffer.
1531 * @param target A modifiable buffer representing the memory region to which
1532 * the bytes will be copied.
1534 * @param source A non-modifiable buffer sequence representing the memory
1535 * regions from which the bytes will be copied.
1537 * @returns The number of bytes copied.
1539 * @note The number of bytes copied is the lesser of:
1541 * @li @c buffer_size(target)
1543 * @li @c buffer_size(source)
1545 * This function is implemented in terms of @c memcpy, and consequently it
1546 * cannot be used to copy between overlapping memory regions.
1548 template <typename ConstBufferSequence>
1549 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1550 const ConstBufferSequence& source)
1552 return buffer_copy(static_cast<const mutable_buffer&>(target), source);
1555 /// Copies bytes from a source buffer to a target buffer sequence.
1557 * @param target A modifiable buffer sequence representing the memory regions to
1558 * which the bytes will be copied.
1560 * @param source A non-modifiable buffer representing the memory region from
1561 * which the bytes will be copied.
1563 * @returns The number of bytes copied.
1565 * @note The number of bytes copied is the lesser of:
1567 * @li @c buffer_size(target)
1569 * @li @c buffer_size(source)
1571 * This function is implemented in terms of @c memcpy, and consequently it
1572 * cannot be used to copy between overlapping memory regions.
1574 template <typename MutableBufferSequence>
1575 std::size_t buffer_copy(const MutableBufferSequence& target,
1576 const const_buffer& source)
1578 std::size_t total_bytes_copied = 0;
1580 typename MutableBufferSequence::const_iterator target_iter = target.begin();
1581 typename MutableBufferSequence::const_iterator target_end = target.end();
1583 for (const_buffer source_buffer(source);
1584 buffer_size(source_buffer) && target_iter != target_end; ++target_iter)
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;
1592 return total_bytes_copied;
1595 /// Copies bytes from a source buffer to a target buffer sequence.
1597 * @param target A modifiable buffer sequence representing the memory regions to
1598 * which the bytes will be copied.
1600 * @param source A non-modifiable buffer representing the memory region from
1601 * which the bytes will be copied.
1603 * @returns The number of bytes copied.
1605 * @note The number of bytes copied is the lesser of:
1607 * @li @c buffer_size(target)
1609 * @li @c buffer_size(source)
1611 * This function is implemented in terms of @c memcpy, and consequently it
1612 * cannot be used to copy between overlapping memory regions.
1614 template <typename MutableBufferSequence>
1615 inline std::size_t buffer_copy(const MutableBufferSequence& target,
1616 const const_buffers_1& source)
1618 return buffer_copy(target, static_cast<const const_buffer&>(source));
1621 /// Copies bytes from a source buffer to a target buffer sequence.
1623 * @param target A modifiable buffer sequence representing the memory regions to
1624 * which the bytes will be copied.
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
1630 * @returns The number of bytes copied.
1632 * @note The number of bytes copied is the lesser of:
1634 * @li @c buffer_size(target)
1636 * @li @c buffer_size(source)
1638 * This function is implemented in terms of @c memcpy, and consequently it
1639 * cannot be used to copy between overlapping memory regions.
1641 template <typename MutableBufferSequence>
1642 inline std::size_t buffer_copy(const MutableBufferSequence& target,
1643 const mutable_buffer& source)
1645 return buffer_copy(target, const_buffer(source));
1648 /// Copies bytes from a source buffer to a target buffer sequence.
1650 * @param target A modifiable buffer sequence representing the memory regions to
1651 * which the bytes will be copied.
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
1657 * @returns The number of bytes copied.
1659 * @note The number of bytes copied is the lesser of:
1661 * @li @c buffer_size(target)
1663 * @li @c buffer_size(source)
1665 * This function is implemented in terms of @c memcpy, and consequently it
1666 * cannot be used to copy between overlapping memory regions.
1668 template <typename MutableBufferSequence>
1669 inline std::size_t buffer_copy(const MutableBufferSequence& target,
1670 const mutable_buffers_1& source)
1672 return buffer_copy(target, const_buffer(source));
1675 /// Copies bytes from a source buffer sequence to a target buffer sequence.
1677 * @param target A modifiable buffer sequence representing the memory regions to
1678 * which the bytes will be copied.
1680 * @param source A non-modifiable buffer sequence representing the memory
1681 * regions from which the bytes will be copied.
1683 * @returns The number of bytes copied.
1685 * @note The number of bytes copied is the lesser of:
1687 * @li @c buffer_size(target)
1689 * @li @c buffer_size(source)
1691 * This function is implemented in terms of @c memcpy, and consequently it
1692 * cannot be used to copy between overlapping memory regions.
1694 template <typename MutableBufferSequence, typename ConstBufferSequence>
1695 std::size_t buffer_copy(const MutableBufferSequence& target,
1696 const ConstBufferSequence& source)
1698 std::size_t total_bytes_copied = 0;
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;
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;
1708 while (target_iter != target_end && source_iter != source_end)
1710 mutable_buffer target_buffer =
1711 mutable_buffer(*target_iter) + target_buffer_offset;
1713 const_buffer source_buffer =
1714 const_buffer(*source_iter) + source_buffer_offset;
1716 std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
1717 total_bytes_copied += bytes_copied;
1719 if (bytes_copied == buffer_size(target_buffer))
1722 target_buffer_offset = 0;
1725 target_buffer_offset += bytes_copied;
1727 if (bytes_copied == buffer_size(source_buffer))
1730 source_buffer_offset = 0;
1733 source_buffer_offset += bytes_copied;
1736 return total_bytes_copied;
1739 /// Copies a limited number of bytes from a source buffer to a target buffer.
1741 * @param target A modifiable buffer representing the memory region to which
1742 * the bytes will be copied.
1744 * @param source A non-modifiable buffer representing the memory region from
1745 * which the bytes will be copied.
1747 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1749 * @returns The number of bytes copied.
1751 * @note The number of bytes copied is the lesser of:
1753 * @li @c buffer_size(target)
1755 * @li @c buffer_size(source)
1757 * @li @c max_bytes_to_copy
1759 * This function is implemented in terms of @c memcpy, and consequently it
1760 * cannot be used to copy between overlapping memory regions.
1762 inline std::size_t buffer_copy(const mutable_buffer& target,
1763 const const_buffer& source, std::size_t max_bytes_to_copy)
1765 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1768 /// Copies a limited number of bytes from a source buffer to a target buffer.
1770 * @param target A modifiable buffer representing the memory region to which
1771 * the bytes will be copied.
1773 * @param source A non-modifiable buffer representing the memory region from
1774 * which the bytes will be copied.
1776 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1778 * @returns The number of bytes copied.
1780 * @note The number of bytes copied is the lesser of:
1782 * @li @c buffer_size(target)
1784 * @li @c buffer_size(source)
1786 * @li @c max_bytes_to_copy
1788 * This function is implemented in terms of @c memcpy, and consequently it
1789 * cannot be used to copy between overlapping memory regions.
1791 inline std::size_t buffer_copy(const mutable_buffer& target,
1792 const const_buffers_1& source, std::size_t max_bytes_to_copy)
1794 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1797 /// Copies a limited number of bytes from a source buffer to a target buffer.
1799 * @param target A modifiable buffer representing the memory region to which
1800 * the bytes will be copied.
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
1806 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1808 * @returns The number of bytes copied.
1810 * @note The number of bytes copied is the lesser of:
1812 * @li @c buffer_size(target)
1814 * @li @c buffer_size(source)
1816 * @li @c max_bytes_to_copy
1818 * This function is implemented in terms of @c memcpy, and consequently it
1819 * cannot be used to copy between overlapping memory regions.
1821 inline std::size_t buffer_copy(const mutable_buffer& target,
1822 const mutable_buffer& source, std::size_t max_bytes_to_copy)
1824 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1827 /// Copies a limited number of bytes from a source buffer to a target buffer.
1829 * @param target A modifiable buffer representing the memory region to which
1830 * the bytes will be copied.
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
1836 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1838 * @returns The number of bytes copied.
1840 * @note The number of bytes copied is the lesser of:
1842 * @li @c buffer_size(target)
1844 * @li @c buffer_size(source)
1846 * @li @c max_bytes_to_copy
1848 * This function is implemented in terms of @c memcpy, and consequently it
1849 * cannot be used to copy between overlapping memory regions.
1851 inline std::size_t buffer_copy(const mutable_buffer& target,
1852 const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
1854 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1857 /// Copies a limited number of bytes from a source buffer sequence to a target
1860 * @param target A modifiable buffer representing the memory region to which
1861 * the bytes will be copied.
1863 * @param source A non-modifiable buffer sequence representing the memory
1864 * regions from which the bytes will be copied.
1866 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1868 * @returns The number of bytes copied.
1870 * @note The number of bytes copied is the lesser of:
1872 * @li @c buffer_size(target)
1874 * @li @c buffer_size(source)
1876 * @li @c max_bytes_to_copy
1878 * This function is implemented in terms of @c memcpy, and consequently it
1879 * cannot be used to copy between overlapping memory regions.
1881 template <typename ConstBufferSequence>
1882 inline std::size_t buffer_copy(const mutable_buffer& target,
1883 const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
1885 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1888 /// Copies a limited number of bytes from a source buffer to a target buffer.
1890 * @param target A modifiable buffer representing the memory region to which
1891 * the bytes will be copied.
1893 * @param source A non-modifiable buffer representing the memory region from
1894 * which the bytes will be copied.
1896 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1898 * @returns The number of bytes copied.
1900 * @note The number of bytes copied is the lesser of:
1902 * @li @c buffer_size(target)
1904 * @li @c buffer_size(source)
1906 * @li @c max_bytes_to_copy
1908 * This function is implemented in terms of @c memcpy, and consequently it
1909 * cannot be used to copy between overlapping memory regions.
1911 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1912 const const_buffer& source, std::size_t max_bytes_to_copy)
1914 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1917 /// Copies a limited number of bytes from a source buffer to a target buffer.
1919 * @param target A modifiable buffer representing the memory region to which
1920 * the bytes will be copied.
1922 * @param source A non-modifiable buffer representing the memory region from
1923 * which the bytes will be copied.
1925 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1927 * @returns The number of bytes copied.
1929 * @note The number of bytes copied is the lesser of:
1931 * @li @c buffer_size(target)
1933 * @li @c buffer_size(source)
1935 * @li @c max_bytes_to_copy
1937 * This function is implemented in terms of @c memcpy, and consequently it
1938 * cannot be used to copy between overlapping memory regions.
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)
1943 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1946 /// Copies a limited number of bytes from a source buffer to a target buffer.
1948 * @param target A modifiable buffer representing the memory region to which
1949 * the bytes will be copied.
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
1955 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1957 * @returns The number of bytes copied.
1959 * @note The number of bytes copied is the lesser of:
1961 * @li @c buffer_size(target)
1963 * @li @c buffer_size(source)
1965 * @li @c max_bytes_to_copy
1967 * This function is implemented in terms of @c memcpy, and consequently it
1968 * cannot be used to copy between overlapping memory regions.
1970 inline std::size_t buffer_copy(const mutable_buffers_1& target,
1971 const mutable_buffer& source, std::size_t max_bytes_to_copy)
1973 return buffer_copy(buffer(target, max_bytes_to_copy), source);
1976 /// Copies a limited number of bytes from a source buffer to a target buffer.
1978 * @param target A modifiable buffer representing the memory region to which
1979 * the bytes will be copied.
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
1985 * @param max_bytes_to_copy The maximum number of bytes to be copied.
1987 * @returns The number of bytes copied.
1989 * @note The number of bytes copied is the lesser of:
1991 * @li @c buffer_size(target)
1993 * @li @c buffer_size(source)
1995 * @li @c max_bytes_to_copy
1997 * This function is implemented in terms of @c memcpy, and consequently it
1998 * cannot be used to copy between overlapping memory regions.
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)
2003 return buffer_copy(buffer(target, max_bytes_to_copy), source);
2006 /// Copies a limited number of bytes from a source buffer sequence to a target
2009 * @param target A modifiable buffer representing the memory region to which
2010 * the bytes will be copied.
2012 * @param source A non-modifiable buffer sequence representing the memory
2013 * regions from which the bytes will be copied.
2015 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2017 * @returns The number of bytes copied.
2019 * @note The number of bytes copied is the lesser of:
2021 * @li @c buffer_size(target)
2023 * @li @c buffer_size(source)
2025 * @li @c max_bytes_to_copy
2027 * This function is implemented in terms of @c memcpy, and consequently it
2028 * cannot be used to copy between overlapping memory regions.
2030 template <typename ConstBufferSequence>
2031 inline std::size_t buffer_copy(const mutable_buffers_1& target,
2032 const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
2034 return buffer_copy(buffer(target, max_bytes_to_copy), source);
2037 /// Copies a limited number of bytes from a source buffer to a target buffer
2040 * @param target A modifiable buffer sequence representing the memory regions to
2041 * which the bytes will be copied.
2043 * @param source A non-modifiable buffer representing the memory region from
2044 * which the bytes will be copied.
2046 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2048 * @returns The number of bytes copied.
2050 * @note The number of bytes copied is the lesser of:
2052 * @li @c buffer_size(target)
2054 * @li @c buffer_size(source)
2056 * @li @c max_bytes_to_copy
2058 * This function is implemented in terms of @c memcpy, and consequently it
2059 * cannot be used to copy between overlapping memory regions.
2061 template <typename MutableBufferSequence>
2062 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2063 const const_buffer& source, std::size_t max_bytes_to_copy)
2065 return buffer_copy(target, buffer(source, max_bytes_to_copy));
2068 /// Copies a limited number of bytes from a source buffer to a target buffer
2071 * @param target A modifiable buffer sequence representing the memory regions to
2072 * which the bytes will be copied.
2074 * @param source A non-modifiable buffer representing the memory region from
2075 * which the bytes will be copied.
2077 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2079 * @returns The number of bytes copied.
2081 * @note The number of bytes copied is the lesser of:
2083 * @li @c buffer_size(target)
2085 * @li @c buffer_size(source)
2087 * @li @c max_bytes_to_copy
2089 * This function is implemented in terms of @c memcpy, and consequently it
2090 * cannot be used to copy between overlapping memory regions.
2092 template <typename MutableBufferSequence>
2093 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2094 const const_buffers_1& source, std::size_t max_bytes_to_copy)
2096 return buffer_copy(target, buffer(source, max_bytes_to_copy));
2099 /// Copies a limited number of bytes from a source buffer to a target buffer
2102 * @param target A modifiable buffer sequence representing the memory regions to
2103 * which the bytes will be copied.
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
2109 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2111 * @returns The number of bytes copied.
2113 * @note The number of bytes copied is the lesser of:
2115 * @li @c buffer_size(target)
2117 * @li @c buffer_size(source)
2119 * @li @c max_bytes_to_copy
2121 * This function is implemented in terms of @c memcpy, and consequently it
2122 * cannot be used to copy between overlapping memory regions.
2124 template <typename MutableBufferSequence>
2125 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2126 const mutable_buffer& source, std::size_t max_bytes_to_copy)
2128 return buffer_copy(target, buffer(source, max_bytes_to_copy));
2131 /// Copies a limited number of bytes from a source buffer to a target buffer
2134 * @param target A modifiable buffer sequence representing the memory regions to
2135 * which the bytes will be copied.
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
2141 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2143 * @returns The number of bytes copied.
2145 * @note The number of bytes copied is the lesser of:
2147 * @li @c buffer_size(target)
2149 * @li @c buffer_size(source)
2151 * @li @c max_bytes_to_copy
2153 * This function is implemented in terms of @c memcpy, and consequently it
2154 * cannot be used to copy between overlapping memory regions.
2156 template <typename MutableBufferSequence>
2157 inline std::size_t buffer_copy(const MutableBufferSequence& target,
2158 const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
2160 return buffer_copy(target, buffer(source, max_bytes_to_copy));
2163 /// Copies a limited number of bytes from a source buffer sequence to a target
2164 /// buffer sequence.
2166 * @param target A modifiable buffer sequence representing the memory regions to
2167 * which the bytes will be copied.
2169 * @param source A non-modifiable buffer sequence representing the memory
2170 * regions from which the bytes will be copied.
2172 * @param max_bytes_to_copy The maximum number of bytes to be copied.
2174 * @returns The number of bytes copied.
2176 * @note The number of bytes copied is the lesser of:
2178 * @li @c buffer_size(target)
2180 * @li @c buffer_size(source)
2182 * @li @c max_bytes_to_copy
2184 * This function is implemented in terms of @c memcpy, and consequently it
2185 * cannot be used to copy between overlapping memory regions.
2187 template <typename MutableBufferSequence, typename ConstBufferSequence>
2188 std::size_t buffer_copy(const MutableBufferSequence& target,
2189 const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
2191 std::size_t total_bytes_copied = 0;
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;
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;
2201 while (total_bytes_copied != max_bytes_to_copy
2202 && target_iter != target_end && source_iter != source_end)
2204 mutable_buffer target_buffer =
2205 mutable_buffer(*target_iter) + target_buffer_offset;
2207 const_buffer source_buffer =
2208 const_buffer(*source_iter) + source_buffer_offset;
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;
2214 if (bytes_copied == buffer_size(target_buffer))
2217 target_buffer_offset = 0;
2220 target_buffer_offset += bytes_copied;
2222 if (bytes_copied == buffer_size(source_buffer))
2225 source_buffer_offset = 0;
2228 source_buffer_offset += bytes_copied;
2231 return total_bytes_copied;
2237 } // namespace boost
2239 #include <boost/asio/detail/pop_options.hpp>
2241 #endif // BOOST_ASIO_BUFFER_HPP