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