buffer.hpp 30 KB

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