read_until.hpp 113 KB

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