buffer.hpp 91 KB

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