buffer.hpp 68 KB

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