buffer.hpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. //
  2. // buffer.hpp
  3. // ~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 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 BOOST_ASIO_BUFFER_HPP
  11. #define BOOST_ASIO_BUFFER_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <cstddef>
  17. #include <string>
  18. #include <vector>
  19. #include <boost/detail/workaround.hpp>
  20. #include <boost/asio/detail/array_fwd.hpp>
  21. #if defined(BOOST_MSVC)
  22. # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
  23. # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
  24. # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  25. # endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
  26. # endif // defined(_HAS_ITERATOR_DEBUGGING)
  27. #endif // defined(BOOST_MSVC)
  28. #if defined(__GNUC__)
  29. # if defined(_GLIBCXX_DEBUG)
  30. # if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
  31. # define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  32. # endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
  33. # endif // defined(_GLIBCXX_DEBUG)
  34. #endif // defined(__GNUC__)
  35. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  36. # include <boost/function.hpp>
  37. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  38. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
  39. || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
  40. # include <boost/type_traits/is_const.hpp>
  41. #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
  42. // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
  43. #include <boost/asio/detail/push_options.hpp>
  44. namespace boost {
  45. namespace asio {
  46. class mutable_buffer;
  47. class const_buffer;
  48. namespace detail {
  49. void* buffer_cast_helper(const mutable_buffer&);
  50. const void* buffer_cast_helper(const const_buffer&);
  51. std::size_t buffer_size_helper(const mutable_buffer&);
  52. std::size_t buffer_size_helper(const const_buffer&);
  53. } // namespace detail
  54. /// Holds a buffer that can be modified.
  55. /**
  56. * The mutable_buffer class provides a safe representation of a buffer that can
  57. * be modified. It does not own the underlying data, and so is cheap to copy or
  58. * assign.
  59. */
  60. class mutable_buffer
  61. {
  62. public:
  63. /// Construct an empty buffer.
  64. mutable_buffer()
  65. : data_(0),
  66. size_(0)
  67. {
  68. }
  69. /// Construct a buffer to represent a given memory range.
  70. mutable_buffer(void* data, std::size_t size)
  71. : data_(data),
  72. size_(size)
  73. {
  74. }
  75. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  76. mutable_buffer(void* data, std::size_t size,
  77. boost::function<void()> debug_check)
  78. : data_(data),
  79. size_(size),
  80. debug_check_(debug_check)
  81. {
  82. }
  83. const boost::function<void()>& get_debug_check() const
  84. {
  85. return debug_check_;
  86. }
  87. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  88. private:
  89. friend void* boost::asio::detail::buffer_cast_helper(
  90. const mutable_buffer& b);
  91. friend std::size_t boost::asio::detail::buffer_size_helper(
  92. const mutable_buffer& b);
  93. void* data_;
  94. std::size_t size_;
  95. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  96. boost::function<void()> debug_check_;
  97. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  98. };
  99. namespace detail {
  100. inline void* buffer_cast_helper(const mutable_buffer& b)
  101. {
  102. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  103. if (b.size_ && b.debug_check_)
  104. b.debug_check_();
  105. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  106. return b.data_;
  107. }
  108. inline std::size_t buffer_size_helper(const mutable_buffer& b)
  109. {
  110. return b.size_;
  111. }
  112. } // namespace detail
  113. /// Cast a non-modifiable buffer to a specified pointer to POD type.
  114. /**
  115. * @relates mutable_buffer
  116. */
  117. template <typename PointerToPodType>
  118. inline PointerToPodType buffer_cast(const mutable_buffer& b)
  119. {
  120. return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
  121. }
  122. /// Get the number of bytes in a non-modifiable buffer.
  123. /**
  124. * @relates mutable_buffer
  125. */
  126. inline std::size_t buffer_size(const mutable_buffer& b)
  127. {
  128. return detail::buffer_size_helper(b);
  129. }
  130. /// Create a new modifiable buffer that is offset from the start of another.
  131. /**
  132. * @relates mutable_buffer
  133. */
  134. inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
  135. {
  136. if (start > buffer_size(b))
  137. return mutable_buffer();
  138. char* new_data = buffer_cast<char*>(b) + start;
  139. std::size_t new_size = buffer_size(b) - start;
  140. return mutable_buffer(new_data, new_size
  141. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  142. , b.get_debug_check()
  143. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  144. );
  145. }
  146. /// Create a new modifiable buffer that is offset from the start of another.
  147. /**
  148. * @relates mutable_buffer
  149. */
  150. inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
  151. {
  152. if (start > buffer_size(b))
  153. return mutable_buffer();
  154. char* new_data = buffer_cast<char*>(b) + start;
  155. std::size_t new_size = buffer_size(b) - start;
  156. return mutable_buffer(new_data, new_size
  157. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  158. , b.get_debug_check()
  159. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  160. );
  161. }
  162. /// Adapts a single modifiable buffer so that it meets the requirements of the
  163. /// MutableBufferSequence concept.
  164. class mutable_buffers_1
  165. : public mutable_buffer
  166. {
  167. public:
  168. /// The type for each element in the list of buffers.
  169. typedef mutable_buffer value_type;
  170. /// A random-access iterator type that may be used to read elements.
  171. typedef const mutable_buffer* const_iterator;
  172. /// Construct to represent a given memory range.
  173. mutable_buffers_1(void* data, std::size_t size)
  174. : mutable_buffer(data, size)
  175. {
  176. }
  177. /// Construct to represent a single modifiable buffer.
  178. explicit mutable_buffers_1(const mutable_buffer& b)
  179. : mutable_buffer(b)
  180. {
  181. }
  182. /// Get a random-access iterator to the first element.
  183. const_iterator begin() const
  184. {
  185. return this;
  186. }
  187. /// Get a random-access iterator for one past the last element.
  188. const_iterator end() const
  189. {
  190. return begin() + 1;
  191. }
  192. };
  193. /// Holds a buffer that cannot be modified.
  194. /**
  195. * The const_buffer class provides a safe representation of a buffer that cannot
  196. * be modified. It does not own the underlying data, and so is cheap to copy or
  197. * assign.
  198. */
  199. class const_buffer
  200. {
  201. public:
  202. /// Construct an empty buffer.
  203. const_buffer()
  204. : data_(0),
  205. size_(0)
  206. {
  207. }
  208. /// Construct a buffer to represent a given memory range.
  209. const_buffer(const void* data, std::size_t size)
  210. : data_(data),
  211. size_(size)
  212. {
  213. }
  214. /// Construct a non-modifiable buffer from a modifiable one.
  215. const_buffer(const mutable_buffer& b)
  216. : data_(boost::asio::detail::buffer_cast_helper(b)),
  217. size_(boost::asio::detail::buffer_size_helper(b))
  218. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  219. , debug_check_(b.get_debug_check())
  220. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  221. {
  222. }
  223. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  224. const_buffer(const void* data, std::size_t size,
  225. boost::function<void()> debug_check)
  226. : data_(data),
  227. size_(size),
  228. debug_check_(debug_check)
  229. {
  230. }
  231. const boost::function<void()>& get_debug_check() const
  232. {
  233. return debug_check_;
  234. }
  235. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  236. private:
  237. friend const void* boost::asio::detail::buffer_cast_helper(
  238. const const_buffer& b);
  239. friend std::size_t boost::asio::detail::buffer_size_helper(
  240. const const_buffer& b);
  241. const void* data_;
  242. std::size_t size_;
  243. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  244. boost::function<void()> debug_check_;
  245. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  246. };
  247. namespace detail {
  248. inline const void* buffer_cast_helper(const const_buffer& b)
  249. {
  250. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  251. if (b.size_ && b.debug_check_)
  252. b.debug_check_();
  253. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  254. return b.data_;
  255. }
  256. inline std::size_t buffer_size_helper(const const_buffer& b)
  257. {
  258. return b.size_;
  259. }
  260. } // namespace detail
  261. /// Cast a non-modifiable buffer to a specified pointer to POD type.
  262. /**
  263. * @relates const_buffer
  264. */
  265. template <typename PointerToPodType>
  266. inline PointerToPodType buffer_cast(const const_buffer& b)
  267. {
  268. return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
  269. }
  270. /// Get the number of bytes in a non-modifiable buffer.
  271. /**
  272. * @relates const_buffer
  273. */
  274. inline std::size_t buffer_size(const const_buffer& b)
  275. {
  276. return detail::buffer_size_helper(b);
  277. }
  278. /// Create a new non-modifiable buffer that is offset from the start of another.
  279. /**
  280. * @relates const_buffer
  281. */
  282. inline const_buffer operator+(const const_buffer& b, std::size_t start)
  283. {
  284. if (start > buffer_size(b))
  285. return const_buffer();
  286. const char* new_data = buffer_cast<const char*>(b) + start;
  287. std::size_t new_size = buffer_size(b) - start;
  288. return const_buffer(new_data, new_size
  289. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  290. , b.get_debug_check()
  291. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  292. );
  293. }
  294. /// Create a new non-modifiable buffer that is offset from the start of another.
  295. /**
  296. * @relates const_buffer
  297. */
  298. inline const_buffer operator+(std::size_t start, const const_buffer& b)
  299. {
  300. if (start > buffer_size(b))
  301. return const_buffer();
  302. const char* new_data = buffer_cast<const char*>(b) + start;
  303. std::size_t new_size = buffer_size(b) - start;
  304. return const_buffer(new_data, new_size
  305. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  306. , b.get_debug_check()
  307. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  308. );
  309. }
  310. /// Adapts a single non-modifiable buffer so that it meets the requirements of
  311. /// the ConstBufferSequence concept.
  312. class const_buffers_1
  313. : public const_buffer
  314. {
  315. public:
  316. /// The type for each element in the list of buffers.
  317. typedef const_buffer value_type;
  318. /// A random-access iterator type that may be used to read elements.
  319. typedef const const_buffer* const_iterator;
  320. /// Construct to represent a given memory range.
  321. const_buffers_1(const void* data, std::size_t size)
  322. : const_buffer(data, size)
  323. {
  324. }
  325. /// Construct to represent a single non-modifiable buffer.
  326. explicit const_buffers_1(const const_buffer& b)
  327. : const_buffer(b)
  328. {
  329. }
  330. /// Get a random-access iterator to the first element.
  331. const_iterator begin() const
  332. {
  333. return this;
  334. }
  335. /// Get a random-access iterator for one past the last element.
  336. const_iterator end() const
  337. {
  338. return begin() + 1;
  339. }
  340. };
  341. /// An implementation of both the ConstBufferSequence and MutableBufferSequence
  342. /// concepts to represent a null buffer sequence.
  343. class null_buffers
  344. {
  345. public:
  346. /// The type for each element in the list of buffers.
  347. typedef mutable_buffer value_type;
  348. /// A random-access iterator type that may be used to read elements.
  349. typedef const mutable_buffer* const_iterator;
  350. /// Get a random-access iterator to the first element.
  351. const_iterator begin() const
  352. {
  353. return &buf_;
  354. }
  355. /// Get a random-access iterator for one past the last element.
  356. const_iterator end() const
  357. {
  358. return &buf_;
  359. }
  360. private:
  361. mutable_buffer buf_;
  362. };
  363. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  364. namespace detail {
  365. template <typename Iterator>
  366. class buffer_debug_check
  367. {
  368. public:
  369. buffer_debug_check(Iterator iter)
  370. : iter_(iter)
  371. {
  372. }
  373. ~buffer_debug_check()
  374. {
  375. #if BOOST_WORKAROUND(BOOST_MSVC, == 1400)
  376. // MSVC 8's string iterator checking may crash in a std::string::iterator
  377. // object's destructor when the iterator points to an already-destroyed
  378. // std::string object, unless the iterator is cleared first.
  379. iter_ = Iterator();
  380. #endif // BOOST_WORKAROUND(BOOST_MSVC, == 1400)
  381. }
  382. void operator()()
  383. {
  384. *iter_;
  385. }
  386. private:
  387. Iterator iter_;
  388. };
  389. } // namespace detail
  390. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  391. /** @defgroup buffer boost::asio::buffer
  392. *
  393. * @brief The boost::asio::buffer function is used to create a buffer object to
  394. * represent raw memory, an array of POD elements, a vector of POD elements,
  395. * or a std::string.
  396. *
  397. * A buffer object represents a contiguous region of memory as a 2-tuple
  398. * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*,
  399. * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a
  400. * tuple of the form <tt>{const void*, size_t}</tt> specifies a const
  401. * (non-modifiable) region of memory. These two forms correspond to the classes
  402. * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion
  403. * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the
  404. * opposite conversion is not permitted.
  405. *
  406. * The simplest use case involves reading or writing a single buffer of a
  407. * specified size:
  408. *
  409. * @code sock.send(boost::asio::buffer(data, size)); @endcode
  410. *
  411. * In the above example, the return value of boost::asio::buffer meets the
  412. * requirements of the ConstBufferSequence concept so that it may be directly
  413. * passed to the socket's write function. A buffer created for modifiable
  414. * memory also meets the requirements of the MutableBufferSequence concept.
  415. *
  416. * An individual buffer may be created from a builtin array, std::vector or
  417. * boost::array of POD elements. This helps prevent buffer overruns by
  418. * automatically determining the size of the buffer:
  419. *
  420. * @code char d1[128];
  421. * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1));
  422. *
  423. * std::vector<char> d2(128);
  424. * bytes_transferred = sock.receive(boost::asio::buffer(d2));
  425. *
  426. * boost::array<char, 128> d3;
  427. * bytes_transferred = sock.receive(boost::asio::buffer(d3)); @endcode
  428. *
  429. * In all three cases above, the buffers created are exactly 128 bytes long.
  430. * Note that a vector is @e never automatically resized when creating or using
  431. * a buffer. The buffer size is determined using the vector's <tt>size()</tt>
  432. * member function, and not its capacity.
  433. *
  434. * @par Accessing Buffer Contents
  435. *
  436. * The contents of a buffer may be accessed using the boost::asio::buffer_size
  437. * and boost::asio::buffer_cast functions:
  438. *
  439. * @code boost::asio::mutable_buffer b1 = ...;
  440. * std::size_t s1 = boost::asio::buffer_size(b1);
  441. * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
  442. *
  443. * boost::asio::const_buffer b2 = ...;
  444. * std::size_t s2 = boost::asio::buffer_size(b2);
  445. * const void* p2 = boost::asio::buffer_cast<const void*>(b2); @endcode
  446. *
  447. * The boost::asio::buffer_cast function permits violations of type safety, so
  448. * uses of it in application code should be carefully considered.
  449. *
  450. * @par Buffer Invalidation
  451. *
  452. * A buffer object does not have any ownership of the memory it refers to. It
  453. * is the responsibility of the application to ensure the memory region remains
  454. * valid until it is no longer required for an I/O operation. When the memory
  455. * is no longer available, the buffer is said to have been invalidated.
  456. *
  457. * For the boost::asio::buffer overloads that accept an argument of type
  458. * std::vector, the buffer objects returned are invalidated by any vector
  459. * operation that also invalidates all references, pointers and iterators
  460. * referring to the elements in the sequence (C++ Std, 23.2.4)
  461. *
  462. * For the boost::asio::buffer overloads that accept an argument of type
  463. * std::string, the buffer objects returned are invalidated according to the
  464. * rules defined for invalidation of references, pointers and iterators
  465. * referring to elements of the sequence (C++ Std, 21.3).
  466. *
  467. * @par Buffer Arithmetic
  468. *
  469. * Buffer objects may be manipulated using simple arithmetic in a safe way
  470. * which helps prevent buffer overruns. Consider an array initialised as
  471. * follows:
  472. *
  473. * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode
  474. *
  475. * A buffer object @c b1 created using:
  476. *
  477. * @code b1 = boost::asio::buffer(a); @endcode
  478. *
  479. * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An
  480. * optional second argument to the boost::asio::buffer function may be used to
  481. * limit the size, in bytes, of the buffer:
  482. *
  483. * @code b2 = boost::asio::buffer(a, 3); @endcode
  484. *
  485. * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the
  486. * size argument exceeds the actual size of the array, the size of the buffer
  487. * object created will be limited to the array size.
  488. *
  489. * An offset may be applied to an existing buffer to create a new one:
  490. *
  491. * @code b3 = b1 + 2; @endcode
  492. *
  493. * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset
  494. * exceeds the size of the existing buffer, the newly created buffer will be
  495. * empty.
  496. *
  497. * Both an offset and size may be specified to create a buffer that corresponds
  498. * to a specific range of bytes within an existing buffer:
  499. *
  500. * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode
  501. *
  502. * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.
  503. *
  504. * @par Buffers and Scatter-Gather I/O
  505. *
  506. * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
  507. * buffer objects may be assigned into a container that supports the
  508. * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
  509. *
  510. * @code
  511. * char d1[128];
  512. * std::vector<char> d2(128);
  513. * boost::array<char, 128> d3;
  514. *
  515. * boost::array<mutable_buffer, 3> bufs1 = {
  516. * boost::asio::buffer(d1),
  517. * boost::asio::buffer(d2),
  518. * boost::asio::buffer(d3) };
  519. * bytes_transferred = sock.receive(bufs1);
  520. *
  521. * std::vector<const_buffer> bufs2;
  522. * bufs2.push_back(boost::asio::buffer(d1));
  523. * bufs2.push_back(boost::asio::buffer(d2));
  524. * bufs2.push_back(boost::asio::buffer(d3));
  525. * bytes_transferred = sock.send(bufs2); @endcode
  526. */
  527. /*@{*/
  528. /// Create a new modifiable buffer from an existing buffer.
  529. /**
  530. * @returns <tt>mutable_buffers_1(b)</tt>.
  531. */
  532. inline mutable_buffers_1 buffer(const mutable_buffer& b)
  533. {
  534. return mutable_buffers_1(b);
  535. }
  536. /// Create a new modifiable buffer from an existing buffer.
  537. /**
  538. * @returns A mutable_buffers_1 value equivalent to:
  539. * @code mutable_buffers_1(
  540. * buffer_cast<void*>(b),
  541. * min(buffer_size(b), max_size_in_bytes)); @endcode
  542. */
  543. inline mutable_buffers_1 buffer(const mutable_buffer& b,
  544. std::size_t max_size_in_bytes)
  545. {
  546. return mutable_buffers_1(
  547. mutable_buffer(buffer_cast<void*>(b),
  548. buffer_size(b) < max_size_in_bytes
  549. ? buffer_size(b) : max_size_in_bytes
  550. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  551. , b.get_debug_check()
  552. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  553. ));
  554. }
  555. /// Create a new non-modifiable buffer from an existing buffer.
  556. /**
  557. * @returns <tt>const_buffers_1(b)</tt>.
  558. */
  559. inline const_buffers_1 buffer(const const_buffer& b)
  560. {
  561. return const_buffers_1(b);
  562. }
  563. /// Create a new non-modifiable buffer from an existing buffer.
  564. /**
  565. * @returns A const_buffers_1 value equivalent to:
  566. * @code const_buffers_1(
  567. * buffer_cast<const void*>(b),
  568. * min(buffer_size(b), max_size_in_bytes)); @endcode
  569. */
  570. inline const_buffers_1 buffer(const const_buffer& b,
  571. std::size_t max_size_in_bytes)
  572. {
  573. return const_buffers_1(
  574. const_buffer(buffer_cast<const void*>(b),
  575. buffer_size(b) < max_size_in_bytes
  576. ? buffer_size(b) : max_size_in_bytes
  577. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  578. , b.get_debug_check()
  579. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  580. ));
  581. }
  582. /// Create a new modifiable buffer that represents the given memory range.
  583. /**
  584. * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>.
  585. */
  586. inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
  587. {
  588. return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
  589. }
  590. /// Create a new non-modifiable buffer that represents the given memory range.
  591. /**
  592. * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>.
  593. */
  594. inline const_buffers_1 buffer(const void* data,
  595. std::size_t size_in_bytes)
  596. {
  597. return const_buffers_1(const_buffer(data, size_in_bytes));
  598. }
  599. /// Create a new modifiable buffer that represents the given POD array.
  600. /**
  601. * @returns A mutable_buffers_1 value equivalent to:
  602. * @code mutable_buffers_1(
  603. * static_cast<void*>(data),
  604. * N * sizeof(PodType)); @endcode
  605. */
  606. template <typename PodType, std::size_t N>
  607. inline mutable_buffers_1 buffer(PodType (&data)[N])
  608. {
  609. return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
  610. }
  611. /// Create a new modifiable buffer that represents the given POD array.
  612. /**
  613. * @returns A mutable_buffers_1 value equivalent to:
  614. * @code mutable_buffers_1(
  615. * static_cast<void*>(data),
  616. * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
  617. */
  618. template <typename PodType, std::size_t N>
  619. inline mutable_buffers_1 buffer(PodType (&data)[N],
  620. std::size_t max_size_in_bytes)
  621. {
  622. return mutable_buffers_1(
  623. mutable_buffer(data,
  624. N * sizeof(PodType) < max_size_in_bytes
  625. ? N * sizeof(PodType) : max_size_in_bytes));
  626. }
  627. /// Create a new non-modifiable buffer that represents the given POD array.
  628. /**
  629. * @returns A const_buffers_1 value equivalent to:
  630. * @code const_buffers_1(
  631. * static_cast<const void*>(data),
  632. * N * sizeof(PodType)); @endcode
  633. */
  634. template <typename PodType, std::size_t N>
  635. inline const_buffers_1 buffer(const PodType (&data)[N])
  636. {
  637. return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
  638. }
  639. /// Create a new non-modifiable buffer that represents the given POD array.
  640. /**
  641. * @returns A const_buffers_1 value equivalent to:
  642. * @code const_buffers_1(
  643. * static_cast<const void*>(data),
  644. * min(N * sizeof(PodType), max_size_in_bytes)); @endcode
  645. */
  646. template <typename PodType, std::size_t N>
  647. inline const_buffers_1 buffer(const PodType (&data)[N],
  648. std::size_t max_size_in_bytes)
  649. {
  650. return const_buffers_1(
  651. const_buffer(data,
  652. N * sizeof(PodType) < max_size_in_bytes
  653. ? N * sizeof(PodType) : max_size_in_bytes));
  654. }
  655. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
  656. || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
  657. // Borland C++ and Sun Studio think the overloads:
  658. //
  659. // unspecified buffer(boost::array<PodType, N>& array ...);
  660. //
  661. // and
  662. //
  663. // unspecified buffer(boost::array<const PodType, N>& array ...);
  664. //
  665. // are ambiguous. This will be worked around by using a buffer_types traits
  666. // class that contains typedefs for the appropriate buffer and container
  667. // classes, based on whether PodType is const or non-const.
  668. namespace detail {
  669. template <bool IsConst>
  670. struct buffer_types_base;
  671. template <>
  672. struct buffer_types_base<false>
  673. {
  674. typedef mutable_buffer buffer_type;
  675. typedef mutable_buffers_1 container_type;
  676. };
  677. template <>
  678. struct buffer_types_base<true>
  679. {
  680. typedef const_buffer buffer_type;
  681. typedef const_buffers_1 container_type;
  682. };
  683. template <typename PodType>
  684. struct buffer_types
  685. : public buffer_types_base<boost::is_const<PodType>::value>
  686. {
  687. };
  688. } // namespace detail
  689. template <typename PodType, std::size_t N>
  690. inline typename detail::buffer_types<PodType>::container_type
  691. buffer(boost::array<PodType, N>& data)
  692. {
  693. typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
  694. buffer_type;
  695. typedef typename boost::asio::detail::buffer_types<PodType>::container_type
  696. container_type;
  697. return container_type(
  698. buffer_type(data.c_array(), data.size() * sizeof(PodType)));
  699. }
  700. template <typename PodType, std::size_t N>
  701. inline typename detail::buffer_types<PodType>::container_type
  702. buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
  703. {
  704. typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
  705. buffer_type;
  706. typedef typename boost::asio::detail::buffer_types<PodType>::container_type
  707. container_type;
  708. return container_type(
  709. buffer_type(data.c_array(),
  710. data.size() * sizeof(PodType) < max_size_in_bytes
  711. ? data.size() * sizeof(PodType) : max_size_in_bytes));
  712. }
  713. #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
  714. // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
  715. /// Create a new modifiable buffer that represents the given POD array.
  716. /**
  717. * @returns A mutable_buffers_1 value equivalent to:
  718. * @code mutable_buffers_1(
  719. * data.data(),
  720. * data.size() * sizeof(PodType)); @endcode
  721. */
  722. template <typename PodType, std::size_t N>
  723. inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
  724. {
  725. return mutable_buffers_1(
  726. mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
  727. }
  728. /// Create a new modifiable buffer that represents the given POD array.
  729. /**
  730. * @returns A mutable_buffers_1 value equivalent to:
  731. * @code mutable_buffers_1(
  732. * data.data(),
  733. * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
  734. */
  735. template <typename PodType, std::size_t N>
  736. inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
  737. std::size_t max_size_in_bytes)
  738. {
  739. return mutable_buffers_1(
  740. mutable_buffer(data.c_array(),
  741. data.size() * sizeof(PodType) < max_size_in_bytes
  742. ? data.size() * sizeof(PodType) : max_size_in_bytes));
  743. }
  744. /// Create a new non-modifiable buffer that represents the given POD array.
  745. /**
  746. * @returns A const_buffers_1 value equivalent to:
  747. * @code const_buffers_1(
  748. * data.data(),
  749. * data.size() * sizeof(PodType)); @endcode
  750. */
  751. template <typename PodType, std::size_t N>
  752. inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
  753. {
  754. return const_buffers_1(
  755. const_buffer(data.data(), data.size() * sizeof(PodType)));
  756. }
  757. /// Create a new non-modifiable buffer that represents the given POD array.
  758. /**
  759. * @returns A const_buffers_1 value equivalent to:
  760. * @code const_buffers_1(
  761. * data.data(),
  762. * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
  763. */
  764. template <typename PodType, std::size_t N>
  765. inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
  766. std::size_t max_size_in_bytes)
  767. {
  768. return const_buffers_1(
  769. const_buffer(data.data(),
  770. data.size() * sizeof(PodType) < max_size_in_bytes
  771. ? data.size() * sizeof(PodType) : max_size_in_bytes));
  772. }
  773. #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
  774. // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
  775. /// Create a new non-modifiable buffer that represents the given POD array.
  776. /**
  777. * @returns A const_buffers_1 value equivalent to:
  778. * @code const_buffers_1(
  779. * data.data(),
  780. * data.size() * sizeof(PodType)); @endcode
  781. */
  782. template <typename PodType, std::size_t N>
  783. inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
  784. {
  785. return const_buffers_1(
  786. const_buffer(data.data(), data.size() * sizeof(PodType)));
  787. }
  788. /// Create a new non-modifiable buffer that represents the given POD array.
  789. /**
  790. * @returns A const_buffers_1 value equivalent to:
  791. * @code const_buffers_1(
  792. * data.data(),
  793. * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
  794. */
  795. template <typename PodType, std::size_t N>
  796. inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
  797. std::size_t max_size_in_bytes)
  798. {
  799. return const_buffers_1(
  800. const_buffer(data.data(),
  801. data.size() * sizeof(PodType) < max_size_in_bytes
  802. ? data.size() * sizeof(PodType) : max_size_in_bytes));
  803. }
  804. /// Create a new modifiable buffer that represents the given POD vector.
  805. /**
  806. * @returns A mutable_buffers_1 value equivalent to:
  807. * @code mutable_buffers_1(
  808. * data.size() ? &data[0] : 0,
  809. * data.size() * sizeof(PodType)); @endcode
  810. *
  811. * @note The buffer is invalidated by any vector operation that would also
  812. * invalidate iterators.
  813. */
  814. template <typename PodType, typename Allocator>
  815. inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
  816. {
  817. return mutable_buffers_1(
  818. mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
  819. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  820. , detail::buffer_debug_check<
  821. typename std::vector<PodType, Allocator>::iterator
  822. >(data.begin())
  823. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  824. ));
  825. }
  826. /// Create a new modifiable buffer that represents the given POD vector.
  827. /**
  828. * @returns A mutable_buffers_1 value equivalent to:
  829. * @code mutable_buffers_1(
  830. * data.size() ? &data[0] : 0,
  831. * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
  832. *
  833. * @note The buffer is invalidated by any vector operation that would also
  834. * invalidate iterators.
  835. */
  836. template <typename PodType, typename Allocator>
  837. inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
  838. std::size_t max_size_in_bytes)
  839. {
  840. return mutable_buffers_1(
  841. mutable_buffer(data.size() ? &data[0] : 0,
  842. data.size() * sizeof(PodType) < max_size_in_bytes
  843. ? data.size() * sizeof(PodType) : max_size_in_bytes
  844. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  845. , detail::buffer_debug_check<
  846. typename std::vector<PodType, Allocator>::iterator
  847. >(data.begin())
  848. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  849. ));
  850. }
  851. /// Create a new non-modifiable buffer that represents the given POD vector.
  852. /**
  853. * @returns A const_buffers_1 value equivalent to:
  854. * @code const_buffers_1(
  855. * data.size() ? &data[0] : 0,
  856. * data.size() * sizeof(PodType)); @endcode
  857. *
  858. * @note The buffer is invalidated by any vector operation that would also
  859. * invalidate iterators.
  860. */
  861. template <typename PodType, typename Allocator>
  862. inline const_buffers_1 buffer(
  863. const std::vector<PodType, Allocator>& data)
  864. {
  865. return const_buffers_1(
  866. const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
  867. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  868. , detail::buffer_debug_check<
  869. typename std::vector<PodType, Allocator>::const_iterator
  870. >(data.begin())
  871. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  872. ));
  873. }
  874. /// Create a new non-modifiable buffer that represents the given POD vector.
  875. /**
  876. * @returns A const_buffers_1 value equivalent to:
  877. * @code const_buffers_1(
  878. * data.size() ? &data[0] : 0,
  879. * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
  880. *
  881. * @note The buffer is invalidated by any vector operation that would also
  882. * invalidate iterators.
  883. */
  884. template <typename PodType, typename Allocator>
  885. inline const_buffers_1 buffer(
  886. const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
  887. {
  888. return const_buffers_1(
  889. const_buffer(data.size() ? &data[0] : 0,
  890. data.size() * sizeof(PodType) < max_size_in_bytes
  891. ? data.size() * sizeof(PodType) : max_size_in_bytes
  892. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  893. , detail::buffer_debug_check<
  894. typename std::vector<PodType, Allocator>::const_iterator
  895. >(data.begin())
  896. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  897. ));
  898. }
  899. /// Create a new non-modifiable buffer that represents the given string.
  900. /**
  901. * @returns <tt>const_buffers_1(data.data(), data.size())</tt>.
  902. *
  903. * @note The buffer is invalidated by any non-const operation called on the
  904. * given string object.
  905. */
  906. inline const_buffers_1 buffer(const std::string& data)
  907. {
  908. return const_buffers_1(const_buffer(data.data(), data.size()
  909. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  910. , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
  911. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  912. ));
  913. }
  914. /// Create a new non-modifiable buffer that represents the given string.
  915. /**
  916. * @returns A const_buffers_1 value equivalent to:
  917. * @code const_buffers_1(
  918. * data.data(),
  919. * min(data.size(), max_size_in_bytes)); @endcode
  920. *
  921. * @note The buffer is invalidated by any non-const operation called on the
  922. * given string object.
  923. */
  924. inline const_buffers_1 buffer(const std::string& data,
  925. std::size_t max_size_in_bytes)
  926. {
  927. return const_buffers_1(
  928. const_buffer(data.data(),
  929. data.size() < max_size_in_bytes
  930. ? data.size() : max_size_in_bytes
  931. #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
  932. , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
  933. #endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
  934. ));
  935. }
  936. /*@}*/
  937. } // namespace asio
  938. } // namespace boost
  939. #include <boost/asio/detail/pop_options.hpp>
  940. #endif // BOOST_ASIO_BUFFER_HPP