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