read_until.hpp 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941
  1. //
  2. // impl/read_until.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_IMPL_READ_UNTIL_HPP
  11. #define ASIO_IMPL_READ_UNTIL_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include <string>
  17. #include <vector>
  18. #include <utility>
  19. #include "asio/associator.hpp"
  20. #include "asio/buffer.hpp"
  21. #include "asio/buffers_iterator.hpp"
  22. #include "asio/detail/base_from_cancellation_state.hpp"
  23. #include "asio/detail/bind_handler.hpp"
  24. #include "asio/detail/handler_cont_helpers.hpp"
  25. #include "asio/detail/handler_tracking.hpp"
  26. #include "asio/detail/handler_type_requirements.hpp"
  27. #include "asio/detail/limits.hpp"
  28. #include "asio/detail/non_const_lvalue.hpp"
  29. #include "asio/detail/throw_error.hpp"
  30. #include "asio/detail/push_options.hpp"
  31. namespace asio {
  32. namespace detail
  33. {
  34. // Algorithm that finds a subsequence of equal values in a sequence. Returns
  35. // (iterator,true) if a full match was found, in which case the iterator
  36. // points to the beginning of the match. Returns (iterator,false) if a
  37. // partial match was found at the end of the first sequence, in which case
  38. // the iterator points to the beginning of the partial match. Returns
  39. // (last1,false) if no full or partial match was found.
  40. template <typename Iterator1, typename Iterator2>
  41. std::pair<Iterator1, bool> partial_search(
  42. Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
  43. {
  44. for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
  45. {
  46. Iterator1 test_iter1 = iter1;
  47. Iterator2 test_iter2 = first2;
  48. for (;; ++test_iter1, ++test_iter2)
  49. {
  50. if (test_iter2 == last2)
  51. return std::make_pair(iter1, true);
  52. if (test_iter1 == last1)
  53. {
  54. if (test_iter2 != first2)
  55. return std::make_pair(iter1, false);
  56. else
  57. break;
  58. }
  59. if (*test_iter1 != *test_iter2)
  60. break;
  61. }
  62. }
  63. return std::make_pair(last1, false);
  64. }
  65. } // namespace detail
  66. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  67. template <typename SyncReadStream, typename DynamicBuffer_v1>
  68. inline std::size_t read_until(SyncReadStream& s,
  69. DynamicBuffer_v1&& buffers, char delim,
  70. constraint_t<
  71. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  72. >,
  73. constraint_t<
  74. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  75. >)
  76. {
  77. asio::error_code ec;
  78. std::size_t bytes_transferred = read_until(s,
  79. static_cast<DynamicBuffer_v1&&>(buffers), delim, ec);
  80. asio::detail::throw_error(ec, "read_until");
  81. return bytes_transferred;
  82. }
  83. template <typename SyncReadStream, typename DynamicBuffer_v1>
  84. std::size_t read_until(SyncReadStream& s,
  85. DynamicBuffer_v1&& buffers,
  86. char delim, asio::error_code& ec,
  87. constraint_t<
  88. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  89. >,
  90. constraint_t<
  91. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  92. >)
  93. {
  94. decay_t<DynamicBuffer_v1> b(
  95. static_cast<DynamicBuffer_v1&&>(buffers));
  96. std::size_t search_position = 0;
  97. for (;;)
  98. {
  99. // Determine the range of the data to be searched.
  100. typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
  101. typedef buffers_iterator<buffers_type> iterator;
  102. buffers_type data_buffers = b.data();
  103. iterator begin = iterator::begin(data_buffers);
  104. iterator start_pos = begin + search_position;
  105. iterator end = iterator::end(data_buffers);
  106. // Look for a match.
  107. iterator iter = std::find(start_pos, end, delim);
  108. if (iter != end)
  109. {
  110. // Found a match. We're done.
  111. ec = asio::error_code();
  112. return iter - begin + 1;
  113. }
  114. else
  115. {
  116. // No match. Next search can start with the new data.
  117. search_position = end - begin;
  118. }
  119. // Check if buffer is full.
  120. if (b.size() == b.max_size())
  121. {
  122. ec = error::not_found;
  123. return 0;
  124. }
  125. // Need more data.
  126. std::size_t bytes_to_read = std::min<std::size_t>(
  127. std::max<std::size_t>(512, b.capacity() - b.size()),
  128. std::min<std::size_t>(65536, b.max_size() - b.size()));
  129. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  130. if (ec)
  131. return 0;
  132. }
  133. }
  134. template <typename SyncReadStream, typename DynamicBuffer_v1>
  135. inline std::size_t read_until(SyncReadStream& s,
  136. DynamicBuffer_v1&& buffers,
  137. ASIO_STRING_VIEW_PARAM delim,
  138. constraint_t<
  139. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  140. >,
  141. constraint_t<
  142. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  143. >)
  144. {
  145. asio::error_code ec;
  146. std::size_t bytes_transferred = read_until(s,
  147. static_cast<DynamicBuffer_v1&&>(buffers), delim, ec);
  148. asio::detail::throw_error(ec, "read_until");
  149. return bytes_transferred;
  150. }
  151. template <typename SyncReadStream, typename DynamicBuffer_v1>
  152. std::size_t read_until(SyncReadStream& s,
  153. DynamicBuffer_v1&& buffers,
  154. ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,
  155. constraint_t<
  156. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  157. >,
  158. constraint_t<
  159. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  160. >)
  161. {
  162. decay_t<DynamicBuffer_v1> b(
  163. static_cast<DynamicBuffer_v1&&>(buffers));
  164. std::size_t search_position = 0;
  165. for (;;)
  166. {
  167. // Determine the range of the data to be searched.
  168. typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
  169. typedef buffers_iterator<buffers_type> iterator;
  170. buffers_type data_buffers = b.data();
  171. iterator begin = iterator::begin(data_buffers);
  172. iterator start_pos = begin + search_position;
  173. iterator end = iterator::end(data_buffers);
  174. // Look for a match.
  175. std::pair<iterator, bool> result = detail::partial_search(
  176. start_pos, end, delim.begin(), delim.end());
  177. if (result.first != end)
  178. {
  179. if (result.second)
  180. {
  181. // Full match. We're done.
  182. ec = asio::error_code();
  183. return result.first - begin + delim.length();
  184. }
  185. else
  186. {
  187. // Partial match. Next search needs to start from beginning of match.
  188. search_position = result.first - begin;
  189. }
  190. }
  191. else
  192. {
  193. // No match. Next search can start with the new data.
  194. search_position = end - begin;
  195. }
  196. // Check if buffer is full.
  197. if (b.size() == b.max_size())
  198. {
  199. ec = error::not_found;
  200. return 0;
  201. }
  202. // Need more data.
  203. std::size_t bytes_to_read = std::min<std::size_t>(
  204. std::max<std::size_t>(512, b.capacity() - b.size()),
  205. std::min<std::size_t>(65536, b.max_size() - b.size()));
  206. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  207. if (ec)
  208. return 0;
  209. }
  210. }
  211. #if !defined(ASIO_NO_EXTENSIONS)
  212. #if defined(ASIO_HAS_BOOST_REGEX)
  213. namespace detail {
  214. struct regex_match_flags
  215. {
  216. template <typename T>
  217. operator T() const
  218. {
  219. return T::match_default | T::match_partial;
  220. }
  221. };
  222. } // namespace detail
  223. template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits>
  224. inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers,
  225. const boost::basic_regex<char, Traits>& expr,
  226. constraint_t<
  227. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  228. >,
  229. constraint_t<
  230. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  231. >)
  232. {
  233. asio::error_code ec;
  234. std::size_t bytes_transferred = read_until(s,
  235. static_cast<DynamicBuffer_v1&&>(buffers), expr, ec);
  236. asio::detail::throw_error(ec, "read_until");
  237. return bytes_transferred;
  238. }
  239. template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits>
  240. std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers,
  241. const boost::basic_regex<char, Traits>& expr, asio::error_code& ec,
  242. constraint_t<
  243. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  244. >,
  245. constraint_t<
  246. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  247. >)
  248. {
  249. decay_t<DynamicBuffer_v1> b(
  250. static_cast<DynamicBuffer_v1&&>(buffers));
  251. std::size_t search_position = 0;
  252. for (;;)
  253. {
  254. // Determine the range of the data to be searched.
  255. typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
  256. typedef buffers_iterator<buffers_type> iterator;
  257. buffers_type data_buffers = b.data();
  258. iterator begin = iterator::begin(data_buffers);
  259. iterator start_pos = begin + search_position;
  260. iterator end = iterator::end(data_buffers);
  261. // Look for a match.
  262. boost::match_results<iterator,
  263. typename std::vector<boost::sub_match<iterator>>::allocator_type>
  264. match_results;
  265. if (regex_search(start_pos, end, match_results,
  266. expr, detail::regex_match_flags()))
  267. {
  268. if (match_results[0].matched)
  269. {
  270. // Full match. We're done.
  271. ec = asio::error_code();
  272. return match_results[0].second - begin;
  273. }
  274. else
  275. {
  276. // Partial match. Next search needs to start from beginning of match.
  277. search_position = match_results[0].first - begin;
  278. }
  279. }
  280. else
  281. {
  282. // No match. Next search can start with the new data.
  283. search_position = end - begin;
  284. }
  285. // Check if buffer is full.
  286. if (b.size() == b.max_size())
  287. {
  288. ec = error::not_found;
  289. return 0;
  290. }
  291. // Need more data.
  292. std::size_t bytes_to_read = std::min<std::size_t>(
  293. std::max<std::size_t>(512, b.capacity() - b.size()),
  294. std::min<std::size_t>(65536, b.max_size() - b.size()));
  295. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  296. if (ec)
  297. return 0;
  298. }
  299. }
  300. #endif // defined(ASIO_HAS_BOOST_REGEX)
  301. template <typename SyncReadStream,
  302. typename DynamicBuffer_v1, typename MatchCondition>
  303. inline std::size_t read_until(SyncReadStream& s,
  304. DynamicBuffer_v1&& buffers,
  305. MatchCondition match_condition,
  306. constraint_t<
  307. is_match_condition<MatchCondition>::value
  308. >,
  309. constraint_t<
  310. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  311. >,
  312. constraint_t<
  313. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  314. >)
  315. {
  316. asio::error_code ec;
  317. std::size_t bytes_transferred = read_until(s,
  318. static_cast<DynamicBuffer_v1&&>(buffers),
  319. match_condition, ec);
  320. asio::detail::throw_error(ec, "read_until");
  321. return bytes_transferred;
  322. }
  323. template <typename SyncReadStream,
  324. typename DynamicBuffer_v1, typename MatchCondition>
  325. std::size_t read_until(SyncReadStream& s,
  326. DynamicBuffer_v1&& buffers,
  327. MatchCondition match_condition, asio::error_code& ec,
  328. constraint_t<
  329. is_match_condition<MatchCondition>::value
  330. >,
  331. constraint_t<
  332. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  333. >,
  334. constraint_t<
  335. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  336. >)
  337. {
  338. decay_t<DynamicBuffer_v1> b(
  339. static_cast<DynamicBuffer_v1&&>(buffers));
  340. std::size_t search_position = 0;
  341. for (;;)
  342. {
  343. // Determine the range of the data to be searched.
  344. typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
  345. typedef buffers_iterator<buffers_type> iterator;
  346. buffers_type data_buffers = b.data();
  347. iterator begin = iterator::begin(data_buffers);
  348. iterator start_pos = begin + search_position;
  349. iterator end = iterator::end(data_buffers);
  350. // Look for a match.
  351. std::pair<iterator, bool> result = match_condition(start_pos, end);
  352. if (result.second)
  353. {
  354. // Full match. We're done.
  355. ec = asio::error_code();
  356. return result.first - begin;
  357. }
  358. else if (result.first != end)
  359. {
  360. // Partial match. Next search needs to start from beginning of match.
  361. search_position = result.first - begin;
  362. }
  363. else
  364. {
  365. // No match. Next search can start with the new data.
  366. search_position = end - begin;
  367. }
  368. // Check if buffer is full.
  369. if (b.size() == b.max_size())
  370. {
  371. ec = error::not_found;
  372. return 0;
  373. }
  374. // Need more data.
  375. std::size_t bytes_to_read = std::min<std::size_t>(
  376. std::max<std::size_t>(512, b.capacity() - b.size()),
  377. std::min<std::size_t>(65536, b.max_size() - b.size()));
  378. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  379. if (ec)
  380. return 0;
  381. }
  382. }
  383. #if !defined(ASIO_NO_IOSTREAM)
  384. template <typename SyncReadStream, typename Allocator>
  385. inline std::size_t read_until(SyncReadStream& s,
  386. asio::basic_streambuf<Allocator>& b, char delim)
  387. {
  388. return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
  389. }
  390. template <typename SyncReadStream, typename Allocator>
  391. inline std::size_t read_until(SyncReadStream& s,
  392. asio::basic_streambuf<Allocator>& b, char delim,
  393. asio::error_code& ec)
  394. {
  395. return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
  396. }
  397. template <typename SyncReadStream, typename Allocator>
  398. inline std::size_t read_until(SyncReadStream& s,
  399. asio::basic_streambuf<Allocator>& b,
  400. ASIO_STRING_VIEW_PARAM delim)
  401. {
  402. return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
  403. }
  404. template <typename SyncReadStream, typename Allocator>
  405. inline std::size_t read_until(SyncReadStream& s,
  406. asio::basic_streambuf<Allocator>& b,
  407. ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec)
  408. {
  409. return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
  410. }
  411. #if defined(ASIO_HAS_BOOST_REGEX)
  412. template <typename SyncReadStream, typename Allocator, typename Traits>
  413. inline std::size_t read_until(SyncReadStream& s,
  414. asio::basic_streambuf<Allocator>& b,
  415. const boost::basic_regex<char, Traits>& expr)
  416. {
  417. return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
  418. }
  419. template <typename SyncReadStream, typename Allocator, typename Traits>
  420. inline std::size_t read_until(SyncReadStream& s,
  421. asio::basic_streambuf<Allocator>& b,
  422. const boost::basic_regex<char, Traits>& expr,
  423. asio::error_code& ec)
  424. {
  425. return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
  426. }
  427. #endif // defined(ASIO_HAS_BOOST_REGEX)
  428. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  429. inline std::size_t read_until(SyncReadStream& s,
  430. asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
  431. constraint_t<is_match_condition<MatchCondition>::value>)
  432. {
  433. return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
  434. }
  435. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  436. inline std::size_t read_until(SyncReadStream& s,
  437. asio::basic_streambuf<Allocator>& b,
  438. MatchCondition match_condition, asio::error_code& ec,
  439. constraint_t<is_match_condition<MatchCondition>::value>)
  440. {
  441. return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
  442. }
  443. #endif // !defined(ASIO_NO_IOSTREAM)
  444. #endif // !defined(ASIO_NO_EXTENSIONS)
  445. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  446. template <typename SyncReadStream, typename DynamicBuffer_v2>
  447. inline std::size_t read_until(SyncReadStream& s,
  448. DynamicBuffer_v2 buffers, char delim,
  449. constraint_t<
  450. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  451. >)
  452. {
  453. asio::error_code ec;
  454. std::size_t bytes_transferred = read_until(s,
  455. static_cast<DynamicBuffer_v2&&>(buffers), delim, ec);
  456. asio::detail::throw_error(ec, "read_until");
  457. return bytes_transferred;
  458. }
  459. template <typename SyncReadStream, typename DynamicBuffer_v2>
  460. std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
  461. char delim, asio::error_code& ec,
  462. constraint_t<
  463. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  464. >)
  465. {
  466. DynamicBuffer_v2& b = buffers;
  467. std::size_t search_position = 0;
  468. for (;;)
  469. {
  470. // Determine the range of the data to be searched.
  471. typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
  472. typedef buffers_iterator<buffers_type> iterator;
  473. buffers_type data_buffers =
  474. const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
  475. iterator begin = iterator::begin(data_buffers);
  476. iterator start_pos = begin + search_position;
  477. iterator end = iterator::end(data_buffers);
  478. // Look for a match.
  479. iterator iter = std::find(start_pos, end, delim);
  480. if (iter != end)
  481. {
  482. // Found a match. We're done.
  483. ec = asio::error_code();
  484. return iter - begin + 1;
  485. }
  486. else
  487. {
  488. // No match. Next search can start with the new data.
  489. search_position = end - begin;
  490. }
  491. // Check if buffer is full.
  492. if (b.size() == b.max_size())
  493. {
  494. ec = error::not_found;
  495. return 0;
  496. }
  497. // Need more data.
  498. std::size_t bytes_to_read = std::min<std::size_t>(
  499. std::max<std::size_t>(512, b.capacity() - b.size()),
  500. std::min<std::size_t>(65536, b.max_size() - b.size()));
  501. std::size_t pos = b.size();
  502. b.grow(bytes_to_read);
  503. std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
  504. b.shrink(bytes_to_read - bytes_transferred);
  505. if (ec)
  506. return 0;
  507. }
  508. }
  509. template <typename SyncReadStream, typename DynamicBuffer_v2>
  510. inline std::size_t read_until(SyncReadStream& s,
  511. DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,
  512. constraint_t<
  513. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  514. >)
  515. {
  516. asio::error_code ec;
  517. std::size_t bytes_transferred = read_until(s,
  518. static_cast<DynamicBuffer_v2&&>(buffers), delim, ec);
  519. asio::detail::throw_error(ec, "read_until");
  520. return bytes_transferred;
  521. }
  522. template <typename SyncReadStream, typename DynamicBuffer_v2>
  523. std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
  524. ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,
  525. constraint_t<
  526. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  527. >)
  528. {
  529. DynamicBuffer_v2& b = buffers;
  530. std::size_t search_position = 0;
  531. for (;;)
  532. {
  533. // Determine the range of the data to be searched.
  534. typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
  535. typedef buffers_iterator<buffers_type> iterator;
  536. buffers_type data_buffers =
  537. const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
  538. iterator begin = iterator::begin(data_buffers);
  539. iterator start_pos = begin + search_position;
  540. iterator end = iterator::end(data_buffers);
  541. // Look for a match.
  542. std::pair<iterator, bool> result = detail::partial_search(
  543. start_pos, end, delim.begin(), delim.end());
  544. if (result.first != end)
  545. {
  546. if (result.second)
  547. {
  548. // Full match. We're done.
  549. ec = asio::error_code();
  550. return result.first - begin + delim.length();
  551. }
  552. else
  553. {
  554. // Partial match. Next search needs to start from beginning of match.
  555. search_position = result.first - begin;
  556. }
  557. }
  558. else
  559. {
  560. // No match. Next search can start with the new data.
  561. search_position = end - begin;
  562. }
  563. // Check if buffer is full.
  564. if (b.size() == b.max_size())
  565. {
  566. ec = error::not_found;
  567. return 0;
  568. }
  569. // Need more data.
  570. std::size_t bytes_to_read = std::min<std::size_t>(
  571. std::max<std::size_t>(512, b.capacity() - b.size()),
  572. std::min<std::size_t>(65536, b.max_size() - b.size()));
  573. std::size_t pos = b.size();
  574. b.grow(bytes_to_read);
  575. std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
  576. b.shrink(bytes_to_read - bytes_transferred);
  577. if (ec)
  578. return 0;
  579. }
  580. }
  581. #if !defined(ASIO_NO_EXTENSIONS)
  582. #if defined(ASIO_HAS_BOOST_REGEX)
  583. template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits>
  584. inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
  585. const boost::basic_regex<char, Traits>& expr,
  586. constraint_t<
  587. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  588. >)
  589. {
  590. asio::error_code ec;
  591. std::size_t bytes_transferred = read_until(s,
  592. static_cast<DynamicBuffer_v2&&>(buffers), expr, ec);
  593. asio::detail::throw_error(ec, "read_until");
  594. return bytes_transferred;
  595. }
  596. template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits>
  597. std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
  598. const boost::basic_regex<char, Traits>& expr, asio::error_code& ec,
  599. constraint_t<
  600. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  601. >)
  602. {
  603. DynamicBuffer_v2& b = buffers;
  604. std::size_t search_position = 0;
  605. for (;;)
  606. {
  607. // Determine the range of the data to be searched.
  608. typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
  609. typedef buffers_iterator<buffers_type> iterator;
  610. buffers_type data_buffers =
  611. const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
  612. iterator begin = iterator::begin(data_buffers);
  613. iterator start_pos = begin + search_position;
  614. iterator end = iterator::end(data_buffers);
  615. // Look for a match.
  616. boost::match_results<iterator,
  617. typename std::vector<boost::sub_match<iterator>>::allocator_type>
  618. match_results;
  619. if (regex_search(start_pos, end, match_results,
  620. expr, detail::regex_match_flags()))
  621. {
  622. if (match_results[0].matched)
  623. {
  624. // Full match. We're done.
  625. ec = asio::error_code();
  626. return match_results[0].second - begin;
  627. }
  628. else
  629. {
  630. // Partial match. Next search needs to start from beginning of match.
  631. search_position = match_results[0].first - begin;
  632. }
  633. }
  634. else
  635. {
  636. // No match. Next search can start with the new data.
  637. search_position = end - begin;
  638. }
  639. // Check if buffer is full.
  640. if (b.size() == b.max_size())
  641. {
  642. ec = error::not_found;
  643. return 0;
  644. }
  645. // Need more data.
  646. std::size_t bytes_to_read = std::min<std::size_t>(
  647. std::max<std::size_t>(512, b.capacity() - b.size()),
  648. std::min<std::size_t>(65536, b.max_size() - b.size()));
  649. std::size_t pos = b.size();
  650. b.grow(bytes_to_read);
  651. std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
  652. b.shrink(bytes_to_read - bytes_transferred);
  653. if (ec)
  654. return 0;
  655. }
  656. }
  657. #endif // defined(ASIO_HAS_BOOST_REGEX)
  658. template <typename SyncReadStream,
  659. typename DynamicBuffer_v2, typename MatchCondition>
  660. inline std::size_t read_until(SyncReadStream& s,
  661. DynamicBuffer_v2 buffers, MatchCondition match_condition,
  662. constraint_t<
  663. is_match_condition<MatchCondition>::value
  664. >,
  665. constraint_t<
  666. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  667. >)
  668. {
  669. asio::error_code ec;
  670. std::size_t bytes_transferred = read_until(s,
  671. static_cast<DynamicBuffer_v2&&>(buffers),
  672. match_condition, ec);
  673. asio::detail::throw_error(ec, "read_until");
  674. return bytes_transferred;
  675. }
  676. template <typename SyncReadStream,
  677. typename DynamicBuffer_v2, typename MatchCondition>
  678. std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
  679. MatchCondition match_condition, asio::error_code& ec,
  680. constraint_t<
  681. is_match_condition<MatchCondition>::value
  682. >,
  683. constraint_t<
  684. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  685. >)
  686. {
  687. DynamicBuffer_v2& b = buffers;
  688. std::size_t search_position = 0;
  689. for (;;)
  690. {
  691. // Determine the range of the data to be searched.
  692. typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
  693. typedef buffers_iterator<buffers_type> iterator;
  694. buffers_type data_buffers =
  695. const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
  696. iterator begin = iterator::begin(data_buffers);
  697. iterator start_pos = begin + search_position;
  698. iterator end = iterator::end(data_buffers);
  699. // Look for a match.
  700. std::pair<iterator, bool> result = match_condition(start_pos, end);
  701. if (result.second)
  702. {
  703. // Full match. We're done.
  704. ec = asio::error_code();
  705. return result.first - begin;
  706. }
  707. else if (result.first != end)
  708. {
  709. // Partial match. Next search needs to start from beginning of match.
  710. search_position = result.first - begin;
  711. }
  712. else
  713. {
  714. // No match. Next search can start with the new data.
  715. search_position = end - begin;
  716. }
  717. // Check if buffer is full.
  718. if (b.size() == b.max_size())
  719. {
  720. ec = error::not_found;
  721. return 0;
  722. }
  723. // Need more data.
  724. std::size_t bytes_to_read = std::min<std::size_t>(
  725. std::max<std::size_t>(512, b.capacity() - b.size()),
  726. std::min<std::size_t>(65536, b.max_size() - b.size()));
  727. std::size_t pos = b.size();
  728. b.grow(bytes_to_read);
  729. std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
  730. b.shrink(bytes_to_read - bytes_transferred);
  731. if (ec)
  732. return 0;
  733. }
  734. }
  735. #endif // !defined(ASIO_NO_EXTENSIONS)
  736. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  737. namespace detail
  738. {
  739. template <typename AsyncReadStream,
  740. typename DynamicBuffer_v1, typename ReadHandler>
  741. class read_until_delim_op_v1
  742. : public base_from_cancellation_state<ReadHandler>
  743. {
  744. public:
  745. template <typename BufferSequence>
  746. read_until_delim_op_v1(AsyncReadStream& stream,
  747. BufferSequence&& buffers,
  748. char delim, ReadHandler& handler)
  749. : base_from_cancellation_state<ReadHandler>(
  750. handler, enable_partial_cancellation()),
  751. stream_(stream),
  752. buffers_(static_cast<BufferSequence&&>(buffers)),
  753. delim_(delim),
  754. start_(0),
  755. search_position_(0),
  756. handler_(static_cast<ReadHandler&&>(handler))
  757. {
  758. }
  759. read_until_delim_op_v1(const read_until_delim_op_v1& other)
  760. : base_from_cancellation_state<ReadHandler>(other),
  761. stream_(other.stream_),
  762. buffers_(other.buffers_),
  763. delim_(other.delim_),
  764. start_(other.start_),
  765. search_position_(other.search_position_),
  766. handler_(other.handler_)
  767. {
  768. }
  769. read_until_delim_op_v1(read_until_delim_op_v1&& other)
  770. : base_from_cancellation_state<ReadHandler>(
  771. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  772. stream_(other.stream_),
  773. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  774. delim_(other.delim_),
  775. start_(other.start_),
  776. search_position_(other.search_position_),
  777. handler_(static_cast<ReadHandler&&>(other.handler_))
  778. {
  779. }
  780. void operator()(asio::error_code ec,
  781. std::size_t bytes_transferred, int start = 0)
  782. {
  783. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  784. std::size_t bytes_to_read;
  785. switch (start_ = start)
  786. {
  787. case 1:
  788. for (;;)
  789. {
  790. {
  791. // Determine the range of the data to be searched.
  792. typedef typename DynamicBuffer_v1::const_buffers_type
  793. buffers_type;
  794. typedef buffers_iterator<buffers_type> iterator;
  795. buffers_type data_buffers = buffers_.data();
  796. iterator begin = iterator::begin(data_buffers);
  797. iterator start_pos = begin + search_position_;
  798. iterator end = iterator::end(data_buffers);
  799. // Look for a match.
  800. iterator iter = std::find(start_pos, end, delim_);
  801. if (iter != end)
  802. {
  803. // Found a match. We're done.
  804. search_position_ = iter - begin + 1;
  805. bytes_to_read = 0;
  806. }
  807. // No match yet. Check if buffer is full.
  808. else if (buffers_.size() == buffers_.max_size())
  809. {
  810. search_position_ = not_found;
  811. bytes_to_read = 0;
  812. }
  813. // Need to read some more data.
  814. else
  815. {
  816. // Next search can start with the new data.
  817. search_position_ = end - begin;
  818. bytes_to_read = std::min<std::size_t>(
  819. std::max<std::size_t>(512,
  820. buffers_.capacity() - buffers_.size()),
  821. std::min<std::size_t>(65536,
  822. buffers_.max_size() - buffers_.size()));
  823. }
  824. }
  825. // Check if we're done.
  826. if (!start && bytes_to_read == 0)
  827. break;
  828. // Start a new asynchronous read operation to obtain more data.
  829. {
  830. ASIO_HANDLER_LOCATION((
  831. __FILE__, __LINE__, "async_read_until"));
  832. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  833. static_cast<read_until_delim_op_v1&&>(*this));
  834. }
  835. return; default:
  836. buffers_.commit(bytes_transferred);
  837. if (ec || bytes_transferred == 0)
  838. break;
  839. if (this->cancelled() != cancellation_type::none)
  840. {
  841. ec = error::operation_aborted;
  842. break;
  843. }
  844. }
  845. const asio::error_code result_ec =
  846. (search_position_ == not_found)
  847. ? error::not_found : ec;
  848. const std::size_t result_n =
  849. (ec || search_position_ == not_found)
  850. ? 0 : search_position_;
  851. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  852. }
  853. }
  854. //private:
  855. AsyncReadStream& stream_;
  856. DynamicBuffer_v1 buffers_;
  857. char delim_;
  858. int start_;
  859. std::size_t search_position_;
  860. ReadHandler handler_;
  861. };
  862. template <typename AsyncReadStream,
  863. typename DynamicBuffer_v1, typename ReadHandler>
  864. inline bool asio_handler_is_continuation(
  865. read_until_delim_op_v1<AsyncReadStream,
  866. DynamicBuffer_v1, ReadHandler>* this_handler)
  867. {
  868. return this_handler->start_ == 0 ? true
  869. : asio_handler_cont_helpers::is_continuation(
  870. this_handler->handler_);
  871. }
  872. template <typename AsyncReadStream>
  873. class initiate_async_read_until_delim_v1
  874. {
  875. public:
  876. typedef typename AsyncReadStream::executor_type executor_type;
  877. explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)
  878. : stream_(stream)
  879. {
  880. }
  881. executor_type get_executor() const noexcept
  882. {
  883. return stream_.get_executor();
  884. }
  885. template <typename ReadHandler, typename DynamicBuffer_v1>
  886. void operator()(ReadHandler&& handler,
  887. DynamicBuffer_v1&& buffers,
  888. char delim) const
  889. {
  890. // If you get an error on the following line it means that your handler
  891. // does not meet the documented type requirements for a ReadHandler.
  892. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  893. non_const_lvalue<ReadHandler> handler2(handler);
  894. read_until_delim_op_v1<AsyncReadStream,
  895. decay_t<DynamicBuffer_v1>,
  896. decay_t<ReadHandler>>(
  897. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  898. delim, handler2.value)(asio::error_code(), 0, 1);
  899. }
  900. private:
  901. AsyncReadStream& stream_;
  902. };
  903. } // namespace detail
  904. #if !defined(GENERATING_DOCUMENTATION)
  905. template <template <typename, typename> class Associator,
  906. typename AsyncReadStream, typename DynamicBuffer_v1,
  907. typename ReadHandler, typename DefaultCandidate>
  908. struct associator<Associator,
  909. detail::read_until_delim_op_v1<AsyncReadStream,
  910. DynamicBuffer_v1, ReadHandler>,
  911. DefaultCandidate>
  912. : Associator<ReadHandler, DefaultCandidate>
  913. {
  914. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  915. const detail::read_until_delim_op_v1<AsyncReadStream,
  916. DynamicBuffer_v1, ReadHandler>& h) noexcept
  917. {
  918. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  919. }
  920. static auto get(
  921. const detail::read_until_delim_op_v1<AsyncReadStream,
  922. DynamicBuffer_v1, ReadHandler>& h,
  923. const DefaultCandidate& c) noexcept
  924. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  925. {
  926. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  927. }
  928. };
  929. #endif // !defined(GENERATING_DOCUMENTATION)
  930. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  931. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  932. std::size_t)) ReadToken>
  933. inline auto async_read_until(AsyncReadStream& s,
  934. DynamicBuffer_v1&& buffers, char delim, ReadToken&& token,
  935. constraint_t<
  936. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  937. >,
  938. constraint_t<
  939. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  940. >)
  941. -> decltype(
  942. async_initiate<ReadToken,
  943. void (asio::error_code, std::size_t)>(
  944. declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(),
  945. token, static_cast<DynamicBuffer_v1&&>(buffers), delim))
  946. {
  947. return async_initiate<ReadToken,
  948. void (asio::error_code, std::size_t)>(
  949. detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
  950. token, static_cast<DynamicBuffer_v1&&>(buffers), delim);
  951. }
  952. namespace detail
  953. {
  954. template <typename AsyncReadStream,
  955. typename DynamicBuffer_v1, typename ReadHandler>
  956. class read_until_delim_string_op_v1
  957. : public base_from_cancellation_state<ReadHandler>
  958. {
  959. public:
  960. template <typename BufferSequence>
  961. read_until_delim_string_op_v1(AsyncReadStream& stream,
  962. BufferSequence&& buffers,
  963. const std::string& delim, ReadHandler& handler)
  964. : base_from_cancellation_state<ReadHandler>(
  965. handler, enable_partial_cancellation()),
  966. stream_(stream),
  967. buffers_(static_cast<BufferSequence&&>(buffers)),
  968. delim_(delim),
  969. start_(0),
  970. search_position_(0),
  971. handler_(static_cast<ReadHandler&&>(handler))
  972. {
  973. }
  974. read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
  975. : base_from_cancellation_state<ReadHandler>(other),
  976. stream_(other.stream_),
  977. buffers_(other.buffers_),
  978. delim_(other.delim_),
  979. start_(other.start_),
  980. search_position_(other.search_position_),
  981. handler_(other.handler_)
  982. {
  983. }
  984. read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)
  985. : base_from_cancellation_state<ReadHandler>(
  986. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  987. stream_(other.stream_),
  988. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  989. delim_(static_cast<std::string&&>(other.delim_)),
  990. start_(other.start_),
  991. search_position_(other.search_position_),
  992. handler_(static_cast<ReadHandler&&>(other.handler_))
  993. {
  994. }
  995. void operator()(asio::error_code ec,
  996. std::size_t bytes_transferred, int start = 0)
  997. {
  998. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  999. std::size_t bytes_to_read;
  1000. switch (start_ = start)
  1001. {
  1002. case 1:
  1003. for (;;)
  1004. {
  1005. {
  1006. // Determine the range of the data to be searched.
  1007. typedef typename DynamicBuffer_v1::const_buffers_type
  1008. buffers_type;
  1009. typedef buffers_iterator<buffers_type> iterator;
  1010. buffers_type data_buffers = buffers_.data();
  1011. iterator begin = iterator::begin(data_buffers);
  1012. iterator start_pos = begin + search_position_;
  1013. iterator end = iterator::end(data_buffers);
  1014. // Look for a match.
  1015. std::pair<iterator, bool> result = detail::partial_search(
  1016. start_pos, end, delim_.begin(), delim_.end());
  1017. if (result.first != end && result.second)
  1018. {
  1019. // Full match. We're done.
  1020. search_position_ = result.first - begin + delim_.length();
  1021. bytes_to_read = 0;
  1022. }
  1023. // No match yet. Check if buffer is full.
  1024. else if (buffers_.size() == buffers_.max_size())
  1025. {
  1026. search_position_ = not_found;
  1027. bytes_to_read = 0;
  1028. }
  1029. // Need to read some more data.
  1030. else
  1031. {
  1032. if (result.first != end)
  1033. {
  1034. // Partial match. Next search needs to start from beginning of
  1035. // match.
  1036. search_position_ = result.first - begin;
  1037. }
  1038. else
  1039. {
  1040. // Next search can start with the new data.
  1041. search_position_ = end - begin;
  1042. }
  1043. bytes_to_read = std::min<std::size_t>(
  1044. std::max<std::size_t>(512,
  1045. buffers_.capacity() - buffers_.size()),
  1046. std::min<std::size_t>(65536,
  1047. buffers_.max_size() - buffers_.size()));
  1048. }
  1049. }
  1050. // Check if we're done.
  1051. if (!start && bytes_to_read == 0)
  1052. break;
  1053. // Start a new asynchronous read operation to obtain more data.
  1054. {
  1055. ASIO_HANDLER_LOCATION((
  1056. __FILE__, __LINE__, "async_read_until"));
  1057. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1058. static_cast<read_until_delim_string_op_v1&&>(*this));
  1059. }
  1060. return; default:
  1061. buffers_.commit(bytes_transferred);
  1062. if (ec || bytes_transferred == 0)
  1063. break;
  1064. if (this->cancelled() != cancellation_type::none)
  1065. {
  1066. ec = error::operation_aborted;
  1067. break;
  1068. }
  1069. }
  1070. const asio::error_code result_ec =
  1071. (search_position_ == not_found)
  1072. ? error::not_found : ec;
  1073. const std::size_t result_n =
  1074. (ec || search_position_ == not_found)
  1075. ? 0 : search_position_;
  1076. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  1077. }
  1078. }
  1079. //private:
  1080. AsyncReadStream& stream_;
  1081. DynamicBuffer_v1 buffers_;
  1082. std::string delim_;
  1083. int start_;
  1084. std::size_t search_position_;
  1085. ReadHandler handler_;
  1086. };
  1087. template <typename AsyncReadStream,
  1088. typename DynamicBuffer_v1, typename ReadHandler>
  1089. inline bool asio_handler_is_continuation(
  1090. read_until_delim_string_op_v1<AsyncReadStream,
  1091. DynamicBuffer_v1, ReadHandler>* this_handler)
  1092. {
  1093. return this_handler->start_ == 0 ? true
  1094. : asio_handler_cont_helpers::is_continuation(
  1095. this_handler->handler_);
  1096. }
  1097. template <typename AsyncReadStream>
  1098. class initiate_async_read_until_delim_string_v1
  1099. {
  1100. public:
  1101. typedef typename AsyncReadStream::executor_type executor_type;
  1102. explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)
  1103. : stream_(stream)
  1104. {
  1105. }
  1106. executor_type get_executor() const noexcept
  1107. {
  1108. return stream_.get_executor();
  1109. }
  1110. template <typename ReadHandler, typename DynamicBuffer_v1>
  1111. void operator()(ReadHandler&& handler,
  1112. DynamicBuffer_v1&& buffers,
  1113. const std::string& delim) const
  1114. {
  1115. // If you get an error on the following line it means that your handler
  1116. // does not meet the documented type requirements for a ReadHandler.
  1117. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1118. non_const_lvalue<ReadHandler> handler2(handler);
  1119. read_until_delim_string_op_v1<AsyncReadStream,
  1120. decay_t<DynamicBuffer_v1>,
  1121. decay_t<ReadHandler>>(
  1122. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  1123. delim, handler2.value)(asio::error_code(), 0, 1);
  1124. }
  1125. private:
  1126. AsyncReadStream& stream_;
  1127. };
  1128. } // namespace detail
  1129. #if !defined(GENERATING_DOCUMENTATION)
  1130. template <template <typename, typename> class Associator,
  1131. typename AsyncReadStream, typename DynamicBuffer_v1,
  1132. typename ReadHandler, typename DefaultCandidate>
  1133. struct associator<Associator,
  1134. detail::read_until_delim_string_op_v1<AsyncReadStream,
  1135. DynamicBuffer_v1, ReadHandler>,
  1136. DefaultCandidate>
  1137. : Associator<ReadHandler, DefaultCandidate>
  1138. {
  1139. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  1140. const detail::read_until_delim_string_op_v1<
  1141. AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h) noexcept
  1142. {
  1143. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1144. }
  1145. static auto get(
  1146. const detail::read_until_delim_string_op_v1<
  1147. AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h,
  1148. const DefaultCandidate& c) noexcept
  1149. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  1150. {
  1151. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1152. }
  1153. };
  1154. #endif // !defined(GENERATING_DOCUMENTATION)
  1155. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1156. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1157. std::size_t)) ReadToken>
  1158. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers,
  1159. ASIO_STRING_VIEW_PARAM delim, ReadToken&& token,
  1160. constraint_t<
  1161. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  1162. >,
  1163. constraint_t<
  1164. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  1165. >)
  1166. -> decltype(
  1167. async_initiate<ReadToken,
  1168. void (asio::error_code, std::size_t)>(
  1169. declval<detail::initiate_async_read_until_delim_string_v1<
  1170. AsyncReadStream>>(),
  1171. token, static_cast<DynamicBuffer_v1&&>(buffers),
  1172. static_cast<std::string>(delim)))
  1173. {
  1174. return async_initiate<ReadToken,
  1175. void (asio::error_code, std::size_t)>(
  1176. detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
  1177. token, static_cast<DynamicBuffer_v1&&>(buffers),
  1178. static_cast<std::string>(delim));
  1179. }
  1180. #if !defined(ASIO_NO_EXTENSIONS)
  1181. #if defined(ASIO_HAS_BOOST_REGEX)
  1182. namespace detail
  1183. {
  1184. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1185. typename RegEx, typename ReadHandler>
  1186. class read_until_expr_op_v1
  1187. : public base_from_cancellation_state<ReadHandler>
  1188. {
  1189. public:
  1190. template <typename BufferSequence, typename Traits>
  1191. read_until_expr_op_v1(AsyncReadStream& stream, BufferSequence&& buffers,
  1192. const boost::basic_regex<char, Traits>& expr, ReadHandler& handler)
  1193. : base_from_cancellation_state<ReadHandler>(
  1194. handler, enable_partial_cancellation()),
  1195. stream_(stream),
  1196. buffers_(static_cast<BufferSequence&&>(buffers)),
  1197. expr_(expr),
  1198. start_(0),
  1199. search_position_(0),
  1200. handler_(static_cast<ReadHandler&&>(handler))
  1201. {
  1202. }
  1203. read_until_expr_op_v1(const read_until_expr_op_v1& other)
  1204. : base_from_cancellation_state<ReadHandler>(other),
  1205. stream_(other.stream_),
  1206. buffers_(other.buffers_),
  1207. expr_(other.expr_),
  1208. start_(other.start_),
  1209. search_position_(other.search_position_),
  1210. handler_(other.handler_)
  1211. {
  1212. }
  1213. read_until_expr_op_v1(read_until_expr_op_v1&& other)
  1214. : base_from_cancellation_state<ReadHandler>(
  1215. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  1216. stream_(other.stream_),
  1217. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  1218. expr_(other.expr_),
  1219. start_(other.start_),
  1220. search_position_(other.search_position_),
  1221. handler_(static_cast<ReadHandler&&>(other.handler_))
  1222. {
  1223. }
  1224. void operator()(asio::error_code ec,
  1225. std::size_t bytes_transferred, int start = 0)
  1226. {
  1227. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1228. std::size_t bytes_to_read;
  1229. switch (start_ = start)
  1230. {
  1231. case 1:
  1232. for (;;)
  1233. {
  1234. {
  1235. // Determine the range of the data to be searched.
  1236. typedef typename DynamicBuffer_v1::const_buffers_type
  1237. buffers_type;
  1238. typedef buffers_iterator<buffers_type> iterator;
  1239. buffers_type data_buffers = buffers_.data();
  1240. iterator begin = iterator::begin(data_buffers);
  1241. iterator start_pos = begin + search_position_;
  1242. iterator end = iterator::end(data_buffers);
  1243. // Look for a match.
  1244. boost::match_results<iterator,
  1245. typename std::vector<boost::sub_match<iterator>>::allocator_type>
  1246. match_results;
  1247. bool match = regex_search(start_pos, end,
  1248. match_results, expr_, regex_match_flags());
  1249. if (match && match_results[0].matched)
  1250. {
  1251. // Full match. We're done.
  1252. search_position_ = match_results[0].second - begin;
  1253. bytes_to_read = 0;
  1254. }
  1255. // No match yet. Check if buffer is full.
  1256. else if (buffers_.size() == buffers_.max_size())
  1257. {
  1258. search_position_ = not_found;
  1259. bytes_to_read = 0;
  1260. }
  1261. // Need to read some more data.
  1262. else
  1263. {
  1264. if (match)
  1265. {
  1266. // Partial match. Next search needs to start from beginning of
  1267. // match.
  1268. search_position_ = match_results[0].first - begin;
  1269. }
  1270. else
  1271. {
  1272. // Next search can start with the new data.
  1273. search_position_ = end - begin;
  1274. }
  1275. bytes_to_read = std::min<std::size_t>(
  1276. std::max<std::size_t>(512,
  1277. buffers_.capacity() - buffers_.size()),
  1278. std::min<std::size_t>(65536,
  1279. buffers_.max_size() - buffers_.size()));
  1280. }
  1281. }
  1282. // Check if we're done.
  1283. if (!start && bytes_to_read == 0)
  1284. break;
  1285. // Start a new asynchronous read operation to obtain more data.
  1286. {
  1287. ASIO_HANDLER_LOCATION((
  1288. __FILE__, __LINE__, "async_read_until"));
  1289. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1290. static_cast<read_until_expr_op_v1&&>(*this));
  1291. }
  1292. return; default:
  1293. buffers_.commit(bytes_transferred);
  1294. if (ec || bytes_transferred == 0)
  1295. break;
  1296. if (this->cancelled() != cancellation_type::none)
  1297. {
  1298. ec = error::operation_aborted;
  1299. break;
  1300. }
  1301. }
  1302. const asio::error_code result_ec =
  1303. (search_position_ == not_found)
  1304. ? error::not_found : ec;
  1305. const std::size_t result_n =
  1306. (ec || search_position_ == not_found)
  1307. ? 0 : search_position_;
  1308. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  1309. }
  1310. }
  1311. //private:
  1312. AsyncReadStream& stream_;
  1313. DynamicBuffer_v1 buffers_;
  1314. RegEx expr_;
  1315. int start_;
  1316. std::size_t search_position_;
  1317. ReadHandler handler_;
  1318. };
  1319. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1320. typename RegEx, typename ReadHandler>
  1321. inline bool asio_handler_is_continuation(
  1322. read_until_expr_op_v1<AsyncReadStream,
  1323. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1324. {
  1325. return this_handler->start_ == 0 ? true
  1326. : asio_handler_cont_helpers::is_continuation(
  1327. this_handler->handler_);
  1328. }
  1329. template <typename AsyncReadStream>
  1330. class initiate_async_read_until_expr_v1
  1331. {
  1332. public:
  1333. typedef typename AsyncReadStream::executor_type executor_type;
  1334. explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)
  1335. : stream_(stream)
  1336. {
  1337. }
  1338. executor_type get_executor() const noexcept
  1339. {
  1340. return stream_.get_executor();
  1341. }
  1342. template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>
  1343. void operator()(ReadHandler&& handler,
  1344. DynamicBuffer_v1&& buffers, const RegEx& expr) const
  1345. {
  1346. // If you get an error on the following line it means that your handler
  1347. // does not meet the documented type requirements for a ReadHandler.
  1348. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1349. non_const_lvalue<ReadHandler> handler2(handler);
  1350. read_until_expr_op_v1<AsyncReadStream,
  1351. decay_t<DynamicBuffer_v1>,
  1352. RegEx, decay_t<ReadHandler>>(
  1353. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  1354. expr, handler2.value)(asio::error_code(), 0, 1);
  1355. }
  1356. private:
  1357. AsyncReadStream& stream_;
  1358. };
  1359. } // namespace detail
  1360. #if !defined(GENERATING_DOCUMENTATION)
  1361. template <template <typename, typename> class Associator,
  1362. typename AsyncReadStream, typename DynamicBuffer_v1,
  1363. typename RegEx, typename ReadHandler, typename DefaultCandidate>
  1364. struct associator<Associator,
  1365. detail::read_until_expr_op_v1<AsyncReadStream,
  1366. DynamicBuffer_v1, RegEx, ReadHandler>,
  1367. DefaultCandidate>
  1368. : Associator<ReadHandler, DefaultCandidate>
  1369. {
  1370. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  1371. const detail::read_until_expr_op_v1<AsyncReadStream,
  1372. DynamicBuffer_v1, RegEx, ReadHandler>& h) noexcept
  1373. {
  1374. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1375. }
  1376. static auto get(
  1377. const detail::read_until_expr_op_v1<AsyncReadStream,
  1378. DynamicBuffer_v1, RegEx, ReadHandler>& h,
  1379. const DefaultCandidate& c) noexcept
  1380. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  1381. {
  1382. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1383. }
  1384. };
  1385. #endif // !defined(GENERATING_DOCUMENTATION)
  1386. template <typename AsyncReadStream, typename DynamicBuffer_v1, typename Traits,
  1387. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1388. std::size_t)) ReadToken>
  1389. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers,
  1390. const boost::basic_regex<char, Traits>& expr, ReadToken&& token,
  1391. constraint_t<
  1392. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  1393. >,
  1394. constraint_t<
  1395. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  1396. >)
  1397. -> decltype(
  1398. async_initiate<ReadToken,
  1399. void (asio::error_code, std::size_t)>(
  1400. declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(),
  1401. token, static_cast<DynamicBuffer_v1&&>(buffers), expr))
  1402. {
  1403. return async_initiate<ReadToken,
  1404. void (asio::error_code, std::size_t)>(
  1405. detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
  1406. token, static_cast<DynamicBuffer_v1&&>(buffers), expr);
  1407. }
  1408. #endif // defined(ASIO_HAS_BOOST_REGEX)
  1409. namespace detail
  1410. {
  1411. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1412. typename MatchCondition, typename ReadHandler>
  1413. class read_until_match_op_v1
  1414. : public base_from_cancellation_state<ReadHandler>
  1415. {
  1416. public:
  1417. template <typename BufferSequence>
  1418. read_until_match_op_v1(AsyncReadStream& stream,
  1419. BufferSequence&& buffers,
  1420. MatchCondition match_condition, ReadHandler& handler)
  1421. : base_from_cancellation_state<ReadHandler>(
  1422. handler, enable_partial_cancellation()),
  1423. stream_(stream),
  1424. buffers_(static_cast<BufferSequence&&>(buffers)),
  1425. match_condition_(match_condition),
  1426. start_(0),
  1427. search_position_(0),
  1428. handler_(static_cast<ReadHandler&&>(handler))
  1429. {
  1430. }
  1431. read_until_match_op_v1(const read_until_match_op_v1& other)
  1432. : base_from_cancellation_state<ReadHandler>(other),
  1433. stream_(other.stream_),
  1434. buffers_(other.buffers_),
  1435. match_condition_(other.match_condition_),
  1436. start_(other.start_),
  1437. search_position_(other.search_position_),
  1438. handler_(other.handler_)
  1439. {
  1440. }
  1441. read_until_match_op_v1(read_until_match_op_v1&& other)
  1442. : base_from_cancellation_state<ReadHandler>(
  1443. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  1444. stream_(other.stream_),
  1445. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  1446. match_condition_(other.match_condition_),
  1447. start_(other.start_),
  1448. search_position_(other.search_position_),
  1449. handler_(static_cast<ReadHandler&&>(other.handler_))
  1450. {
  1451. }
  1452. void operator()(asio::error_code ec,
  1453. std::size_t bytes_transferred, int start = 0)
  1454. {
  1455. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1456. std::size_t bytes_to_read;
  1457. switch (start_ = start)
  1458. {
  1459. case 1:
  1460. for (;;)
  1461. {
  1462. {
  1463. // Determine the range of the data to be searched.
  1464. typedef typename DynamicBuffer_v1::const_buffers_type
  1465. buffers_type;
  1466. typedef buffers_iterator<buffers_type> iterator;
  1467. buffers_type data_buffers = buffers_.data();
  1468. iterator begin = iterator::begin(data_buffers);
  1469. iterator start_pos = begin + search_position_;
  1470. iterator end = iterator::end(data_buffers);
  1471. // Look for a match.
  1472. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  1473. if (result.second)
  1474. {
  1475. // Full match. We're done.
  1476. search_position_ = result.first - begin;
  1477. bytes_to_read = 0;
  1478. }
  1479. // No match yet. Check if buffer is full.
  1480. else if (buffers_.size() == buffers_.max_size())
  1481. {
  1482. search_position_ = not_found;
  1483. bytes_to_read = 0;
  1484. }
  1485. // Need to read some more data.
  1486. else
  1487. {
  1488. if (result.first != end)
  1489. {
  1490. // Partial match. Next search needs to start from beginning of
  1491. // match.
  1492. search_position_ = result.first - begin;
  1493. }
  1494. else
  1495. {
  1496. // Next search can start with the new data.
  1497. search_position_ = end - begin;
  1498. }
  1499. bytes_to_read = std::min<std::size_t>(
  1500. std::max<std::size_t>(512,
  1501. buffers_.capacity() - buffers_.size()),
  1502. std::min<std::size_t>(65536,
  1503. buffers_.max_size() - buffers_.size()));
  1504. }
  1505. }
  1506. // Check if we're done.
  1507. if (!start && bytes_to_read == 0)
  1508. break;
  1509. // Start a new asynchronous read operation to obtain more data.
  1510. {
  1511. ASIO_HANDLER_LOCATION((
  1512. __FILE__, __LINE__, "async_read_until"));
  1513. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1514. static_cast<read_until_match_op_v1&&>(*this));
  1515. }
  1516. return; default:
  1517. buffers_.commit(bytes_transferred);
  1518. if (ec || bytes_transferred == 0)
  1519. break;
  1520. if (this->cancelled() != cancellation_type::none)
  1521. {
  1522. ec = error::operation_aborted;
  1523. break;
  1524. }
  1525. }
  1526. const asio::error_code result_ec =
  1527. (search_position_ == not_found)
  1528. ? error::not_found : ec;
  1529. const std::size_t result_n =
  1530. (ec || search_position_ == not_found)
  1531. ? 0 : search_position_;
  1532. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  1533. }
  1534. }
  1535. //private:
  1536. AsyncReadStream& stream_;
  1537. DynamicBuffer_v1 buffers_;
  1538. MatchCondition match_condition_;
  1539. int start_;
  1540. std::size_t search_position_;
  1541. ReadHandler handler_;
  1542. };
  1543. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1544. typename MatchCondition, typename ReadHandler>
  1545. inline bool asio_handler_is_continuation(
  1546. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1547. MatchCondition, ReadHandler>* this_handler)
  1548. {
  1549. return this_handler->start_ == 0 ? true
  1550. : asio_handler_cont_helpers::is_continuation(
  1551. this_handler->handler_);
  1552. }
  1553. template <typename AsyncReadStream>
  1554. class initiate_async_read_until_match_v1
  1555. {
  1556. public:
  1557. typedef typename AsyncReadStream::executor_type executor_type;
  1558. explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)
  1559. : stream_(stream)
  1560. {
  1561. }
  1562. executor_type get_executor() const noexcept
  1563. {
  1564. return stream_.get_executor();
  1565. }
  1566. template <typename ReadHandler,
  1567. typename DynamicBuffer_v1, typename MatchCondition>
  1568. void operator()(ReadHandler&& handler,
  1569. DynamicBuffer_v1&& buffers,
  1570. MatchCondition match_condition) const
  1571. {
  1572. // If you get an error on the following line it means that your handler
  1573. // does not meet the documented type requirements for a ReadHandler.
  1574. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1575. non_const_lvalue<ReadHandler> handler2(handler);
  1576. read_until_match_op_v1<AsyncReadStream,
  1577. decay_t<DynamicBuffer_v1>,
  1578. MatchCondition, decay_t<ReadHandler>>(
  1579. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  1580. match_condition, handler2.value)(asio::error_code(), 0, 1);
  1581. }
  1582. private:
  1583. AsyncReadStream& stream_;
  1584. };
  1585. } // namespace detail
  1586. #if !defined(GENERATING_DOCUMENTATION)
  1587. template <template <typename, typename> class Associator,
  1588. typename AsyncReadStream, typename DynamicBuffer_v1,
  1589. typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
  1590. struct associator<Associator,
  1591. detail::read_until_match_op_v1<AsyncReadStream,
  1592. DynamicBuffer_v1, MatchCondition, ReadHandler>,
  1593. DefaultCandidate>
  1594. : Associator<ReadHandler, DefaultCandidate>
  1595. {
  1596. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  1597. const detail::read_until_match_op_v1<AsyncReadStream,
  1598. DynamicBuffer_v1, MatchCondition, ReadHandler>& h) noexcept
  1599. {
  1600. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1601. }
  1602. static auto get(
  1603. const detail::read_until_match_op_v1<AsyncReadStream,
  1604. DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
  1605. const DefaultCandidate& c) noexcept
  1606. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  1607. {
  1608. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1609. }
  1610. };
  1611. #endif // !defined(GENERATING_DOCUMENTATION)
  1612. template <typename AsyncReadStream,
  1613. typename DynamicBuffer_v1, typename MatchCondition,
  1614. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1615. std::size_t)) ReadToken>
  1616. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers,
  1617. MatchCondition match_condition, ReadToken&& token,
  1618. constraint_t<
  1619. is_match_condition<MatchCondition>::value
  1620. >,
  1621. constraint_t<
  1622. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  1623. >,
  1624. constraint_t<
  1625. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  1626. >)
  1627. -> decltype(
  1628. async_initiate<ReadToken,
  1629. void (asio::error_code, std::size_t)>(
  1630. declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(),
  1631. token, static_cast<DynamicBuffer_v1&&>(buffers),
  1632. match_condition))
  1633. {
  1634. return async_initiate<ReadToken,
  1635. void (asio::error_code, std::size_t)>(
  1636. detail::initiate_async_read_until_match_v1<AsyncReadStream>(s),
  1637. token, static_cast<DynamicBuffer_v1&&>(buffers),
  1638. match_condition);
  1639. }
  1640. #if !defined(ASIO_NO_IOSTREAM)
  1641. template <typename AsyncReadStream, typename Allocator,
  1642. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1643. std::size_t)) ReadToken>
  1644. inline auto async_read_until(AsyncReadStream& s,
  1645. asio::basic_streambuf<Allocator>& b, char delim, ReadToken&& token)
  1646. -> decltype(
  1647. async_initiate<ReadToken,
  1648. void (asio::error_code, std::size_t)>(
  1649. declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(),
  1650. token, basic_streambuf_ref<Allocator>(b), delim))
  1651. {
  1652. return async_initiate<ReadToken,
  1653. void (asio::error_code, std::size_t)>(
  1654. detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
  1655. token, basic_streambuf_ref<Allocator>(b), delim);
  1656. }
  1657. template <typename AsyncReadStream, typename Allocator,
  1658. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1659. std::size_t)) ReadToken>
  1660. inline auto async_read_until(AsyncReadStream& s,
  1661. asio::basic_streambuf<Allocator>& b,
  1662. ASIO_STRING_VIEW_PARAM delim, ReadToken&& token)
  1663. -> decltype(
  1664. async_initiate<ReadToken,
  1665. void (asio::error_code, std::size_t)>(
  1666. declval<detail::initiate_async_read_until_delim_string_v1<
  1667. AsyncReadStream>>(),
  1668. token, basic_streambuf_ref<Allocator>(b),
  1669. static_cast<std::string>(delim)))
  1670. {
  1671. return async_initiate<ReadToken,
  1672. void (asio::error_code, std::size_t)>(
  1673. detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
  1674. token, basic_streambuf_ref<Allocator>(b),
  1675. static_cast<std::string>(delim));
  1676. }
  1677. #if defined(ASIO_HAS_BOOST_REGEX)
  1678. template <typename AsyncReadStream, typename Allocator, typename Traits,
  1679. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1680. std::size_t)) ReadToken>
  1681. inline auto async_read_until(AsyncReadStream& s,
  1682. asio::basic_streambuf<Allocator>& b,
  1683. const boost::basic_regex<char, Traits>& expr, ReadToken&& token)
  1684. -> decltype(
  1685. async_initiate<ReadToken,
  1686. void (asio::error_code, std::size_t)>(
  1687. declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(),
  1688. token, basic_streambuf_ref<Allocator>(b), expr))
  1689. {
  1690. return async_initiate<ReadToken,
  1691. void (asio::error_code, std::size_t)>(
  1692. detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
  1693. token, basic_streambuf_ref<Allocator>(b), expr);
  1694. }
  1695. #endif // defined(ASIO_HAS_BOOST_REGEX)
  1696. template <typename AsyncReadStream, typename Allocator, typename MatchCondition,
  1697. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1698. std::size_t)) ReadToken>
  1699. inline auto async_read_until(AsyncReadStream& s,
  1700. asio::basic_streambuf<Allocator>& b,
  1701. MatchCondition match_condition, ReadToken&& token,
  1702. constraint_t<is_match_condition<MatchCondition>::value>)
  1703. -> decltype(
  1704. async_initiate<ReadToken,
  1705. void (asio::error_code, std::size_t)>(
  1706. declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(),
  1707. token, basic_streambuf_ref<Allocator>(b), match_condition))
  1708. {
  1709. return async_initiate<ReadToken,
  1710. void (asio::error_code, std::size_t)>(
  1711. detail::initiate_async_read_until_match_v1<AsyncReadStream>(s),
  1712. token, basic_streambuf_ref<Allocator>(b), match_condition);
  1713. }
  1714. #endif // !defined(ASIO_NO_IOSTREAM)
  1715. #endif // !defined(ASIO_NO_EXTENSIONS)
  1716. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  1717. namespace detail
  1718. {
  1719. template <typename AsyncReadStream,
  1720. typename DynamicBuffer_v2, typename ReadHandler>
  1721. class read_until_delim_op_v2
  1722. : public base_from_cancellation_state<ReadHandler>
  1723. {
  1724. public:
  1725. template <typename BufferSequence>
  1726. read_until_delim_op_v2(AsyncReadStream& stream,
  1727. BufferSequence&& buffers,
  1728. char delim, ReadHandler& handler)
  1729. : base_from_cancellation_state<ReadHandler>(
  1730. handler, enable_partial_cancellation()),
  1731. stream_(stream),
  1732. buffers_(static_cast<BufferSequence&&>(buffers)),
  1733. delim_(delim),
  1734. start_(0),
  1735. search_position_(0),
  1736. bytes_to_read_(0),
  1737. handler_(static_cast<ReadHandler&&>(handler))
  1738. {
  1739. }
  1740. read_until_delim_op_v2(const read_until_delim_op_v2& other)
  1741. : base_from_cancellation_state<ReadHandler>(other),
  1742. stream_(other.stream_),
  1743. buffers_(other.buffers_),
  1744. delim_(other.delim_),
  1745. start_(other.start_),
  1746. search_position_(other.search_position_),
  1747. bytes_to_read_(other.bytes_to_read_),
  1748. handler_(other.handler_)
  1749. {
  1750. }
  1751. read_until_delim_op_v2(read_until_delim_op_v2&& other)
  1752. : base_from_cancellation_state<ReadHandler>(
  1753. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  1754. stream_(other.stream_),
  1755. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  1756. delim_(other.delim_),
  1757. start_(other.start_),
  1758. search_position_(other.search_position_),
  1759. bytes_to_read_(other.bytes_to_read_),
  1760. handler_(static_cast<ReadHandler&&>(other.handler_))
  1761. {
  1762. }
  1763. void operator()(asio::error_code ec,
  1764. std::size_t bytes_transferred, int start = 0)
  1765. {
  1766. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1767. std::size_t pos;
  1768. switch (start_ = start)
  1769. {
  1770. case 1:
  1771. for (;;)
  1772. {
  1773. {
  1774. // Determine the range of the data to be searched.
  1775. typedef typename DynamicBuffer_v2::const_buffers_type
  1776. buffers_type;
  1777. typedef buffers_iterator<buffers_type> iterator;
  1778. buffers_type data_buffers =
  1779. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  1780. 0, buffers_.size());
  1781. iterator begin = iterator::begin(data_buffers);
  1782. iterator start_pos = begin + search_position_;
  1783. iterator end = iterator::end(data_buffers);
  1784. // Look for a match.
  1785. iterator iter = std::find(start_pos, end, delim_);
  1786. if (iter != end)
  1787. {
  1788. // Found a match. We're done.
  1789. search_position_ = iter - begin + 1;
  1790. bytes_to_read_ = 0;
  1791. }
  1792. // No match yet. Check if buffer is full.
  1793. else if (buffers_.size() == buffers_.max_size())
  1794. {
  1795. search_position_ = not_found;
  1796. bytes_to_read_ = 0;
  1797. }
  1798. // Need to read some more data.
  1799. else
  1800. {
  1801. // Next search can start with the new data.
  1802. search_position_ = end - begin;
  1803. bytes_to_read_ = std::min<std::size_t>(
  1804. std::max<std::size_t>(512,
  1805. buffers_.capacity() - buffers_.size()),
  1806. std::min<std::size_t>(65536,
  1807. buffers_.max_size() - buffers_.size()));
  1808. }
  1809. }
  1810. // Check if we're done.
  1811. if (!start && bytes_to_read_ == 0)
  1812. break;
  1813. // Start a new asynchronous read operation to obtain more data.
  1814. pos = buffers_.size();
  1815. buffers_.grow(bytes_to_read_);
  1816. {
  1817. ASIO_HANDLER_LOCATION((
  1818. __FILE__, __LINE__, "async_read_until"));
  1819. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  1820. static_cast<read_until_delim_op_v2&&>(*this));
  1821. }
  1822. return; default:
  1823. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  1824. if (ec || bytes_transferred == 0)
  1825. break;
  1826. if (this->cancelled() != cancellation_type::none)
  1827. {
  1828. ec = error::operation_aborted;
  1829. break;
  1830. }
  1831. }
  1832. const asio::error_code result_ec =
  1833. (search_position_ == not_found)
  1834. ? error::not_found : ec;
  1835. const std::size_t result_n =
  1836. (ec || search_position_ == not_found)
  1837. ? 0 : search_position_;
  1838. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  1839. }
  1840. }
  1841. //private:
  1842. AsyncReadStream& stream_;
  1843. DynamicBuffer_v2 buffers_;
  1844. char delim_;
  1845. int start_;
  1846. std::size_t search_position_;
  1847. std::size_t bytes_to_read_;
  1848. ReadHandler handler_;
  1849. };
  1850. template <typename AsyncReadStream,
  1851. typename DynamicBuffer_v2, typename ReadHandler>
  1852. inline bool asio_handler_is_continuation(
  1853. read_until_delim_op_v2<AsyncReadStream,
  1854. DynamicBuffer_v2, ReadHandler>* this_handler)
  1855. {
  1856. return this_handler->start_ == 0 ? true
  1857. : asio_handler_cont_helpers::is_continuation(
  1858. this_handler->handler_);
  1859. }
  1860. template <typename AsyncReadStream>
  1861. class initiate_async_read_until_delim_v2
  1862. {
  1863. public:
  1864. typedef typename AsyncReadStream::executor_type executor_type;
  1865. explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)
  1866. : stream_(stream)
  1867. {
  1868. }
  1869. executor_type get_executor() const noexcept
  1870. {
  1871. return stream_.get_executor();
  1872. }
  1873. template <typename ReadHandler, typename DynamicBuffer_v2>
  1874. void operator()(ReadHandler&& handler,
  1875. DynamicBuffer_v2&& buffers, char delim) const
  1876. {
  1877. // If you get an error on the following line it means that your handler
  1878. // does not meet the documented type requirements for a ReadHandler.
  1879. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1880. non_const_lvalue<ReadHandler> handler2(handler);
  1881. read_until_delim_op_v2<AsyncReadStream,
  1882. decay_t<DynamicBuffer_v2>,
  1883. decay_t<ReadHandler>>(
  1884. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  1885. delim, handler2.value)(asio::error_code(), 0, 1);
  1886. }
  1887. private:
  1888. AsyncReadStream& stream_;
  1889. };
  1890. } // namespace detail
  1891. #if !defined(GENERATING_DOCUMENTATION)
  1892. template <template <typename, typename> class Associator,
  1893. typename AsyncReadStream, typename DynamicBuffer_v2,
  1894. typename ReadHandler, typename DefaultCandidate>
  1895. struct associator<Associator,
  1896. detail::read_until_delim_op_v2<AsyncReadStream,
  1897. DynamicBuffer_v2, ReadHandler>,
  1898. DefaultCandidate>
  1899. : Associator<ReadHandler, DefaultCandidate>
  1900. {
  1901. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  1902. const detail::read_until_delim_op_v2<AsyncReadStream,
  1903. DynamicBuffer_v2, ReadHandler>& h) noexcept
  1904. {
  1905. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1906. }
  1907. static auto get(
  1908. const detail::read_until_delim_op_v2<AsyncReadStream,
  1909. DynamicBuffer_v2, ReadHandler>& h,
  1910. const DefaultCandidate& c) noexcept
  1911. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  1912. {
  1913. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1914. }
  1915. };
  1916. #endif // !defined(GENERATING_DOCUMENTATION)
  1917. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  1918. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  1919. std::size_t)) ReadToken>
  1920. inline auto async_read_until(AsyncReadStream& s,
  1921. DynamicBuffer_v2 buffers, char delim, ReadToken&& token,
  1922. constraint_t<
  1923. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  1924. >)
  1925. -> decltype(
  1926. async_initiate<ReadToken,
  1927. void (asio::error_code, std::size_t)>(
  1928. declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream>>(),
  1929. token, static_cast<DynamicBuffer_v2&&>(buffers), delim))
  1930. {
  1931. return async_initiate<ReadToken,
  1932. void (asio::error_code, std::size_t)>(
  1933. detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),
  1934. token, static_cast<DynamicBuffer_v2&&>(buffers), delim);
  1935. }
  1936. namespace detail
  1937. {
  1938. template <typename AsyncReadStream,
  1939. typename DynamicBuffer_v2, typename ReadHandler>
  1940. class read_until_delim_string_op_v2
  1941. : public base_from_cancellation_state<ReadHandler>
  1942. {
  1943. public:
  1944. template <typename BufferSequence>
  1945. read_until_delim_string_op_v2(AsyncReadStream& stream,
  1946. BufferSequence&& buffers,
  1947. const std::string& delim, ReadHandler& handler)
  1948. : base_from_cancellation_state<ReadHandler>(
  1949. handler, enable_partial_cancellation()),
  1950. stream_(stream),
  1951. buffers_(static_cast<BufferSequence&&>(buffers)),
  1952. delim_(delim),
  1953. start_(0),
  1954. search_position_(0),
  1955. bytes_to_read_(0),
  1956. handler_(static_cast<ReadHandler&&>(handler))
  1957. {
  1958. }
  1959. read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
  1960. : base_from_cancellation_state<ReadHandler>(other),
  1961. stream_(other.stream_),
  1962. buffers_(other.buffers_),
  1963. delim_(other.delim_),
  1964. start_(other.start_),
  1965. search_position_(other.search_position_),
  1966. bytes_to_read_(other.bytes_to_read_),
  1967. handler_(other.handler_)
  1968. {
  1969. }
  1970. read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
  1971. : base_from_cancellation_state<ReadHandler>(
  1972. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  1973. stream_(other.stream_),
  1974. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  1975. delim_(static_cast<std::string&&>(other.delim_)),
  1976. start_(other.start_),
  1977. search_position_(other.search_position_),
  1978. bytes_to_read_(other.bytes_to_read_),
  1979. handler_(static_cast<ReadHandler&&>(other.handler_))
  1980. {
  1981. }
  1982. void operator()(asio::error_code ec,
  1983. std::size_t bytes_transferred, int start = 0)
  1984. {
  1985. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1986. std::size_t pos;
  1987. switch (start_ = start)
  1988. {
  1989. case 1:
  1990. for (;;)
  1991. {
  1992. {
  1993. // Determine the range of the data to be searched.
  1994. typedef typename DynamicBuffer_v2::const_buffers_type
  1995. buffers_type;
  1996. typedef buffers_iterator<buffers_type> iterator;
  1997. buffers_type data_buffers =
  1998. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  1999. 0, buffers_.size());
  2000. iterator begin = iterator::begin(data_buffers);
  2001. iterator start_pos = begin + search_position_;
  2002. iterator end = iterator::end(data_buffers);
  2003. // Look for a match.
  2004. std::pair<iterator, bool> result = detail::partial_search(
  2005. start_pos, end, delim_.begin(), delim_.end());
  2006. if (result.first != end && result.second)
  2007. {
  2008. // Full match. We're done.
  2009. search_position_ = result.first - begin + delim_.length();
  2010. bytes_to_read_ = 0;
  2011. }
  2012. // No match yet. Check if buffer is full.
  2013. else if (buffers_.size() == buffers_.max_size())
  2014. {
  2015. search_position_ = not_found;
  2016. bytes_to_read_ = 0;
  2017. }
  2018. // Need to read some more data.
  2019. else
  2020. {
  2021. if (result.first != end)
  2022. {
  2023. // Partial match. Next search needs to start from beginning of
  2024. // match.
  2025. search_position_ = result.first - begin;
  2026. }
  2027. else
  2028. {
  2029. // Next search can start with the new data.
  2030. search_position_ = end - begin;
  2031. }
  2032. bytes_to_read_ = std::min<std::size_t>(
  2033. std::max<std::size_t>(512,
  2034. buffers_.capacity() - buffers_.size()),
  2035. std::min<std::size_t>(65536,
  2036. buffers_.max_size() - buffers_.size()));
  2037. }
  2038. }
  2039. // Check if we're done.
  2040. if (!start && bytes_to_read_ == 0)
  2041. break;
  2042. // Start a new asynchronous read operation to obtain more data.
  2043. pos = buffers_.size();
  2044. buffers_.grow(bytes_to_read_);
  2045. {
  2046. ASIO_HANDLER_LOCATION((
  2047. __FILE__, __LINE__, "async_read_until"));
  2048. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2049. static_cast<read_until_delim_string_op_v2&&>(*this));
  2050. }
  2051. return; default:
  2052. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2053. if (ec || bytes_transferred == 0)
  2054. break;
  2055. if (this->cancelled() != cancellation_type::none)
  2056. {
  2057. ec = error::operation_aborted;
  2058. break;
  2059. }
  2060. }
  2061. const asio::error_code result_ec =
  2062. (search_position_ == not_found)
  2063. ? error::not_found : ec;
  2064. const std::size_t result_n =
  2065. (ec || search_position_ == not_found)
  2066. ? 0 : search_position_;
  2067. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  2068. }
  2069. }
  2070. //private:
  2071. AsyncReadStream& stream_;
  2072. DynamicBuffer_v2 buffers_;
  2073. std::string delim_;
  2074. int start_;
  2075. std::size_t search_position_;
  2076. std::size_t bytes_to_read_;
  2077. ReadHandler handler_;
  2078. };
  2079. template <typename AsyncReadStream,
  2080. typename DynamicBuffer_v2, typename ReadHandler>
  2081. inline bool asio_handler_is_continuation(
  2082. read_until_delim_string_op_v2<AsyncReadStream,
  2083. DynamicBuffer_v2, ReadHandler>* this_handler)
  2084. {
  2085. return this_handler->start_ == 0 ? true
  2086. : asio_handler_cont_helpers::is_continuation(
  2087. this_handler->handler_);
  2088. }
  2089. template <typename AsyncReadStream>
  2090. class initiate_async_read_until_delim_string_v2
  2091. {
  2092. public:
  2093. typedef typename AsyncReadStream::executor_type executor_type;
  2094. explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)
  2095. : stream_(stream)
  2096. {
  2097. }
  2098. executor_type get_executor() const noexcept
  2099. {
  2100. return stream_.get_executor();
  2101. }
  2102. template <typename ReadHandler, typename DynamicBuffer_v2>
  2103. void operator()(ReadHandler&& handler,
  2104. DynamicBuffer_v2&& buffers,
  2105. const std::string& delim) const
  2106. {
  2107. // If you get an error on the following line it means that your handler
  2108. // does not meet the documented type requirements for a ReadHandler.
  2109. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2110. non_const_lvalue<ReadHandler> handler2(handler);
  2111. read_until_delim_string_op_v2<AsyncReadStream,
  2112. decay_t<DynamicBuffer_v2>,
  2113. decay_t<ReadHandler>>(
  2114. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  2115. delim, handler2.value)(asio::error_code(), 0, 1);
  2116. }
  2117. private:
  2118. AsyncReadStream& stream_;
  2119. };
  2120. } // namespace detail
  2121. #if !defined(GENERATING_DOCUMENTATION)
  2122. template <template <typename, typename> class Associator,
  2123. typename AsyncReadStream, typename DynamicBuffer_v2,
  2124. typename ReadHandler, typename DefaultCandidate>
  2125. struct associator<Associator,
  2126. detail::read_until_delim_string_op_v2<AsyncReadStream,
  2127. DynamicBuffer_v2, ReadHandler>,
  2128. DefaultCandidate>
  2129. : Associator<ReadHandler, DefaultCandidate>
  2130. {
  2131. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  2132. const detail::read_until_delim_string_op_v2<
  2133. AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h) noexcept
  2134. {
  2135. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2136. }
  2137. static auto get(
  2138. const detail::read_until_delim_string_op_v2<
  2139. AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h,
  2140. const DefaultCandidate& c) noexcept
  2141. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  2142. {
  2143. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2144. }
  2145. };
  2146. #endif // !defined(GENERATING_DOCUMENTATION)
  2147. template <typename AsyncReadStream,
  2148. typename DynamicBuffer_v2,
  2149. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  2150. std::size_t)) ReadToken>
  2151. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  2152. ASIO_STRING_VIEW_PARAM delim, ReadToken&& token,
  2153. constraint_t<
  2154. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2155. >)
  2156. -> decltype(
  2157. async_initiate<ReadToken,
  2158. void (asio::error_code, std::size_t)>(
  2159. declval<detail::initiate_async_read_until_delim_string_v2<
  2160. AsyncReadStream>>(),
  2161. token, static_cast<DynamicBuffer_v2&&>(buffers),
  2162. static_cast<std::string>(delim)))
  2163. {
  2164. return async_initiate<ReadToken,
  2165. void (asio::error_code, std::size_t)>(
  2166. detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),
  2167. token, static_cast<DynamicBuffer_v2&&>(buffers),
  2168. static_cast<std::string>(delim));
  2169. }
  2170. #if !defined(ASIO_NO_EXTENSIONS)
  2171. #if defined(ASIO_HAS_BOOST_REGEX)
  2172. namespace detail
  2173. {
  2174. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2175. typename RegEx, typename ReadHandler>
  2176. class read_until_expr_op_v2
  2177. : public base_from_cancellation_state<ReadHandler>
  2178. {
  2179. public:
  2180. template <typename BufferSequence, typename Traits>
  2181. read_until_expr_op_v2(AsyncReadStream& stream, BufferSequence&& buffers,
  2182. const boost::basic_regex<char, Traits>& expr, ReadHandler& handler)
  2183. : base_from_cancellation_state<ReadHandler>(
  2184. handler, enable_partial_cancellation()),
  2185. stream_(stream),
  2186. buffers_(static_cast<BufferSequence&&>(buffers)),
  2187. expr_(expr),
  2188. start_(0),
  2189. search_position_(0),
  2190. bytes_to_read_(0),
  2191. handler_(static_cast<ReadHandler&&>(handler))
  2192. {
  2193. }
  2194. read_until_expr_op_v2(const read_until_expr_op_v2& other)
  2195. : base_from_cancellation_state<ReadHandler>(other),
  2196. stream_(other.stream_),
  2197. buffers_(other.buffers_),
  2198. expr_(other.expr_),
  2199. start_(other.start_),
  2200. search_position_(other.search_position_),
  2201. bytes_to_read_(other.bytes_to_read_),
  2202. handler_(other.handler_)
  2203. {
  2204. }
  2205. read_until_expr_op_v2(read_until_expr_op_v2&& other)
  2206. : base_from_cancellation_state<ReadHandler>(
  2207. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  2208. stream_(other.stream_),
  2209. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  2210. expr_(other.expr_),
  2211. start_(other.start_),
  2212. search_position_(other.search_position_),
  2213. bytes_to_read_(other.bytes_to_read_),
  2214. handler_(static_cast<ReadHandler&&>(other.handler_))
  2215. {
  2216. }
  2217. void operator()(asio::error_code ec,
  2218. std::size_t bytes_transferred, int start = 0)
  2219. {
  2220. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2221. std::size_t pos;
  2222. switch (start_ = start)
  2223. {
  2224. case 1:
  2225. for (;;)
  2226. {
  2227. {
  2228. // Determine the range of the data to be searched.
  2229. typedef typename DynamicBuffer_v2::const_buffers_type
  2230. buffers_type;
  2231. typedef buffers_iterator<buffers_type> iterator;
  2232. buffers_type data_buffers =
  2233. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2234. 0, buffers_.size());
  2235. iterator begin = iterator::begin(data_buffers);
  2236. iterator start_pos = begin + search_position_;
  2237. iterator end = iterator::end(data_buffers);
  2238. // Look for a match.
  2239. boost::match_results<iterator,
  2240. typename std::vector<boost::sub_match<iterator>>::allocator_type>
  2241. match_results;
  2242. bool match = regex_search(start_pos, end,
  2243. match_results, expr_, regex_match_flags());
  2244. if (match && match_results[0].matched)
  2245. {
  2246. // Full match. We're done.
  2247. search_position_ = match_results[0].second - begin;
  2248. bytes_to_read_ = 0;
  2249. }
  2250. // No match yet. Check if buffer is full.
  2251. else if (buffers_.size() == buffers_.max_size())
  2252. {
  2253. search_position_ = not_found;
  2254. bytes_to_read_ = 0;
  2255. }
  2256. // Need to read some more data.
  2257. else
  2258. {
  2259. if (match)
  2260. {
  2261. // Partial match. Next search needs to start from beginning of
  2262. // match.
  2263. search_position_ = match_results[0].first - begin;
  2264. }
  2265. else
  2266. {
  2267. // Next search can start with the new data.
  2268. search_position_ = end - begin;
  2269. }
  2270. bytes_to_read_ = std::min<std::size_t>(
  2271. std::max<std::size_t>(512,
  2272. buffers_.capacity() - buffers_.size()),
  2273. std::min<std::size_t>(65536,
  2274. buffers_.max_size() - buffers_.size()));
  2275. }
  2276. }
  2277. // Check if we're done.
  2278. if (!start && bytes_to_read_ == 0)
  2279. break;
  2280. // Start a new asynchronous read operation to obtain more data.
  2281. pos = buffers_.size();
  2282. buffers_.grow(bytes_to_read_);
  2283. {
  2284. ASIO_HANDLER_LOCATION((
  2285. __FILE__, __LINE__, "async_read_until"));
  2286. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2287. static_cast<read_until_expr_op_v2&&>(*this));
  2288. }
  2289. return; default:
  2290. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2291. if (ec || bytes_transferred == 0)
  2292. break;
  2293. if (this->cancelled() != cancellation_type::none)
  2294. {
  2295. ec = error::operation_aborted;
  2296. break;
  2297. }
  2298. }
  2299. const asio::error_code result_ec =
  2300. (search_position_ == not_found)
  2301. ? error::not_found : ec;
  2302. const std::size_t result_n =
  2303. (ec || search_position_ == not_found)
  2304. ? 0 : search_position_;
  2305. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  2306. }
  2307. }
  2308. //private:
  2309. AsyncReadStream& stream_;
  2310. DynamicBuffer_v2 buffers_;
  2311. RegEx expr_;
  2312. int start_;
  2313. std::size_t search_position_;
  2314. std::size_t bytes_to_read_;
  2315. ReadHandler handler_;
  2316. };
  2317. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2318. typename RegEx, typename ReadHandler>
  2319. inline bool asio_handler_is_continuation(
  2320. read_until_expr_op_v2<AsyncReadStream,
  2321. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2322. {
  2323. return this_handler->start_ == 0 ? true
  2324. : asio_handler_cont_helpers::is_continuation(
  2325. this_handler->handler_);
  2326. }
  2327. template <typename AsyncReadStream>
  2328. class initiate_async_read_until_expr_v2
  2329. {
  2330. public:
  2331. typedef typename AsyncReadStream::executor_type executor_type;
  2332. explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)
  2333. : stream_(stream)
  2334. {
  2335. }
  2336. executor_type get_executor() const noexcept
  2337. {
  2338. return stream_.get_executor();
  2339. }
  2340. template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>
  2341. void operator()(ReadHandler&& handler,
  2342. DynamicBuffer_v2&& buffers,
  2343. const RegEx& expr) const
  2344. {
  2345. // If you get an error on the following line it means that your handler
  2346. // does not meet the documented type requirements for a ReadHandler.
  2347. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2348. non_const_lvalue<ReadHandler> handler2(handler);
  2349. read_until_expr_op_v2<AsyncReadStream,
  2350. decay_t<DynamicBuffer_v2>,
  2351. RegEx, decay_t<ReadHandler>>(
  2352. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  2353. expr, handler2.value)(asio::error_code(), 0, 1);
  2354. }
  2355. private:
  2356. AsyncReadStream& stream_;
  2357. };
  2358. } // namespace detail
  2359. #if !defined(GENERATING_DOCUMENTATION)
  2360. template <template <typename, typename> class Associator,
  2361. typename AsyncReadStream, typename DynamicBuffer_v2,
  2362. typename RegEx, typename ReadHandler, typename DefaultCandidate>
  2363. struct associator<Associator,
  2364. detail::read_until_expr_op_v2<AsyncReadStream,
  2365. DynamicBuffer_v2, RegEx, ReadHandler>,
  2366. DefaultCandidate>
  2367. : Associator<ReadHandler, DefaultCandidate>
  2368. {
  2369. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  2370. const detail::read_until_expr_op_v2<AsyncReadStream,
  2371. DynamicBuffer_v2, RegEx, ReadHandler>& h) noexcept
  2372. {
  2373. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2374. }
  2375. static auto get(
  2376. const detail::read_until_expr_op_v2<AsyncReadStream,
  2377. DynamicBuffer_v2, RegEx, ReadHandler>& h,
  2378. const DefaultCandidate& c) noexcept
  2379. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  2380. {
  2381. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2382. }
  2383. };
  2384. #endif // !defined(GENERATING_DOCUMENTATION)
  2385. template <typename AsyncReadStream, typename DynamicBuffer_v2, typename Traits,
  2386. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  2387. std::size_t)) ReadToken>
  2388. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  2389. const boost::basic_regex<char, Traits>& expr, ReadToken&& token,
  2390. constraint_t<
  2391. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2392. >)
  2393. -> decltype(
  2394. async_initiate<ReadToken,
  2395. void (asio::error_code, std::size_t)>(
  2396. declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream>>(),
  2397. token, static_cast<DynamicBuffer_v2&&>(buffers), expr))
  2398. {
  2399. return async_initiate<ReadToken,
  2400. void (asio::error_code, std::size_t)>(
  2401. detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),
  2402. token, static_cast<DynamicBuffer_v2&&>(buffers), expr);
  2403. }
  2404. #endif // defined(ASIO_HAS_BOOST_REGEX)
  2405. namespace detail
  2406. {
  2407. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2408. typename MatchCondition, typename ReadHandler>
  2409. class read_until_match_op_v2
  2410. : public base_from_cancellation_state<ReadHandler>
  2411. {
  2412. public:
  2413. template <typename BufferSequence>
  2414. read_until_match_op_v2(AsyncReadStream& stream,
  2415. BufferSequence&& buffers,
  2416. MatchCondition match_condition, ReadHandler& handler)
  2417. : base_from_cancellation_state<ReadHandler>(
  2418. handler, enable_partial_cancellation()),
  2419. stream_(stream),
  2420. buffers_(static_cast<BufferSequence&&>(buffers)),
  2421. match_condition_(match_condition),
  2422. start_(0),
  2423. search_position_(0),
  2424. bytes_to_read_(0),
  2425. handler_(static_cast<ReadHandler&&>(handler))
  2426. {
  2427. }
  2428. read_until_match_op_v2(const read_until_match_op_v2& other)
  2429. : base_from_cancellation_state<ReadHandler>(other),
  2430. stream_(other.stream_),
  2431. buffers_(other.buffers_),
  2432. match_condition_(other.match_condition_),
  2433. start_(other.start_),
  2434. search_position_(other.search_position_),
  2435. bytes_to_read_(other.bytes_to_read_),
  2436. handler_(other.handler_)
  2437. {
  2438. }
  2439. read_until_match_op_v2(read_until_match_op_v2&& other)
  2440. : base_from_cancellation_state<ReadHandler>(
  2441. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  2442. stream_(other.stream_),
  2443. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  2444. match_condition_(other.match_condition_),
  2445. start_(other.start_),
  2446. search_position_(other.search_position_),
  2447. bytes_to_read_(other.bytes_to_read_),
  2448. handler_(static_cast<ReadHandler&&>(other.handler_))
  2449. {
  2450. }
  2451. void operator()(asio::error_code ec,
  2452. std::size_t bytes_transferred, int start = 0)
  2453. {
  2454. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2455. std::size_t pos;
  2456. switch (start_ = start)
  2457. {
  2458. case 1:
  2459. for (;;)
  2460. {
  2461. {
  2462. // Determine the range of the data to be searched.
  2463. typedef typename DynamicBuffer_v2::const_buffers_type
  2464. buffers_type;
  2465. typedef buffers_iterator<buffers_type> iterator;
  2466. buffers_type data_buffers =
  2467. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2468. 0, buffers_.size());
  2469. iterator begin = iterator::begin(data_buffers);
  2470. iterator start_pos = begin + search_position_;
  2471. iterator end = iterator::end(data_buffers);
  2472. // Look for a match.
  2473. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  2474. if (result.second)
  2475. {
  2476. // Full match. We're done.
  2477. search_position_ = result.first - begin;
  2478. bytes_to_read_ = 0;
  2479. }
  2480. // No match yet. Check if buffer is full.
  2481. else if (buffers_.size() == buffers_.max_size())
  2482. {
  2483. search_position_ = not_found;
  2484. bytes_to_read_ = 0;
  2485. }
  2486. // Need to read some more data.
  2487. else
  2488. {
  2489. if (result.first != end)
  2490. {
  2491. // Partial match. Next search needs to start from beginning of
  2492. // match.
  2493. search_position_ = result.first - begin;
  2494. }
  2495. else
  2496. {
  2497. // Next search can start with the new data.
  2498. search_position_ = end - begin;
  2499. }
  2500. bytes_to_read_ = std::min<std::size_t>(
  2501. std::max<std::size_t>(512,
  2502. buffers_.capacity() - buffers_.size()),
  2503. std::min<std::size_t>(65536,
  2504. buffers_.max_size() - buffers_.size()));
  2505. }
  2506. }
  2507. // Check if we're done.
  2508. if (!start && bytes_to_read_ == 0)
  2509. break;
  2510. // Start a new asynchronous read operation to obtain more data.
  2511. pos = buffers_.size();
  2512. buffers_.grow(bytes_to_read_);
  2513. {
  2514. ASIO_HANDLER_LOCATION((
  2515. __FILE__, __LINE__, "async_read_until"));
  2516. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2517. static_cast<read_until_match_op_v2&&>(*this));
  2518. }
  2519. return; default:
  2520. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2521. if (ec || bytes_transferred == 0)
  2522. break;
  2523. if (this->cancelled() != cancellation_type::none)
  2524. {
  2525. ec = error::operation_aborted;
  2526. break;
  2527. }
  2528. }
  2529. const asio::error_code result_ec =
  2530. (search_position_ == not_found)
  2531. ? error::not_found : ec;
  2532. const std::size_t result_n =
  2533. (ec || search_position_ == not_found)
  2534. ? 0 : search_position_;
  2535. static_cast<ReadHandler&&>(handler_)(result_ec, result_n);
  2536. }
  2537. }
  2538. //private:
  2539. AsyncReadStream& stream_;
  2540. DynamicBuffer_v2 buffers_;
  2541. MatchCondition match_condition_;
  2542. int start_;
  2543. std::size_t search_position_;
  2544. std::size_t bytes_to_read_;
  2545. ReadHandler handler_;
  2546. };
  2547. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2548. typename MatchCondition, typename ReadHandler>
  2549. inline bool asio_handler_is_continuation(
  2550. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  2551. MatchCondition, ReadHandler>* this_handler)
  2552. {
  2553. return this_handler->start_ == 0 ? true
  2554. : asio_handler_cont_helpers::is_continuation(
  2555. this_handler->handler_);
  2556. }
  2557. template <typename AsyncReadStream>
  2558. class initiate_async_read_until_match_v2
  2559. {
  2560. public:
  2561. typedef typename AsyncReadStream::executor_type executor_type;
  2562. explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)
  2563. : stream_(stream)
  2564. {
  2565. }
  2566. executor_type get_executor() const noexcept
  2567. {
  2568. return stream_.get_executor();
  2569. }
  2570. template <typename ReadHandler,
  2571. typename DynamicBuffer_v2, typename MatchCondition>
  2572. void operator()(ReadHandler&& handler,
  2573. DynamicBuffer_v2&& buffers,
  2574. MatchCondition match_condition) const
  2575. {
  2576. // If you get an error on the following line it means that your handler
  2577. // does not meet the documented type requirements for a ReadHandler.
  2578. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2579. non_const_lvalue<ReadHandler> handler2(handler);
  2580. read_until_match_op_v2<AsyncReadStream, decay_t<DynamicBuffer_v2>,
  2581. MatchCondition, decay_t<ReadHandler>>(
  2582. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  2583. match_condition, handler2.value)(asio::error_code(), 0, 1);
  2584. }
  2585. private:
  2586. AsyncReadStream& stream_;
  2587. };
  2588. } // namespace detail
  2589. #if !defined(GENERATING_DOCUMENTATION)
  2590. template <template <typename, typename> class Associator,
  2591. typename AsyncReadStream, typename DynamicBuffer_v2,
  2592. typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
  2593. struct associator<Associator,
  2594. detail::read_until_match_op_v2<AsyncReadStream,
  2595. DynamicBuffer_v2, MatchCondition, ReadHandler>,
  2596. DefaultCandidate>
  2597. : Associator<ReadHandler, DefaultCandidate>
  2598. {
  2599. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  2600. const detail::read_until_match_op_v2<AsyncReadStream,
  2601. DynamicBuffer_v2, MatchCondition, ReadHandler>& h) noexcept
  2602. {
  2603. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2604. }
  2605. static auto get(
  2606. const detail::read_until_match_op_v2<AsyncReadStream,
  2607. DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
  2608. const DefaultCandidate& c) noexcept
  2609. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  2610. {
  2611. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2612. }
  2613. };
  2614. #endif // !defined(GENERATING_DOCUMENTATION)
  2615. template <typename AsyncReadStream,
  2616. typename DynamicBuffer_v2, typename MatchCondition,
  2617. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  2618. std::size_t)) ReadToken>
  2619. inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  2620. MatchCondition match_condition, ReadToken&& token,
  2621. constraint_t<
  2622. is_match_condition<MatchCondition>::value
  2623. >,
  2624. constraint_t<
  2625. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2626. >)
  2627. -> decltype(
  2628. async_initiate<ReadToken,
  2629. void (asio::error_code, std::size_t)>(
  2630. declval<detail::initiate_async_read_until_match_v2<AsyncReadStream>>(),
  2631. token, static_cast<DynamicBuffer_v2&&>(buffers),
  2632. match_condition))
  2633. {
  2634. return async_initiate<ReadToken,
  2635. void (asio::error_code, std::size_t)>(
  2636. detail::initiate_async_read_until_match_v2<AsyncReadStream>(s),
  2637. token, static_cast<DynamicBuffer_v2&&>(buffers),
  2638. match_condition);
  2639. }
  2640. #endif // !defined(ASIO_NO_EXTENSIONS)
  2641. } // namespace asio
  2642. #include "asio/detail/pop_options.hpp"
  2643. #endif // ASIO_IMPL_READ_UNTIL_HPP