buffer.hpp 66 KB

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