Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2495 lines
79KB

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