buffer.hpp 86 KB

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