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 36namespace asio { 37 38class mutable_buffer; 39class const_buffer; 40 41namespace detail { 42void* buffer_cast_helper(const mutable_buffer&); 43const void* buffer_cast_helper(const const_buffer&); 44std::size_t buffer_size_helper(const mutable_buffer&); 45std::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 */ 67class mutable_buffer 68{ 69public: 70 /// Construct an empty buffer. 71 mutable_buffer() 72 : data_(0), 73 size_(0) 74 { 75 } 76 77 /// Construct a buffer to represent a given memory range. 78 mutable_buffer(void* data, std::size_t size) 79 : data_(data), 80 size_(size) 81 { 82 } 83 84 85private: 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 96namespace detail { 97 98inline void* buffer_cast_helper(const mutable_buffer& b) 99{ 100 return b.data_; 101} 102 103inline 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. 112class mutable_buffers_1 113 : public mutable_buffer 114{ 115public: 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. 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. 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. 135 const_iterator begin() const 136 { 137 return this; 138 } 139 140 /// Get a random-access iterator for one past the last element. 141 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 */ 166class const_buffer 167{ 168public: 169 /// Construct an empty buffer. 170 const_buffer() 171 : data_(0), 172 size_(0) 173 { 174 } 175 176 /// Construct a buffer to represent a given memory range. 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. 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 191private: 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 202namespace detail { 203 204inline const void* buffer_cast_helper(const const_buffer& b) 205{ 206 return b.data_; 207} 208 209inline 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. 218class const_buffers_1 219 : public const_buffer 220{ 221public: 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. 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. 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. 241 const_iterator begin() const 242 { 243 return this; 244 } 245 246 /// Get a random-access iterator for one past the last element. 247 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. 255class null_buffers 256{ 257public: 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. 265 const_iterator begin() const 266 { 267 return &buf_; 268 } 269 270 /// Get a random-access iterator for one past the last element. 271 const_iterator end() const 272 { 273 return &buf_; 274 } 275 276private: 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. 288inline 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. 294inline 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. 300inline 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. 306inline 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 */ 316template <typename BufferSequence> 317inline 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. 354template <typename PointerToPodType> 355inline 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. 361template <typename PointerToPodType> 362inline 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 */ 373inline 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 */ 387inline 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 */ 401inline 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 */ 415inline 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 */ 592inline 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 */ 604inline 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 */ 618inline 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 */ 630inline 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 */ 644inline 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 */ 653inline 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 */ 666template <typename PodType, std::size_t N> 667inline 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 */ 679template <typename PodType, std::size_t N> 680inline 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 */ 696template <typename PodType, std::size_t N> 697inline 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 */ 709template <typename PodType, std::size_t N> 710inline 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 733namespace detail { 734 735template <bool IsConst> 736struct buffer_types_base; 737 738template <> 739struct buffer_types_base<false> 740{ 741 typedef mutable_buffer buffer_type; 742 typedef mutable_buffers_1 container_type; 743}; 744 745template <> 746struct buffer_types_base<true> 747{ 748 typedef const_buffer buffer_type; 749 typedef const_buffers_1 container_type; 750}; 751 752template <typename PodType> 753struct buffer_types 754 : public buffer_types_base<is_const<PodType>::value> 755{ 756}; 757 758} // namespace detail 759 760template <typename PodType, std::size_t N> 761inline typename detail::buffer_types<PodType>::container_type 762buffer(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 772template <typename PodType, std::size_t N> 773inline typename detail::buffer_types<PodType>::container_type 774buffer(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 */ 795template <typename PodType, std::size_t N> 796inline 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 */ 809template <typename PodType, std::size_t N> 810inline 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 */ 826template <typename PodType, std::size_t N> 827inline 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 */ 840template <typename PodType, std::size_t N> 841inline 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 */ 859template <typename PodType, std::size_t N> 860inline 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 */ 873template <typename PodType, std::size_t N> 874inline 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 */ 891template <typename PodType, std::size_t N> 892inline 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 */ 905template <typename PodType, std::size_t N> 906inline 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 */ 922template <typename PodType, std::size_t N> 923inline 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 */ 936template <typename PodType, std::size_t N> 937inline 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 */ 953template <typename PodType, std::size_t N> 954inline 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 */ 967template <typename PodType, std::size_t N> 968inline 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 */ 988template <typename PodType, typename Allocator> 989inline 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 */ 1006template <typename PodType, typename Allocator> 1007inline 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 */ 1027template <typename PodType, typename Allocator> 1028inline 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 */ 1046template <typename PodType, typename Allocator> 1047inline 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 */ 1064template <typename Elem, typename Traits, typename Allocator> 1065inline 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 */ 1082template <typename Elem, typename Traits, typename Allocator> 1083inline 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 */ 1143inline 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 */ 1173inline 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 */ 1199inline 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 */ 1225inline 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 */ 1250template <typename ConstBufferSequence> 1251std::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 */ 1290inline 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 */ 1315inline 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 */ 1342inline 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 */ 1369inline 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 */ 1395template <typename ConstBufferSequence> 1396inline 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 */ 1421template <typename MutableBufferSequence> 1422std::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 */ 1461template <typename MutableBufferSequence> 1462inline 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 */ 1488template <typename MutableBufferSequence> 1489inline 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 */ 1515template <typename MutableBufferSequence> 1516inline 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 */ 1541template <typename MutableBufferSequence, typename ConstBufferSequence> 1542std::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 */ 1609inline 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 */ 1638inline 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 */ 1668inline 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 */ 1698inline 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 */ 1728template <typename ConstBufferSequence> 1729inline 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 */ 1758inline 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 */ 1787inline 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 */ 1817inline 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 */ 1847inline 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 */ 1877template <typename ConstBufferSequence> 1878inline 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 */ 1908template <typename MutableBufferSequence> 1909inline 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 */ 1939template <typename MutableBufferSequence> 1940inline 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 */ 1971template <typename MutableBufferSequence> 1972inline 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 */ 2003template <typename MutableBufferSequence> 2004inline 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 */ 2034template <typename MutableBufferSequence, typename ConstBufferSequence> 2035std::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