read_until.hpp 119 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457
  1. //
  2. // impl/read_until.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef 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/associator.hpp>
  20. #include <boost/asio/buffer.hpp>
  21. #include <boost/asio/buffers_iterator.hpp>
  22. #include <boost/asio/detail/base_from_cancellation_state.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. : public base_from_cancellation_state<ReadHandler>
  736. {
  737. public:
  738. template <typename BufferSequence>
  739. read_until_delim_op_v1(AsyncReadStream& stream,
  740. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  741. char delim, ReadHandler& handler)
  742. : base_from_cancellation_state<ReadHandler>(
  743. handler, enable_partial_cancellation()),
  744. stream_(stream),
  745. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  746. delim_(delim),
  747. start_(0),
  748. search_position_(0),
  749. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  750. {
  751. }
  752. #if defined(BOOST_ASIO_HAS_MOVE)
  753. read_until_delim_op_v1(const read_until_delim_op_v1& other)
  754. : base_from_cancellation_state<ReadHandler>(other),
  755. stream_(other.stream_),
  756. buffers_(other.buffers_),
  757. delim_(other.delim_),
  758. start_(other.start_),
  759. search_position_(other.search_position_),
  760. handler_(other.handler_)
  761. {
  762. }
  763. read_until_delim_op_v1(read_until_delim_op_v1&& other)
  764. : base_from_cancellation_state<ReadHandler>(
  765. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  766. ReadHandler>)(other)),
  767. stream_(other.stream_),
  768. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  769. delim_(other.delim_),
  770. start_(other.start_),
  771. search_position_(other.search_position_),
  772. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  773. {
  774. }
  775. #endif // defined(BOOST_ASIO_HAS_MOVE)
  776. void operator()(boost::system::error_code ec,
  777. std::size_t bytes_transferred, int start = 0)
  778. {
  779. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  780. std::size_t bytes_to_read;
  781. switch (start_ = start)
  782. {
  783. case 1:
  784. for (;;)
  785. {
  786. {
  787. // Determine the range of the data to be searched.
  788. typedef typename DynamicBuffer_v1::const_buffers_type
  789. buffers_type;
  790. typedef buffers_iterator<buffers_type> iterator;
  791. buffers_type data_buffers = buffers_.data();
  792. iterator begin = iterator::begin(data_buffers);
  793. iterator start_pos = begin + search_position_;
  794. iterator end = iterator::end(data_buffers);
  795. // Look for a match.
  796. iterator iter = std::find(start_pos, end, delim_);
  797. if (iter != end)
  798. {
  799. // Found a match. We're done.
  800. search_position_ = iter - begin + 1;
  801. bytes_to_read = 0;
  802. }
  803. // No match yet. Check if buffer is full.
  804. else if (buffers_.size() == buffers_.max_size())
  805. {
  806. search_position_ = not_found;
  807. bytes_to_read = 0;
  808. }
  809. // Need to read some more data.
  810. else
  811. {
  812. // Next search can start with the new data.
  813. search_position_ = end - begin;
  814. bytes_to_read = std::min<std::size_t>(
  815. std::max<std::size_t>(512,
  816. buffers_.capacity() - buffers_.size()),
  817. std::min<std::size_t>(65536,
  818. buffers_.max_size() - buffers_.size()));
  819. }
  820. }
  821. // Check if we're done.
  822. if (!start && bytes_to_read == 0)
  823. break;
  824. // Start a new asynchronous read operation to obtain more data.
  825. {
  826. BOOST_ASIO_HANDLER_LOCATION((
  827. __FILE__, __LINE__, "async_read_until"));
  828. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  829. BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));
  830. }
  831. return; default:
  832. buffers_.commit(bytes_transferred);
  833. if (ec || bytes_transferred == 0)
  834. break;
  835. if (this->cancelled() != cancellation_type::none)
  836. {
  837. ec = error::operation_aborted;
  838. break;
  839. }
  840. }
  841. const boost::system::error_code result_ec =
  842. (search_position_ == not_found)
  843. ? error::not_found : ec;
  844. const std::size_t result_n =
  845. (ec || search_position_ == not_found)
  846. ? 0 : search_position_;
  847. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  848. }
  849. }
  850. //private:
  851. AsyncReadStream& stream_;
  852. DynamicBuffer_v1 buffers_;
  853. char delim_;
  854. int start_;
  855. std::size_t search_position_;
  856. ReadHandler handler_;
  857. };
  858. template <typename AsyncReadStream,
  859. typename DynamicBuffer_v1, typename ReadHandler>
  860. inline asio_handler_allocate_is_deprecated
  861. asio_handler_allocate(std::size_t size,
  862. read_until_delim_op_v1<AsyncReadStream,
  863. DynamicBuffer_v1, ReadHandler>* this_handler)
  864. {
  865. #if defined(BOOST_ASIO_NO_DEPRECATED)
  866. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  867. return asio_handler_allocate_is_no_longer_used();
  868. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  869. return boost_asio_handler_alloc_helpers::allocate(
  870. size, this_handler->handler_);
  871. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  872. }
  873. template <typename AsyncReadStream,
  874. typename DynamicBuffer_v1, typename ReadHandler>
  875. inline asio_handler_deallocate_is_deprecated
  876. asio_handler_deallocate(void* pointer, std::size_t size,
  877. read_until_delim_op_v1<AsyncReadStream,
  878. DynamicBuffer_v1, ReadHandler>* this_handler)
  879. {
  880. boost_asio_handler_alloc_helpers::deallocate(
  881. pointer, size, this_handler->handler_);
  882. #if defined(BOOST_ASIO_NO_DEPRECATED)
  883. return asio_handler_deallocate_is_no_longer_used();
  884. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  885. }
  886. template <typename AsyncReadStream,
  887. typename DynamicBuffer_v1, typename ReadHandler>
  888. inline bool asio_handler_is_continuation(
  889. read_until_delim_op_v1<AsyncReadStream,
  890. DynamicBuffer_v1, ReadHandler>* this_handler)
  891. {
  892. return this_handler->start_ == 0 ? true
  893. : boost_asio_handler_cont_helpers::is_continuation(
  894. this_handler->handler_);
  895. }
  896. template <typename Function, typename AsyncReadStream,
  897. typename DynamicBuffer_v1, typename ReadHandler>
  898. inline asio_handler_invoke_is_deprecated
  899. asio_handler_invoke(Function& function,
  900. read_until_delim_op_v1<AsyncReadStream,
  901. DynamicBuffer_v1, ReadHandler>* this_handler)
  902. {
  903. boost_asio_handler_invoke_helpers::invoke(
  904. function, this_handler->handler_);
  905. #if defined(BOOST_ASIO_NO_DEPRECATED)
  906. return asio_handler_invoke_is_no_longer_used();
  907. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  908. }
  909. template <typename Function, typename AsyncReadStream,
  910. typename DynamicBuffer_v1, typename ReadHandler>
  911. inline asio_handler_invoke_is_deprecated
  912. asio_handler_invoke(const Function& function,
  913. read_until_delim_op_v1<AsyncReadStream,
  914. DynamicBuffer_v1, ReadHandler>* this_handler)
  915. {
  916. boost_asio_handler_invoke_helpers::invoke(
  917. function, this_handler->handler_);
  918. #if defined(BOOST_ASIO_NO_DEPRECATED)
  919. return asio_handler_invoke_is_no_longer_used();
  920. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  921. }
  922. template <typename AsyncReadStream>
  923. class initiate_async_read_until_delim_v1
  924. {
  925. public:
  926. typedef typename AsyncReadStream::executor_type executor_type;
  927. explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)
  928. : stream_(stream)
  929. {
  930. }
  931. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  932. {
  933. return stream_.get_executor();
  934. }
  935. template <typename ReadHandler, typename DynamicBuffer_v1>
  936. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  937. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  938. char delim) const
  939. {
  940. // If you get an error on the following line it means that your handler
  941. // does not meet the documented type requirements for a ReadHandler.
  942. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  943. non_const_lvalue<ReadHandler> handler2(handler);
  944. read_until_delim_op_v1<AsyncReadStream,
  945. typename decay<DynamicBuffer_v1>::type,
  946. typename decay<ReadHandler>::type>(
  947. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  948. delim, handler2.value)(boost::system::error_code(), 0, 1);
  949. }
  950. private:
  951. AsyncReadStream& stream_;
  952. };
  953. } // namespace detail
  954. #if !defined(GENERATING_DOCUMENTATION)
  955. template <template <typename, typename> class Associator,
  956. typename AsyncReadStream, typename DynamicBuffer_v1,
  957. typename ReadHandler, typename DefaultCandidate>
  958. struct associator<Associator,
  959. detail::read_until_delim_op_v1<AsyncReadStream,
  960. DynamicBuffer_v1, ReadHandler>,
  961. DefaultCandidate>
  962. : Associator<ReadHandler, DefaultCandidate>
  963. {
  964. static typename Associator<ReadHandler, DefaultCandidate>::type
  965. get(const detail::read_until_delim_op_v1<AsyncReadStream,
  966. DynamicBuffer_v1, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  967. {
  968. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  969. }
  970. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  971. typename Associator<ReadHandler, DefaultCandidate>::type)
  972. get(const detail::read_until_delim_op_v1<AsyncReadStream,
  973. DynamicBuffer_v1, ReadHandler>& h,
  974. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  975. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  976. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  977. {
  978. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  979. }
  980. };
  981. #endif // !defined(GENERATING_DOCUMENTATION)
  982. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  983. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  984. std::size_t)) ReadToken>
  985. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  986. void (boost::system::error_code, std::size_t))
  987. async_read_until(AsyncReadStream& s,
  988. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  989. char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  990. typename constraint<
  991. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  992. >::type,
  993. typename constraint<
  994. !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  995. >::type)
  996. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  997. async_initiate<ReadToken,
  998. void (boost::system::error_code, std::size_t)>(
  999. declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream> >(),
  1000. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim)))
  1001. {
  1002. return async_initiate<ReadToken,
  1003. void (boost::system::error_code, std::size_t)>(
  1004. detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
  1005. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);
  1006. }
  1007. namespace detail
  1008. {
  1009. template <typename AsyncReadStream,
  1010. typename DynamicBuffer_v1, typename ReadHandler>
  1011. class read_until_delim_string_op_v1
  1012. : public base_from_cancellation_state<ReadHandler>
  1013. {
  1014. public:
  1015. template <typename BufferSequence>
  1016. read_until_delim_string_op_v1(AsyncReadStream& stream,
  1017. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  1018. const std::string& delim, ReadHandler& handler)
  1019. : base_from_cancellation_state<ReadHandler>(
  1020. handler, enable_partial_cancellation()),
  1021. stream_(stream),
  1022. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  1023. delim_(delim),
  1024. start_(0),
  1025. search_position_(0),
  1026. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  1027. {
  1028. }
  1029. #if defined(BOOST_ASIO_HAS_MOVE)
  1030. read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
  1031. : base_from_cancellation_state<ReadHandler>(other),
  1032. stream_(other.stream_),
  1033. buffers_(other.buffers_),
  1034. delim_(other.delim_),
  1035. start_(other.start_),
  1036. search_position_(other.search_position_),
  1037. handler_(other.handler_)
  1038. {
  1039. }
  1040. read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)
  1041. : base_from_cancellation_state<ReadHandler>(
  1042. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  1043. ReadHandler>)(other)),
  1044. stream_(other.stream_),
  1045. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  1046. delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
  1047. start_(other.start_),
  1048. search_position_(other.search_position_),
  1049. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  1050. {
  1051. }
  1052. #endif // defined(BOOST_ASIO_HAS_MOVE)
  1053. void operator()(boost::system::error_code ec,
  1054. std::size_t bytes_transferred, int start = 0)
  1055. {
  1056. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1057. std::size_t bytes_to_read;
  1058. switch (start_ = start)
  1059. {
  1060. case 1:
  1061. for (;;)
  1062. {
  1063. {
  1064. // Determine the range of the data to be searched.
  1065. typedef typename DynamicBuffer_v1::const_buffers_type
  1066. buffers_type;
  1067. typedef buffers_iterator<buffers_type> iterator;
  1068. buffers_type data_buffers = buffers_.data();
  1069. iterator begin = iterator::begin(data_buffers);
  1070. iterator start_pos = begin + search_position_;
  1071. iterator end = iterator::end(data_buffers);
  1072. // Look for a match.
  1073. std::pair<iterator, bool> result = detail::partial_search(
  1074. start_pos, end, delim_.begin(), delim_.end());
  1075. if (result.first != end && result.second)
  1076. {
  1077. // Full match. We're done.
  1078. search_position_ = result.first - begin + delim_.length();
  1079. bytes_to_read = 0;
  1080. }
  1081. // No match yet. Check if buffer is full.
  1082. else if (buffers_.size() == buffers_.max_size())
  1083. {
  1084. search_position_ = not_found;
  1085. bytes_to_read = 0;
  1086. }
  1087. // Need to read some more data.
  1088. else
  1089. {
  1090. if (result.first != end)
  1091. {
  1092. // Partial match. Next search needs to start from beginning of
  1093. // match.
  1094. search_position_ = result.first - begin;
  1095. }
  1096. else
  1097. {
  1098. // Next search can start with the new data.
  1099. search_position_ = end - begin;
  1100. }
  1101. bytes_to_read = std::min<std::size_t>(
  1102. std::max<std::size_t>(512,
  1103. buffers_.capacity() - buffers_.size()),
  1104. std::min<std::size_t>(65536,
  1105. buffers_.max_size() - buffers_.size()));
  1106. }
  1107. }
  1108. // Check if we're done.
  1109. if (!start && bytes_to_read == 0)
  1110. break;
  1111. // Start a new asynchronous read operation to obtain more data.
  1112. {
  1113. BOOST_ASIO_HANDLER_LOCATION((
  1114. __FILE__, __LINE__, "async_read_until"));
  1115. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1116. BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this));
  1117. }
  1118. return; default:
  1119. buffers_.commit(bytes_transferred);
  1120. if (ec || bytes_transferred == 0)
  1121. break;
  1122. if (this->cancelled() != cancellation_type::none)
  1123. {
  1124. ec = error::operation_aborted;
  1125. break;
  1126. }
  1127. }
  1128. const boost::system::error_code result_ec =
  1129. (search_position_ == not_found)
  1130. ? error::not_found : ec;
  1131. const std::size_t result_n =
  1132. (ec || search_position_ == not_found)
  1133. ? 0 : search_position_;
  1134. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  1135. }
  1136. }
  1137. //private:
  1138. AsyncReadStream& stream_;
  1139. DynamicBuffer_v1 buffers_;
  1140. std::string delim_;
  1141. int start_;
  1142. std::size_t search_position_;
  1143. ReadHandler handler_;
  1144. };
  1145. template <typename AsyncReadStream,
  1146. typename DynamicBuffer_v1, typename ReadHandler>
  1147. inline asio_handler_allocate_is_deprecated
  1148. asio_handler_allocate(std::size_t size,
  1149. read_until_delim_string_op_v1<AsyncReadStream,
  1150. DynamicBuffer_v1, ReadHandler>* this_handler)
  1151. {
  1152. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1153. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  1154. return asio_handler_allocate_is_no_longer_used();
  1155. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  1156. return boost_asio_handler_alloc_helpers::allocate(
  1157. size, this_handler->handler_);
  1158. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1159. }
  1160. template <typename AsyncReadStream,
  1161. typename DynamicBuffer_v1, typename ReadHandler>
  1162. inline asio_handler_deallocate_is_deprecated
  1163. asio_handler_deallocate(void* pointer, std::size_t size,
  1164. read_until_delim_string_op_v1<AsyncReadStream,
  1165. DynamicBuffer_v1, ReadHandler>* this_handler)
  1166. {
  1167. boost_asio_handler_alloc_helpers::deallocate(
  1168. pointer, size, this_handler->handler_);
  1169. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1170. return asio_handler_deallocate_is_no_longer_used();
  1171. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1172. }
  1173. template <typename AsyncReadStream,
  1174. typename DynamicBuffer_v1, typename ReadHandler>
  1175. inline bool asio_handler_is_continuation(
  1176. read_until_delim_string_op_v1<AsyncReadStream,
  1177. DynamicBuffer_v1, ReadHandler>* this_handler)
  1178. {
  1179. return this_handler->start_ == 0 ? true
  1180. : boost_asio_handler_cont_helpers::is_continuation(
  1181. this_handler->handler_);
  1182. }
  1183. template <typename Function, typename AsyncReadStream,
  1184. typename DynamicBuffer_v1, typename ReadHandler>
  1185. inline asio_handler_invoke_is_deprecated
  1186. asio_handler_invoke(Function& function,
  1187. read_until_delim_string_op_v1<AsyncReadStream,
  1188. DynamicBuffer_v1, ReadHandler>* this_handler)
  1189. {
  1190. boost_asio_handler_invoke_helpers::invoke(
  1191. function, this_handler->handler_);
  1192. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1193. return asio_handler_invoke_is_no_longer_used();
  1194. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1195. }
  1196. template <typename Function, typename AsyncReadStream,
  1197. typename DynamicBuffer_v1, typename ReadHandler>
  1198. inline asio_handler_invoke_is_deprecated
  1199. asio_handler_invoke(const Function& function,
  1200. read_until_delim_string_op_v1<AsyncReadStream,
  1201. DynamicBuffer_v1, ReadHandler>* this_handler)
  1202. {
  1203. boost_asio_handler_invoke_helpers::invoke(
  1204. function, this_handler->handler_);
  1205. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1206. return asio_handler_invoke_is_no_longer_used();
  1207. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1208. }
  1209. template <typename AsyncReadStream>
  1210. class initiate_async_read_until_delim_string_v1
  1211. {
  1212. public:
  1213. typedef typename AsyncReadStream::executor_type executor_type;
  1214. explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)
  1215. : stream_(stream)
  1216. {
  1217. }
  1218. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  1219. {
  1220. return stream_.get_executor();
  1221. }
  1222. template <typename ReadHandler, typename DynamicBuffer_v1>
  1223. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  1224. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  1225. const std::string& delim) const
  1226. {
  1227. // If you get an error on the following line it means that your handler
  1228. // does not meet the documented type requirements for a ReadHandler.
  1229. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1230. non_const_lvalue<ReadHandler> handler2(handler);
  1231. read_until_delim_string_op_v1<AsyncReadStream,
  1232. typename decay<DynamicBuffer_v1>::type,
  1233. typename decay<ReadHandler>::type>(
  1234. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1235. delim, handler2.value)(boost::system::error_code(), 0, 1);
  1236. }
  1237. private:
  1238. AsyncReadStream& stream_;
  1239. };
  1240. } // namespace detail
  1241. #if !defined(GENERATING_DOCUMENTATION)
  1242. template <template <typename, typename> class Associator,
  1243. typename AsyncReadStream, typename DynamicBuffer_v1,
  1244. typename ReadHandler, typename DefaultCandidate>
  1245. struct associator<Associator,
  1246. detail::read_until_delim_string_op_v1<AsyncReadStream,
  1247. DynamicBuffer_v1, ReadHandler>,
  1248. DefaultCandidate>
  1249. : Associator<ReadHandler, DefaultCandidate>
  1250. {
  1251. static typename Associator<ReadHandler, DefaultCandidate>::type
  1252. get(const detail::read_until_delim_string_op_v1<AsyncReadStream,
  1253. DynamicBuffer_v1, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  1254. {
  1255. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1256. }
  1257. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  1258. typename Associator<ReadHandler, DefaultCandidate>::type)
  1259. get(const detail::read_until_delim_string_op_v1<AsyncReadStream,
  1260. DynamicBuffer_v1, ReadHandler>& h,
  1261. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  1262. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  1263. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  1264. {
  1265. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1266. }
  1267. };
  1268. #endif // !defined(GENERATING_DOCUMENTATION)
  1269. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1270. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1271. std::size_t)) ReadToken>
  1272. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1273. void (boost::system::error_code, std::size_t))
  1274. async_read_until(AsyncReadStream& s,
  1275. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  1276. BOOST_ASIO_STRING_VIEW_PARAM delim,
  1277. BOOST_ASIO_MOVE_ARG(ReadToken) token,
  1278. typename constraint<
  1279. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  1280. >::type,
  1281. typename constraint<
  1282. !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  1283. >::type)
  1284. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1285. async_initiate<ReadToken,
  1286. void (boost::system::error_code, std::size_t)>(
  1287. declval<detail::initiate_async_read_until_delim_string_v1<
  1288. AsyncReadStream> >(),
  1289. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1290. static_cast<std::string>(delim))))
  1291. {
  1292. return async_initiate<ReadToken,
  1293. void (boost::system::error_code, std::size_t)>(
  1294. detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
  1295. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1296. static_cast<std::string>(delim));
  1297. }
  1298. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  1299. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1300. namespace detail
  1301. {
  1302. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1303. typename RegEx, typename ReadHandler>
  1304. class read_until_expr_op_v1
  1305. : public base_from_cancellation_state<ReadHandler>
  1306. {
  1307. public:
  1308. template <typename BufferSequence>
  1309. read_until_expr_op_v1(AsyncReadStream& stream,
  1310. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  1311. const boost::regex& expr, ReadHandler& handler)
  1312. : base_from_cancellation_state<ReadHandler>(
  1313. handler, enable_partial_cancellation()),
  1314. stream_(stream),
  1315. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  1316. expr_(expr),
  1317. start_(0),
  1318. search_position_(0),
  1319. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  1320. {
  1321. }
  1322. #if defined(BOOST_ASIO_HAS_MOVE)
  1323. read_until_expr_op_v1(const read_until_expr_op_v1& other)
  1324. : base_from_cancellation_state<ReadHandler>(other),
  1325. stream_(other.stream_),
  1326. buffers_(other.buffers_),
  1327. expr_(other.expr_),
  1328. start_(other.start_),
  1329. search_position_(other.search_position_),
  1330. handler_(other.handler_)
  1331. {
  1332. }
  1333. read_until_expr_op_v1(read_until_expr_op_v1&& other)
  1334. : base_from_cancellation_state<ReadHandler>(
  1335. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  1336. ReadHandler>)(other)),
  1337. stream_(other.stream_),
  1338. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  1339. expr_(other.expr_),
  1340. start_(other.start_),
  1341. search_position_(other.search_position_),
  1342. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  1343. {
  1344. }
  1345. #endif // defined(BOOST_ASIO_HAS_MOVE)
  1346. void operator()(boost::system::error_code ec,
  1347. std::size_t bytes_transferred, int start = 0)
  1348. {
  1349. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1350. std::size_t bytes_to_read;
  1351. switch (start_ = start)
  1352. {
  1353. case 1:
  1354. for (;;)
  1355. {
  1356. {
  1357. // Determine the range of the data to be searched.
  1358. typedef typename DynamicBuffer_v1::const_buffers_type
  1359. buffers_type;
  1360. typedef buffers_iterator<buffers_type> iterator;
  1361. buffers_type data_buffers = buffers_.data();
  1362. iterator begin = iterator::begin(data_buffers);
  1363. iterator start_pos = begin + search_position_;
  1364. iterator end = iterator::end(data_buffers);
  1365. // Look for a match.
  1366. boost::match_results<iterator,
  1367. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  1368. match_results;
  1369. bool match = regex_search(start_pos, end, match_results, expr_,
  1370. boost::match_default | boost::match_partial);
  1371. if (match && match_results[0].matched)
  1372. {
  1373. // Full match. We're done.
  1374. search_position_ = match_results[0].second - begin;
  1375. bytes_to_read = 0;
  1376. }
  1377. // No match yet. Check if buffer is full.
  1378. else if (buffers_.size() == buffers_.max_size())
  1379. {
  1380. search_position_ = not_found;
  1381. bytes_to_read = 0;
  1382. }
  1383. // Need to read some more data.
  1384. else
  1385. {
  1386. if (match)
  1387. {
  1388. // Partial match. Next search needs to start from beginning of
  1389. // match.
  1390. search_position_ = match_results[0].first - begin;
  1391. }
  1392. else
  1393. {
  1394. // Next search can start with the new data.
  1395. search_position_ = end - begin;
  1396. }
  1397. bytes_to_read = std::min<std::size_t>(
  1398. std::max<std::size_t>(512,
  1399. buffers_.capacity() - buffers_.size()),
  1400. std::min<std::size_t>(65536,
  1401. buffers_.max_size() - buffers_.size()));
  1402. }
  1403. }
  1404. // Check if we're done.
  1405. if (!start && bytes_to_read == 0)
  1406. break;
  1407. // Start a new asynchronous read operation to obtain more data.
  1408. {
  1409. BOOST_ASIO_HANDLER_LOCATION((
  1410. __FILE__, __LINE__, "async_read_until"));
  1411. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1412. BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));
  1413. }
  1414. return; default:
  1415. buffers_.commit(bytes_transferred);
  1416. if (ec || bytes_transferred == 0)
  1417. break;
  1418. if (this->cancelled() != cancellation_type::none)
  1419. {
  1420. ec = error::operation_aborted;
  1421. break;
  1422. }
  1423. }
  1424. const boost::system::error_code result_ec =
  1425. (search_position_ == not_found)
  1426. ? error::not_found : ec;
  1427. const std::size_t result_n =
  1428. (ec || search_position_ == not_found)
  1429. ? 0 : search_position_;
  1430. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  1431. }
  1432. }
  1433. //private:
  1434. AsyncReadStream& stream_;
  1435. DynamicBuffer_v1 buffers_;
  1436. RegEx expr_;
  1437. int start_;
  1438. std::size_t search_position_;
  1439. ReadHandler handler_;
  1440. };
  1441. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1442. typename RegEx, typename ReadHandler>
  1443. inline asio_handler_allocate_is_deprecated
  1444. asio_handler_allocate(std::size_t size,
  1445. read_until_expr_op_v1<AsyncReadStream,
  1446. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1447. {
  1448. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1449. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  1450. return asio_handler_allocate_is_no_longer_used();
  1451. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  1452. return boost_asio_handler_alloc_helpers::allocate(
  1453. size, this_handler->handler_);
  1454. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1455. }
  1456. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1457. typename RegEx, typename ReadHandler>
  1458. inline asio_handler_deallocate_is_deprecated
  1459. asio_handler_deallocate(void* pointer, std::size_t size,
  1460. read_until_expr_op_v1<AsyncReadStream,
  1461. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1462. {
  1463. boost_asio_handler_alloc_helpers::deallocate(
  1464. pointer, size, this_handler->handler_);
  1465. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1466. return asio_handler_deallocate_is_no_longer_used();
  1467. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1468. }
  1469. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1470. typename RegEx, typename ReadHandler>
  1471. inline bool asio_handler_is_continuation(
  1472. read_until_expr_op_v1<AsyncReadStream,
  1473. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1474. {
  1475. return this_handler->start_ == 0 ? true
  1476. : boost_asio_handler_cont_helpers::is_continuation(
  1477. this_handler->handler_);
  1478. }
  1479. template <typename Function, typename AsyncReadStream,
  1480. typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
  1481. inline asio_handler_invoke_is_deprecated
  1482. asio_handler_invoke(Function& function,
  1483. read_until_expr_op_v1<AsyncReadStream,
  1484. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1485. {
  1486. boost_asio_handler_invoke_helpers::invoke(
  1487. function, this_handler->handler_);
  1488. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1489. return asio_handler_invoke_is_no_longer_used();
  1490. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1491. }
  1492. template <typename Function, typename AsyncReadStream,
  1493. typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
  1494. inline asio_handler_invoke_is_deprecated
  1495. asio_handler_invoke(const Function& function,
  1496. read_until_expr_op_v1<AsyncReadStream,
  1497. DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
  1498. {
  1499. boost_asio_handler_invoke_helpers::invoke(
  1500. function, this_handler->handler_);
  1501. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1502. return asio_handler_invoke_is_no_longer_used();
  1503. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1504. }
  1505. template <typename AsyncReadStream>
  1506. class initiate_async_read_until_expr_v1
  1507. {
  1508. public:
  1509. typedef typename AsyncReadStream::executor_type executor_type;
  1510. explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)
  1511. : stream_(stream)
  1512. {
  1513. }
  1514. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  1515. {
  1516. return stream_.get_executor();
  1517. }
  1518. template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>
  1519. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  1520. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) const
  1521. {
  1522. // If you get an error on the following line it means that your handler
  1523. // does not meet the documented type requirements for a ReadHandler.
  1524. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1525. non_const_lvalue<ReadHandler> handler2(handler);
  1526. read_until_expr_op_v1<AsyncReadStream,
  1527. typename decay<DynamicBuffer_v1>::type,
  1528. RegEx, typename decay<ReadHandler>::type>(
  1529. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1530. expr, handler2.value)(boost::system::error_code(), 0, 1);
  1531. }
  1532. private:
  1533. AsyncReadStream& stream_;
  1534. };
  1535. } // namespace detail
  1536. #if !defined(GENERATING_DOCUMENTATION)
  1537. template <template <typename, typename> class Associator,
  1538. typename AsyncReadStream, typename DynamicBuffer_v1,
  1539. typename RegEx, typename ReadHandler, typename DefaultCandidate>
  1540. struct associator<Associator,
  1541. detail::read_until_expr_op_v1<AsyncReadStream,
  1542. DynamicBuffer_v1, RegEx, ReadHandler>,
  1543. DefaultCandidate>
  1544. : Associator<ReadHandler, DefaultCandidate>
  1545. {
  1546. static typename Associator<ReadHandler, DefaultCandidate>::type
  1547. get(const detail::read_until_expr_op_v1<AsyncReadStream,
  1548. DynamicBuffer_v1, RegEx, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  1549. {
  1550. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1551. }
  1552. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  1553. typename Associator<ReadHandler, DefaultCandidate>::type)
  1554. get(const detail::read_until_expr_op_v1<AsyncReadStream,
  1555. DynamicBuffer_v1, RegEx, ReadHandler>& h,
  1556. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  1557. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  1558. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  1559. {
  1560. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1561. }
  1562. };
  1563. #endif // !defined(GENERATING_DOCUMENTATION)
  1564. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1565. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1566. std::size_t)) ReadToken>
  1567. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1568. void (boost::system::error_code, std::size_t))
  1569. async_read_until(AsyncReadStream& s,
  1570. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  1571. const boost::regex& expr,
  1572. BOOST_ASIO_MOVE_ARG(ReadToken) token,
  1573. typename constraint<
  1574. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  1575. >::type,
  1576. typename constraint<
  1577. !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  1578. >::type)
  1579. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1580. async_initiate<ReadToken,
  1581. void (boost::system::error_code, std::size_t)>(
  1582. declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream> >(),
  1583. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr)))
  1584. {
  1585. return async_initiate<ReadToken,
  1586. void (boost::system::error_code, std::size_t)>(
  1587. detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
  1588. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);
  1589. }
  1590. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1591. namespace detail
  1592. {
  1593. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1594. typename MatchCondition, typename ReadHandler>
  1595. class read_until_match_op_v1
  1596. : public base_from_cancellation_state<ReadHandler>
  1597. {
  1598. public:
  1599. template <typename BufferSequence>
  1600. read_until_match_op_v1(AsyncReadStream& stream,
  1601. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  1602. MatchCondition match_condition, ReadHandler& handler)
  1603. : base_from_cancellation_state<ReadHandler>(
  1604. handler, enable_partial_cancellation()),
  1605. stream_(stream),
  1606. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  1607. match_condition_(match_condition),
  1608. start_(0),
  1609. search_position_(0),
  1610. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  1611. {
  1612. }
  1613. #if defined(BOOST_ASIO_HAS_MOVE)
  1614. read_until_match_op_v1(const read_until_match_op_v1& other)
  1615. : base_from_cancellation_state<ReadHandler>(other),
  1616. stream_(other.stream_),
  1617. buffers_(other.buffers_),
  1618. match_condition_(other.match_condition_),
  1619. start_(other.start_),
  1620. search_position_(other.search_position_),
  1621. handler_(other.handler_)
  1622. {
  1623. }
  1624. read_until_match_op_v1(read_until_match_op_v1&& other)
  1625. : base_from_cancellation_state<ReadHandler>(
  1626. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  1627. ReadHandler>)(other)),
  1628. stream_(other.stream_),
  1629. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  1630. match_condition_(other.match_condition_),
  1631. start_(other.start_),
  1632. search_position_(other.search_position_),
  1633. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  1634. {
  1635. }
  1636. #endif // defined(BOOST_ASIO_HAS_MOVE)
  1637. void operator()(boost::system::error_code ec,
  1638. std::size_t bytes_transferred, int start = 0)
  1639. {
  1640. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1641. std::size_t bytes_to_read;
  1642. switch (start_ = start)
  1643. {
  1644. case 1:
  1645. for (;;)
  1646. {
  1647. {
  1648. // Determine the range of the data to be searched.
  1649. typedef typename DynamicBuffer_v1::const_buffers_type
  1650. buffers_type;
  1651. typedef buffers_iterator<buffers_type> iterator;
  1652. buffers_type data_buffers = buffers_.data();
  1653. iterator begin = iterator::begin(data_buffers);
  1654. iterator start_pos = begin + search_position_;
  1655. iterator end = iterator::end(data_buffers);
  1656. // Look for a match.
  1657. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  1658. if (result.second)
  1659. {
  1660. // Full match. We're done.
  1661. search_position_ = result.first - begin;
  1662. bytes_to_read = 0;
  1663. }
  1664. // No match yet. Check if buffer is full.
  1665. else if (buffers_.size() == buffers_.max_size())
  1666. {
  1667. search_position_ = not_found;
  1668. bytes_to_read = 0;
  1669. }
  1670. // Need to read some more data.
  1671. else
  1672. {
  1673. if (result.first != end)
  1674. {
  1675. // Partial match. Next search needs to start from beginning of
  1676. // match.
  1677. search_position_ = result.first - begin;
  1678. }
  1679. else
  1680. {
  1681. // Next search can start with the new data.
  1682. search_position_ = end - begin;
  1683. }
  1684. bytes_to_read = std::min<std::size_t>(
  1685. std::max<std::size_t>(512,
  1686. buffers_.capacity() - buffers_.size()),
  1687. std::min<std::size_t>(65536,
  1688. buffers_.max_size() - buffers_.size()));
  1689. }
  1690. }
  1691. // Check if we're done.
  1692. if (!start && bytes_to_read == 0)
  1693. break;
  1694. // Start a new asynchronous read operation to obtain more data.
  1695. {
  1696. BOOST_ASIO_HANDLER_LOCATION((
  1697. __FILE__, __LINE__, "async_read_until"));
  1698. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1699. BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this));
  1700. }
  1701. return; default:
  1702. buffers_.commit(bytes_transferred);
  1703. if (ec || bytes_transferred == 0)
  1704. break;
  1705. if (this->cancelled() != cancellation_type::none)
  1706. {
  1707. ec = error::operation_aborted;
  1708. break;
  1709. }
  1710. }
  1711. const boost::system::error_code result_ec =
  1712. (search_position_ == not_found)
  1713. ? error::not_found : ec;
  1714. const std::size_t result_n =
  1715. (ec || search_position_ == not_found)
  1716. ? 0 : search_position_;
  1717. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  1718. }
  1719. }
  1720. //private:
  1721. AsyncReadStream& stream_;
  1722. DynamicBuffer_v1 buffers_;
  1723. MatchCondition match_condition_;
  1724. int start_;
  1725. std::size_t search_position_;
  1726. ReadHandler handler_;
  1727. };
  1728. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1729. typename MatchCondition, typename ReadHandler>
  1730. inline asio_handler_allocate_is_deprecated
  1731. asio_handler_allocate(std::size_t size,
  1732. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1733. MatchCondition, ReadHandler>* this_handler)
  1734. {
  1735. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1736. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  1737. return asio_handler_allocate_is_no_longer_used();
  1738. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  1739. return boost_asio_handler_alloc_helpers::allocate(
  1740. size, this_handler->handler_);
  1741. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1742. }
  1743. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1744. typename MatchCondition, typename ReadHandler>
  1745. inline asio_handler_deallocate_is_deprecated
  1746. asio_handler_deallocate(void* pointer, std::size_t size,
  1747. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1748. MatchCondition, ReadHandler>* this_handler)
  1749. {
  1750. boost_asio_handler_alloc_helpers::deallocate(
  1751. pointer, size, this_handler->handler_);
  1752. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1753. return asio_handler_deallocate_is_no_longer_used();
  1754. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1755. }
  1756. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  1757. typename MatchCondition, typename ReadHandler>
  1758. inline bool asio_handler_is_continuation(
  1759. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1760. MatchCondition, ReadHandler>* this_handler)
  1761. {
  1762. return this_handler->start_ == 0 ? true
  1763. : boost_asio_handler_cont_helpers::is_continuation(
  1764. this_handler->handler_);
  1765. }
  1766. template <typename Function, typename AsyncReadStream,
  1767. typename DynamicBuffer_v1, typename MatchCondition,
  1768. typename ReadHandler>
  1769. inline asio_handler_invoke_is_deprecated
  1770. asio_handler_invoke(Function& function,
  1771. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1772. MatchCondition, ReadHandler>* this_handler)
  1773. {
  1774. boost_asio_handler_invoke_helpers::invoke(
  1775. function, this_handler->handler_);
  1776. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1777. return asio_handler_invoke_is_no_longer_used();
  1778. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1779. }
  1780. template <typename Function, typename AsyncReadStream,
  1781. typename DynamicBuffer_v1, typename MatchCondition,
  1782. typename ReadHandler>
  1783. inline asio_handler_invoke_is_deprecated
  1784. asio_handler_invoke(const Function& function,
  1785. read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
  1786. MatchCondition, ReadHandler>* this_handler)
  1787. {
  1788. boost_asio_handler_invoke_helpers::invoke(
  1789. function, this_handler->handler_);
  1790. #if defined(BOOST_ASIO_NO_DEPRECATED)
  1791. return asio_handler_invoke_is_no_longer_used();
  1792. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  1793. }
  1794. template <typename AsyncReadStream>
  1795. class initiate_async_read_until_match_v1
  1796. {
  1797. public:
  1798. typedef typename AsyncReadStream::executor_type executor_type;
  1799. explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)
  1800. : stream_(stream)
  1801. {
  1802. }
  1803. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  1804. {
  1805. return stream_.get_executor();
  1806. }
  1807. template <typename ReadHandler,
  1808. typename DynamicBuffer_v1, typename MatchCondition>
  1809. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  1810. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  1811. MatchCondition match_condition) const
  1812. {
  1813. // If you get an error on the following line it means that your handler
  1814. // does not meet the documented type requirements for a ReadHandler.
  1815. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1816. non_const_lvalue<ReadHandler> handler2(handler);
  1817. read_until_match_op_v1<AsyncReadStream,
  1818. typename decay<DynamicBuffer_v1>::type,
  1819. MatchCondition, typename decay<ReadHandler>::type>(
  1820. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1821. match_condition, handler2.value)(boost::system::error_code(), 0, 1);
  1822. }
  1823. private:
  1824. AsyncReadStream& stream_;
  1825. };
  1826. } // namespace detail
  1827. #if !defined(GENERATING_DOCUMENTATION)
  1828. template <template <typename, typename> class Associator,
  1829. typename AsyncReadStream, typename DynamicBuffer_v1,
  1830. typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
  1831. struct associator<Associator,
  1832. detail::read_until_match_op_v1<AsyncReadStream,
  1833. DynamicBuffer_v1, MatchCondition, ReadHandler>,
  1834. DefaultCandidate>
  1835. : Associator<ReadHandler, DefaultCandidate>
  1836. {
  1837. static typename Associator<ReadHandler, DefaultCandidate>::type
  1838. get(const detail::read_until_match_op_v1<AsyncReadStream,
  1839. DynamicBuffer_v1, MatchCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  1840. {
  1841. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  1842. }
  1843. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  1844. typename Associator<ReadHandler, DefaultCandidate>::type)
  1845. get(const detail::read_until_match_op_v1<AsyncReadStream,
  1846. DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
  1847. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  1848. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  1849. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  1850. {
  1851. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  1852. }
  1853. };
  1854. #endif // !defined(GENERATING_DOCUMENTATION)
  1855. template <typename AsyncReadStream,
  1856. typename DynamicBuffer_v1, typename MatchCondition,
  1857. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1858. std::size_t)) ReadToken>
  1859. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1860. void (boost::system::error_code, std::size_t))
  1861. async_read_until(AsyncReadStream& s,
  1862. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  1863. MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  1864. typename constraint<
  1865. is_match_condition<MatchCondition>::value
  1866. >::type,
  1867. typename constraint<
  1868. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  1869. >::type,
  1870. typename constraint<
  1871. !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  1872. >::type)
  1873. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1874. async_initiate<ReadToken,
  1875. void (boost::system::error_code, std::size_t)>(
  1876. declval<detail::initiate_async_read_until_match_v1<AsyncReadStream> >(),
  1877. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1878. match_condition)))
  1879. {
  1880. return async_initiate<ReadToken,
  1881. void (boost::system::error_code, std::size_t)>(
  1882. detail::initiate_async_read_until_match_v1<AsyncReadStream>(s),
  1883. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  1884. match_condition);
  1885. }
  1886. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  1887. template <typename AsyncReadStream, typename Allocator,
  1888. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1889. std::size_t)) ReadToken>
  1890. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1891. void (boost::system::error_code, std::size_t))
  1892. async_read_until(AsyncReadStream& s,
  1893. boost::asio::basic_streambuf<Allocator>& b,
  1894. char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token)
  1895. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1896. async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1897. delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token))))
  1898. {
  1899. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1900. delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
  1901. }
  1902. template <typename AsyncReadStream, typename Allocator,
  1903. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1904. std::size_t)) ReadToken>
  1905. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1906. void (boost::system::error_code, std::size_t))
  1907. async_read_until(AsyncReadStream& s,
  1908. boost::asio::basic_streambuf<Allocator>& b,
  1909. BOOST_ASIO_STRING_VIEW_PARAM delim,
  1910. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  1911. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1912. async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1913. delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token))))
  1914. {
  1915. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1916. delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
  1917. }
  1918. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1919. template <typename AsyncReadStream, typename Allocator,
  1920. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1921. std::size_t)) ReadToken>
  1922. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1923. void (boost::system::error_code, std::size_t))
  1924. async_read_until(AsyncReadStream& s,
  1925. boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
  1926. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  1927. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1928. async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1929. expr, BOOST_ASIO_MOVE_CAST(ReadToken)(token))))
  1930. {
  1931. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1932. expr, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
  1933. }
  1934. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1935. template <typename AsyncReadStream, typename Allocator, typename MatchCondition,
  1936. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  1937. std::size_t)) ReadToken>
  1938. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  1939. void (boost::system::error_code, std::size_t))
  1940. async_read_until(AsyncReadStream& s,
  1941. boost::asio::basic_streambuf<Allocator>& b,
  1942. MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  1943. typename constraint<is_match_condition<MatchCondition>::value>::type)
  1944. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  1945. async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1946. match_condition, BOOST_ASIO_MOVE_CAST(ReadToken)(token))))
  1947. {
  1948. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1949. match_condition, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
  1950. }
  1951. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  1952. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  1953. #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
  1954. namespace detail
  1955. {
  1956. template <typename AsyncReadStream,
  1957. typename DynamicBuffer_v2, typename ReadHandler>
  1958. class read_until_delim_op_v2
  1959. : public base_from_cancellation_state<ReadHandler>
  1960. {
  1961. public:
  1962. template <typename BufferSequence>
  1963. read_until_delim_op_v2(AsyncReadStream& stream,
  1964. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  1965. char delim, ReadHandler& handler)
  1966. : base_from_cancellation_state<ReadHandler>(
  1967. handler, enable_partial_cancellation()),
  1968. stream_(stream),
  1969. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  1970. delim_(delim),
  1971. start_(0),
  1972. search_position_(0),
  1973. bytes_to_read_(0),
  1974. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  1975. {
  1976. }
  1977. #if defined(BOOST_ASIO_HAS_MOVE)
  1978. read_until_delim_op_v2(const read_until_delim_op_v2& other)
  1979. : base_from_cancellation_state<ReadHandler>(other),
  1980. stream_(other.stream_),
  1981. buffers_(other.buffers_),
  1982. delim_(other.delim_),
  1983. start_(other.start_),
  1984. search_position_(other.search_position_),
  1985. bytes_to_read_(other.bytes_to_read_),
  1986. handler_(other.handler_)
  1987. {
  1988. }
  1989. read_until_delim_op_v2(read_until_delim_op_v2&& other)
  1990. : base_from_cancellation_state<ReadHandler>(
  1991. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  1992. ReadHandler>)(other)),
  1993. stream_(other.stream_),
  1994. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  1995. delim_(other.delim_),
  1996. start_(other.start_),
  1997. search_position_(other.search_position_),
  1998. bytes_to_read_(other.bytes_to_read_),
  1999. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  2000. {
  2001. }
  2002. #endif // defined(BOOST_ASIO_HAS_MOVE)
  2003. void operator()(boost::system::error_code ec,
  2004. std::size_t bytes_transferred, int start = 0)
  2005. {
  2006. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2007. std::size_t pos;
  2008. switch (start_ = start)
  2009. {
  2010. case 1:
  2011. for (;;)
  2012. {
  2013. {
  2014. // Determine the range of the data to be searched.
  2015. typedef typename DynamicBuffer_v2::const_buffers_type
  2016. buffers_type;
  2017. typedef buffers_iterator<buffers_type> iterator;
  2018. buffers_type data_buffers =
  2019. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2020. 0, buffers_.size());
  2021. iterator begin = iterator::begin(data_buffers);
  2022. iterator start_pos = begin + search_position_;
  2023. iterator end = iterator::end(data_buffers);
  2024. // Look for a match.
  2025. iterator iter = std::find(start_pos, end, delim_);
  2026. if (iter != end)
  2027. {
  2028. // Found a match. We're done.
  2029. search_position_ = iter - begin + 1;
  2030. bytes_to_read_ = 0;
  2031. }
  2032. // No match yet. Check if buffer is full.
  2033. else if (buffers_.size() == buffers_.max_size())
  2034. {
  2035. search_position_ = not_found;
  2036. bytes_to_read_ = 0;
  2037. }
  2038. // Need to read some more data.
  2039. else
  2040. {
  2041. // Next search can start with the new data.
  2042. search_position_ = end - begin;
  2043. bytes_to_read_ = std::min<std::size_t>(
  2044. std::max<std::size_t>(512,
  2045. buffers_.capacity() - buffers_.size()),
  2046. std::min<std::size_t>(65536,
  2047. buffers_.max_size() - buffers_.size()));
  2048. }
  2049. }
  2050. // Check if we're done.
  2051. if (!start && bytes_to_read_ == 0)
  2052. break;
  2053. // Start a new asynchronous read operation to obtain more data.
  2054. pos = buffers_.size();
  2055. buffers_.grow(bytes_to_read_);
  2056. {
  2057. BOOST_ASIO_HANDLER_LOCATION((
  2058. __FILE__, __LINE__, "async_read_until"));
  2059. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2060. BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));
  2061. }
  2062. return; default:
  2063. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2064. if (ec || bytes_transferred == 0)
  2065. break;
  2066. if (this->cancelled() != cancellation_type::none)
  2067. {
  2068. ec = error::operation_aborted;
  2069. break;
  2070. }
  2071. }
  2072. const boost::system::error_code result_ec =
  2073. (search_position_ == not_found)
  2074. ? error::not_found : ec;
  2075. const std::size_t result_n =
  2076. (ec || search_position_ == not_found)
  2077. ? 0 : search_position_;
  2078. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  2079. }
  2080. }
  2081. //private:
  2082. AsyncReadStream& stream_;
  2083. DynamicBuffer_v2 buffers_;
  2084. char delim_;
  2085. int start_;
  2086. std::size_t search_position_;
  2087. std::size_t bytes_to_read_;
  2088. ReadHandler handler_;
  2089. };
  2090. template <typename AsyncReadStream,
  2091. typename DynamicBuffer_v2, typename ReadHandler>
  2092. inline asio_handler_allocate_is_deprecated
  2093. asio_handler_allocate(std::size_t size,
  2094. read_until_delim_op_v2<AsyncReadStream,
  2095. DynamicBuffer_v2, ReadHandler>* this_handler)
  2096. {
  2097. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2098. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  2099. return asio_handler_allocate_is_no_longer_used();
  2100. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  2101. return boost_asio_handler_alloc_helpers::allocate(
  2102. size, this_handler->handler_);
  2103. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2104. }
  2105. template <typename AsyncReadStream,
  2106. typename DynamicBuffer_v2, typename ReadHandler>
  2107. inline asio_handler_deallocate_is_deprecated
  2108. asio_handler_deallocate(void* pointer, std::size_t size,
  2109. read_until_delim_op_v2<AsyncReadStream,
  2110. DynamicBuffer_v2, ReadHandler>* this_handler)
  2111. {
  2112. boost_asio_handler_alloc_helpers::deallocate(
  2113. pointer, size, this_handler->handler_);
  2114. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2115. return asio_handler_deallocate_is_no_longer_used();
  2116. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2117. }
  2118. template <typename AsyncReadStream,
  2119. typename DynamicBuffer_v2, typename ReadHandler>
  2120. inline bool asio_handler_is_continuation(
  2121. read_until_delim_op_v2<AsyncReadStream,
  2122. DynamicBuffer_v2, ReadHandler>* this_handler)
  2123. {
  2124. return this_handler->start_ == 0 ? true
  2125. : boost_asio_handler_cont_helpers::is_continuation(
  2126. this_handler->handler_);
  2127. }
  2128. template <typename Function, typename AsyncReadStream,
  2129. typename DynamicBuffer_v2, typename ReadHandler>
  2130. inline asio_handler_invoke_is_deprecated
  2131. asio_handler_invoke(Function& function,
  2132. read_until_delim_op_v2<AsyncReadStream,
  2133. DynamicBuffer_v2, ReadHandler>* this_handler)
  2134. {
  2135. boost_asio_handler_invoke_helpers::invoke(
  2136. function, this_handler->handler_);
  2137. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2138. return asio_handler_invoke_is_no_longer_used();
  2139. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2140. }
  2141. template <typename Function, typename AsyncReadStream,
  2142. typename DynamicBuffer_v2, typename ReadHandler>
  2143. inline asio_handler_invoke_is_deprecated
  2144. asio_handler_invoke(const Function& function,
  2145. read_until_delim_op_v2<AsyncReadStream,
  2146. DynamicBuffer_v2, ReadHandler>* this_handler)
  2147. {
  2148. boost_asio_handler_invoke_helpers::invoke(
  2149. function, this_handler->handler_);
  2150. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2151. return asio_handler_invoke_is_no_longer_used();
  2152. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2153. }
  2154. template <typename AsyncReadStream>
  2155. class initiate_async_read_until_delim_v2
  2156. {
  2157. public:
  2158. typedef typename AsyncReadStream::executor_type executor_type;
  2159. explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)
  2160. : stream_(stream)
  2161. {
  2162. }
  2163. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  2164. {
  2165. return stream_.get_executor();
  2166. }
  2167. template <typename ReadHandler, typename DynamicBuffer_v2>
  2168. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  2169. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) const
  2170. {
  2171. // If you get an error on the following line it means that your handler
  2172. // does not meet the documented type requirements for a ReadHandler.
  2173. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2174. non_const_lvalue<ReadHandler> handler2(handler);
  2175. read_until_delim_op_v2<AsyncReadStream,
  2176. typename decay<DynamicBuffer_v2>::type,
  2177. typename decay<ReadHandler>::type>(
  2178. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  2179. delim, handler2.value)(boost::system::error_code(), 0, 1);
  2180. }
  2181. private:
  2182. AsyncReadStream& stream_;
  2183. };
  2184. } // namespace detail
  2185. #if !defined(GENERATING_DOCUMENTATION)
  2186. template <template <typename, typename> class Associator,
  2187. typename AsyncReadStream, typename DynamicBuffer_v2,
  2188. typename ReadHandler, typename DefaultCandidate>
  2189. struct associator<Associator,
  2190. detail::read_until_delim_op_v2<AsyncReadStream,
  2191. DynamicBuffer_v2, ReadHandler>,
  2192. DefaultCandidate>
  2193. : Associator<ReadHandler, DefaultCandidate>
  2194. {
  2195. static typename Associator<ReadHandler, DefaultCandidate>::type
  2196. get(const detail::read_until_delim_op_v2<AsyncReadStream,
  2197. DynamicBuffer_v2, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  2198. {
  2199. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2200. }
  2201. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  2202. typename Associator<ReadHandler, DefaultCandidate>::type)
  2203. get(const detail::read_until_delim_op_v2<AsyncReadStream,
  2204. DynamicBuffer_v2, ReadHandler>& h,
  2205. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  2206. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  2207. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  2208. {
  2209. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2210. }
  2211. };
  2212. #endif // !defined(GENERATING_DOCUMENTATION)
  2213. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2214. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  2215. std::size_t)) ReadToken>
  2216. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  2217. void (boost::system::error_code, std::size_t))
  2218. async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  2219. char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  2220. typename constraint<
  2221. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2222. >::type)
  2223. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  2224. async_initiate<ReadToken,
  2225. void (boost::system::error_code, std::size_t)>(
  2226. declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream> >(),
  2227. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim)))
  2228. {
  2229. return async_initiate<ReadToken,
  2230. void (boost::system::error_code, std::size_t)>(
  2231. detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),
  2232. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);
  2233. }
  2234. namespace detail
  2235. {
  2236. template <typename AsyncReadStream,
  2237. typename DynamicBuffer_v2, typename ReadHandler>
  2238. class read_until_delim_string_op_v2
  2239. : public base_from_cancellation_state<ReadHandler>
  2240. {
  2241. public:
  2242. template <typename BufferSequence>
  2243. read_until_delim_string_op_v2(AsyncReadStream& stream,
  2244. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  2245. const std::string& delim, ReadHandler& handler)
  2246. : base_from_cancellation_state<ReadHandler>(
  2247. handler, enable_partial_cancellation()),
  2248. stream_(stream),
  2249. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  2250. delim_(delim),
  2251. start_(0),
  2252. search_position_(0),
  2253. bytes_to_read_(0),
  2254. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  2255. {
  2256. }
  2257. #if defined(BOOST_ASIO_HAS_MOVE)
  2258. read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
  2259. : base_from_cancellation_state<ReadHandler>(other),
  2260. stream_(other.stream_),
  2261. buffers_(other.buffers_),
  2262. delim_(other.delim_),
  2263. start_(other.start_),
  2264. search_position_(other.search_position_),
  2265. bytes_to_read_(other.bytes_to_read_),
  2266. handler_(other.handler_)
  2267. {
  2268. }
  2269. read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
  2270. : base_from_cancellation_state<ReadHandler>(
  2271. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  2272. ReadHandler>)(other)),
  2273. stream_(other.stream_),
  2274. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  2275. delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
  2276. start_(other.start_),
  2277. search_position_(other.search_position_),
  2278. bytes_to_read_(other.bytes_to_read_),
  2279. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  2280. {
  2281. }
  2282. #endif // defined(BOOST_ASIO_HAS_MOVE)
  2283. void operator()(boost::system::error_code ec,
  2284. std::size_t bytes_transferred, int start = 0)
  2285. {
  2286. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2287. std::size_t pos;
  2288. switch (start_ = start)
  2289. {
  2290. case 1:
  2291. for (;;)
  2292. {
  2293. {
  2294. // Determine the range of the data to be searched.
  2295. typedef typename DynamicBuffer_v2::const_buffers_type
  2296. buffers_type;
  2297. typedef buffers_iterator<buffers_type> iterator;
  2298. buffers_type data_buffers =
  2299. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2300. 0, buffers_.size());
  2301. iterator begin = iterator::begin(data_buffers);
  2302. iterator start_pos = begin + search_position_;
  2303. iterator end = iterator::end(data_buffers);
  2304. // Look for a match.
  2305. std::pair<iterator, bool> result = detail::partial_search(
  2306. start_pos, end, delim_.begin(), delim_.end());
  2307. if (result.first != end && result.second)
  2308. {
  2309. // Full match. We're done.
  2310. search_position_ = result.first - begin + delim_.length();
  2311. bytes_to_read_ = 0;
  2312. }
  2313. // No match yet. Check if buffer is full.
  2314. else if (buffers_.size() == buffers_.max_size())
  2315. {
  2316. search_position_ = not_found;
  2317. bytes_to_read_ = 0;
  2318. }
  2319. // Need to read some more data.
  2320. else
  2321. {
  2322. if (result.first != end)
  2323. {
  2324. // Partial match. Next search needs to start from beginning of
  2325. // match.
  2326. search_position_ = result.first - begin;
  2327. }
  2328. else
  2329. {
  2330. // Next search can start with the new data.
  2331. search_position_ = end - begin;
  2332. }
  2333. bytes_to_read_ = std::min<std::size_t>(
  2334. std::max<std::size_t>(512,
  2335. buffers_.capacity() - buffers_.size()),
  2336. std::min<std::size_t>(65536,
  2337. buffers_.max_size() - buffers_.size()));
  2338. }
  2339. }
  2340. // Check if we're done.
  2341. if (!start && bytes_to_read_ == 0)
  2342. break;
  2343. // Start a new asynchronous read operation to obtain more data.
  2344. pos = buffers_.size();
  2345. buffers_.grow(bytes_to_read_);
  2346. {
  2347. BOOST_ASIO_HANDLER_LOCATION((
  2348. __FILE__, __LINE__, "async_read_until"));
  2349. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2350. BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));
  2351. }
  2352. return; default:
  2353. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2354. if (ec || bytes_transferred == 0)
  2355. break;
  2356. if (this->cancelled() != cancellation_type::none)
  2357. {
  2358. ec = error::operation_aborted;
  2359. break;
  2360. }
  2361. }
  2362. const boost::system::error_code result_ec =
  2363. (search_position_ == not_found)
  2364. ? error::not_found : ec;
  2365. const std::size_t result_n =
  2366. (ec || search_position_ == not_found)
  2367. ? 0 : search_position_;
  2368. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  2369. }
  2370. }
  2371. //private:
  2372. AsyncReadStream& stream_;
  2373. DynamicBuffer_v2 buffers_;
  2374. std::string delim_;
  2375. int start_;
  2376. std::size_t search_position_;
  2377. std::size_t bytes_to_read_;
  2378. ReadHandler handler_;
  2379. };
  2380. template <typename AsyncReadStream,
  2381. typename DynamicBuffer_v2, typename ReadHandler>
  2382. inline asio_handler_allocate_is_deprecated
  2383. asio_handler_allocate(std::size_t size,
  2384. read_until_delim_string_op_v2<AsyncReadStream,
  2385. DynamicBuffer_v2, ReadHandler>* this_handler)
  2386. {
  2387. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2388. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  2389. return asio_handler_allocate_is_no_longer_used();
  2390. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  2391. return boost_asio_handler_alloc_helpers::allocate(
  2392. size, this_handler->handler_);
  2393. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2394. }
  2395. template <typename AsyncReadStream,
  2396. typename DynamicBuffer_v2, typename ReadHandler>
  2397. inline asio_handler_deallocate_is_deprecated
  2398. asio_handler_deallocate(void* pointer, std::size_t size,
  2399. read_until_delim_string_op_v2<AsyncReadStream,
  2400. DynamicBuffer_v2, ReadHandler>* this_handler)
  2401. {
  2402. boost_asio_handler_alloc_helpers::deallocate(
  2403. pointer, size, this_handler->handler_);
  2404. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2405. return asio_handler_deallocate_is_no_longer_used();
  2406. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2407. }
  2408. template <typename AsyncReadStream,
  2409. typename DynamicBuffer_v2, typename ReadHandler>
  2410. inline bool asio_handler_is_continuation(
  2411. read_until_delim_string_op_v2<AsyncReadStream,
  2412. DynamicBuffer_v2, ReadHandler>* this_handler)
  2413. {
  2414. return this_handler->start_ == 0 ? true
  2415. : boost_asio_handler_cont_helpers::is_continuation(
  2416. this_handler->handler_);
  2417. }
  2418. template <typename Function, typename AsyncReadStream,
  2419. typename DynamicBuffer_v2, typename ReadHandler>
  2420. inline asio_handler_invoke_is_deprecated
  2421. asio_handler_invoke(Function& function,
  2422. read_until_delim_string_op_v2<AsyncReadStream,
  2423. DynamicBuffer_v2, ReadHandler>* this_handler)
  2424. {
  2425. boost_asio_handler_invoke_helpers::invoke(
  2426. function, this_handler->handler_);
  2427. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2428. return asio_handler_invoke_is_no_longer_used();
  2429. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2430. }
  2431. template <typename Function, typename AsyncReadStream,
  2432. typename DynamicBuffer_v2, typename ReadHandler>
  2433. inline asio_handler_invoke_is_deprecated
  2434. asio_handler_invoke(const Function& function,
  2435. read_until_delim_string_op_v2<AsyncReadStream,
  2436. DynamicBuffer_v2, ReadHandler>* this_handler)
  2437. {
  2438. boost_asio_handler_invoke_helpers::invoke(
  2439. function, this_handler->handler_);
  2440. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2441. return asio_handler_invoke_is_no_longer_used();
  2442. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2443. }
  2444. template <typename AsyncReadStream>
  2445. class initiate_async_read_until_delim_string_v2
  2446. {
  2447. public:
  2448. typedef typename AsyncReadStream::executor_type executor_type;
  2449. explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)
  2450. : stream_(stream)
  2451. {
  2452. }
  2453. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  2454. {
  2455. return stream_.get_executor();
  2456. }
  2457. template <typename ReadHandler, typename DynamicBuffer_v2>
  2458. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  2459. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  2460. const std::string& delim) const
  2461. {
  2462. // If you get an error on the following line it means that your handler
  2463. // does not meet the documented type requirements for a ReadHandler.
  2464. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2465. non_const_lvalue<ReadHandler> handler2(handler);
  2466. read_until_delim_string_op_v2<AsyncReadStream,
  2467. typename decay<DynamicBuffer_v2>::type,
  2468. typename decay<ReadHandler>::type>(
  2469. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  2470. delim, handler2.value)(boost::system::error_code(), 0, 1);
  2471. }
  2472. private:
  2473. AsyncReadStream& stream_;
  2474. };
  2475. } // namespace detail
  2476. #if !defined(GENERATING_DOCUMENTATION)
  2477. template <template <typename, typename> class Associator,
  2478. typename AsyncReadStream, typename DynamicBuffer_v2,
  2479. typename ReadHandler, typename DefaultCandidate>
  2480. struct associator<Associator,
  2481. detail::read_until_delim_string_op_v2<AsyncReadStream,
  2482. DynamicBuffer_v2, ReadHandler>,
  2483. DefaultCandidate>
  2484. : Associator<ReadHandler, DefaultCandidate>
  2485. {
  2486. static typename Associator<ReadHandler, DefaultCandidate>::type
  2487. get(const detail::read_until_delim_string_op_v2<AsyncReadStream,
  2488. DynamicBuffer_v2, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  2489. {
  2490. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2491. }
  2492. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  2493. typename Associator<ReadHandler, DefaultCandidate>::type)
  2494. get(const detail::read_until_delim_string_op_v2<AsyncReadStream,
  2495. DynamicBuffer_v2, ReadHandler>& h,
  2496. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  2497. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  2498. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  2499. {
  2500. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2501. }
  2502. };
  2503. #endif // !defined(GENERATING_DOCUMENTATION)
  2504. template <typename AsyncReadStream,
  2505. typename DynamicBuffer_v2,
  2506. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  2507. std::size_t)) ReadToken>
  2508. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  2509. void (boost::system::error_code, std::size_t))
  2510. async_read_until(AsyncReadStream& s,
  2511. DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
  2512. BOOST_ASIO_MOVE_ARG(ReadToken) token,
  2513. typename constraint<
  2514. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2515. >::type)
  2516. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  2517. async_initiate<ReadToken,
  2518. void (boost::system::error_code, std::size_t)>(
  2519. declval<detail::initiate_async_read_until_delim_string_v2<
  2520. AsyncReadStream> >(),
  2521. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  2522. static_cast<std::string>(delim))))
  2523. {
  2524. return async_initiate<ReadToken,
  2525. void (boost::system::error_code, std::size_t)>(
  2526. detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),
  2527. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  2528. static_cast<std::string>(delim));
  2529. }
  2530. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  2531. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  2532. namespace detail
  2533. {
  2534. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2535. typename RegEx, typename ReadHandler>
  2536. class read_until_expr_op_v2
  2537. : public base_from_cancellation_state<ReadHandler>
  2538. {
  2539. public:
  2540. template <typename BufferSequence>
  2541. read_until_expr_op_v2(AsyncReadStream& stream,
  2542. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  2543. const boost::regex& expr, ReadHandler& handler)
  2544. : base_from_cancellation_state<ReadHandler>(
  2545. handler, enable_partial_cancellation()),
  2546. stream_(stream),
  2547. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  2548. expr_(expr),
  2549. start_(0),
  2550. search_position_(0),
  2551. bytes_to_read_(0),
  2552. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  2553. {
  2554. }
  2555. #if defined(BOOST_ASIO_HAS_MOVE)
  2556. read_until_expr_op_v2(const read_until_expr_op_v2& other)
  2557. : base_from_cancellation_state<ReadHandler>(other),
  2558. stream_(other.stream_),
  2559. buffers_(other.buffers_),
  2560. expr_(other.expr_),
  2561. start_(other.start_),
  2562. search_position_(other.search_position_),
  2563. bytes_to_read_(other.bytes_to_read_),
  2564. handler_(other.handler_)
  2565. {
  2566. }
  2567. read_until_expr_op_v2(read_until_expr_op_v2&& other)
  2568. : base_from_cancellation_state<ReadHandler>(
  2569. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  2570. ReadHandler>)(other)),
  2571. stream_(other.stream_),
  2572. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  2573. expr_(other.expr_),
  2574. start_(other.start_),
  2575. search_position_(other.search_position_),
  2576. bytes_to_read_(other.bytes_to_read_),
  2577. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  2578. {
  2579. }
  2580. #endif // defined(BOOST_ASIO_HAS_MOVE)
  2581. void operator()(boost::system::error_code ec,
  2582. std::size_t bytes_transferred, int start = 0)
  2583. {
  2584. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2585. std::size_t pos;
  2586. switch (start_ = start)
  2587. {
  2588. case 1:
  2589. for (;;)
  2590. {
  2591. {
  2592. // Determine the range of the data to be searched.
  2593. typedef typename DynamicBuffer_v2::const_buffers_type
  2594. buffers_type;
  2595. typedef buffers_iterator<buffers_type> iterator;
  2596. buffers_type data_buffers =
  2597. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2598. 0, buffers_.size());
  2599. iterator begin = iterator::begin(data_buffers);
  2600. iterator start_pos = begin + search_position_;
  2601. iterator end = iterator::end(data_buffers);
  2602. // Look for a match.
  2603. boost::match_results<iterator,
  2604. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  2605. match_results;
  2606. bool match = regex_search(start_pos, end, match_results, expr_,
  2607. boost::match_default | boost::match_partial);
  2608. if (match && match_results[0].matched)
  2609. {
  2610. // Full match. We're done.
  2611. search_position_ = match_results[0].second - begin;
  2612. bytes_to_read_ = 0;
  2613. }
  2614. // No match yet. Check if buffer is full.
  2615. else if (buffers_.size() == buffers_.max_size())
  2616. {
  2617. search_position_ = not_found;
  2618. bytes_to_read_ = 0;
  2619. }
  2620. // Need to read some more data.
  2621. else
  2622. {
  2623. if (match)
  2624. {
  2625. // Partial match. Next search needs to start from beginning of
  2626. // match.
  2627. search_position_ = match_results[0].first - begin;
  2628. }
  2629. else
  2630. {
  2631. // Next search can start with the new data.
  2632. search_position_ = end - begin;
  2633. }
  2634. bytes_to_read_ = std::min<std::size_t>(
  2635. std::max<std::size_t>(512,
  2636. buffers_.capacity() - buffers_.size()),
  2637. std::min<std::size_t>(65536,
  2638. buffers_.max_size() - buffers_.size()));
  2639. }
  2640. }
  2641. // Check if we're done.
  2642. if (!start && bytes_to_read_ == 0)
  2643. break;
  2644. // Start a new asynchronous read operation to obtain more data.
  2645. pos = buffers_.size();
  2646. buffers_.grow(bytes_to_read_);
  2647. {
  2648. BOOST_ASIO_HANDLER_LOCATION((
  2649. __FILE__, __LINE__, "async_read_until"));
  2650. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2651. BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));
  2652. }
  2653. return; default:
  2654. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2655. if (ec || bytes_transferred == 0)
  2656. break;
  2657. if (this->cancelled() != cancellation_type::none)
  2658. {
  2659. ec = error::operation_aborted;
  2660. break;
  2661. }
  2662. }
  2663. const boost::system::error_code result_ec =
  2664. (search_position_ == not_found)
  2665. ? error::not_found : ec;
  2666. const std::size_t result_n =
  2667. (ec || search_position_ == not_found)
  2668. ? 0 : search_position_;
  2669. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  2670. }
  2671. }
  2672. //private:
  2673. AsyncReadStream& stream_;
  2674. DynamicBuffer_v2 buffers_;
  2675. RegEx expr_;
  2676. int start_;
  2677. std::size_t search_position_;
  2678. std::size_t bytes_to_read_;
  2679. ReadHandler handler_;
  2680. };
  2681. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2682. typename RegEx, typename ReadHandler>
  2683. inline asio_handler_allocate_is_deprecated
  2684. asio_handler_allocate(std::size_t size,
  2685. read_until_expr_op_v2<AsyncReadStream,
  2686. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2687. {
  2688. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2689. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  2690. return asio_handler_allocate_is_no_longer_used();
  2691. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  2692. return boost_asio_handler_alloc_helpers::allocate(
  2693. size, this_handler->handler_);
  2694. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2695. }
  2696. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2697. typename RegEx, typename ReadHandler>
  2698. inline asio_handler_deallocate_is_deprecated
  2699. asio_handler_deallocate(void* pointer, std::size_t size,
  2700. read_until_expr_op_v2<AsyncReadStream,
  2701. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2702. {
  2703. boost_asio_handler_alloc_helpers::deallocate(
  2704. pointer, size, this_handler->handler_);
  2705. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2706. return asio_handler_deallocate_is_no_longer_used();
  2707. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2708. }
  2709. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2710. typename RegEx, typename ReadHandler>
  2711. inline bool asio_handler_is_continuation(
  2712. read_until_expr_op_v2<AsyncReadStream,
  2713. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2714. {
  2715. return this_handler->start_ == 0 ? true
  2716. : boost_asio_handler_cont_helpers::is_continuation(
  2717. this_handler->handler_);
  2718. }
  2719. template <typename Function, typename AsyncReadStream,
  2720. typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
  2721. inline asio_handler_invoke_is_deprecated
  2722. asio_handler_invoke(Function& function,
  2723. read_until_expr_op_v2<AsyncReadStream,
  2724. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2725. {
  2726. boost_asio_handler_invoke_helpers::invoke(
  2727. function, this_handler->handler_);
  2728. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2729. return asio_handler_invoke_is_no_longer_used();
  2730. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2731. }
  2732. template <typename Function, typename AsyncReadStream,
  2733. typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
  2734. inline asio_handler_invoke_is_deprecated
  2735. asio_handler_invoke(const Function& function,
  2736. read_until_expr_op_v2<AsyncReadStream,
  2737. DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
  2738. {
  2739. boost_asio_handler_invoke_helpers::invoke(
  2740. function, this_handler->handler_);
  2741. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2742. return asio_handler_invoke_is_no_longer_used();
  2743. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2744. }
  2745. template <typename AsyncReadStream>
  2746. class initiate_async_read_until_expr_v2
  2747. {
  2748. public:
  2749. typedef typename AsyncReadStream::executor_type executor_type;
  2750. explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)
  2751. : stream_(stream)
  2752. {
  2753. }
  2754. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  2755. {
  2756. return stream_.get_executor();
  2757. }
  2758. template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>
  2759. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  2760. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  2761. const RegEx& expr) const
  2762. {
  2763. // If you get an error on the following line it means that your handler
  2764. // does not meet the documented type requirements for a ReadHandler.
  2765. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  2766. non_const_lvalue<ReadHandler> handler2(handler);
  2767. read_until_expr_op_v2<AsyncReadStream,
  2768. typename decay<DynamicBuffer_v2>::type,
  2769. RegEx, typename decay<ReadHandler>::type>(
  2770. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  2771. expr, handler2.value)(boost::system::error_code(), 0, 1);
  2772. }
  2773. private:
  2774. AsyncReadStream& stream_;
  2775. };
  2776. } // namespace detail
  2777. #if !defined(GENERATING_DOCUMENTATION)
  2778. template <template <typename, typename> class Associator,
  2779. typename AsyncReadStream, typename DynamicBuffer_v2,
  2780. typename RegEx, typename ReadHandler, typename DefaultCandidate>
  2781. struct associator<Associator,
  2782. detail::read_until_expr_op_v2<AsyncReadStream,
  2783. DynamicBuffer_v2, RegEx, ReadHandler>,
  2784. DefaultCandidate>
  2785. : Associator<ReadHandler, DefaultCandidate>
  2786. {
  2787. static typename Associator<ReadHandler, DefaultCandidate>::type
  2788. get(const detail::read_until_expr_op_v2<AsyncReadStream,
  2789. DynamicBuffer_v2, RegEx, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  2790. {
  2791. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  2792. }
  2793. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  2794. typename Associator<ReadHandler, DefaultCandidate>::type)
  2795. get(const detail::read_until_expr_op_v2<AsyncReadStream,
  2796. DynamicBuffer_v2, RegEx, ReadHandler>& h,
  2797. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  2798. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  2799. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  2800. {
  2801. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  2802. }
  2803. };
  2804. #endif // !defined(GENERATING_DOCUMENTATION)
  2805. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2806. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  2807. std::size_t)) ReadToken>
  2808. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  2809. void (boost::system::error_code, std::size_t))
  2810. async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  2811. const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  2812. typename constraint<
  2813. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  2814. >::type)
  2815. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  2816. async_initiate<ReadToken,
  2817. void (boost::system::error_code, std::size_t)>(
  2818. declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream> >(),
  2819. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr)))
  2820. {
  2821. return async_initiate<ReadToken,
  2822. void (boost::system::error_code, std::size_t)>(
  2823. detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),
  2824. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);
  2825. }
  2826. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  2827. namespace detail
  2828. {
  2829. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2830. typename MatchCondition, typename ReadHandler>
  2831. class read_until_match_op_v2
  2832. : public base_from_cancellation_state<ReadHandler>
  2833. {
  2834. public:
  2835. template <typename BufferSequence>
  2836. read_until_match_op_v2(AsyncReadStream& stream,
  2837. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  2838. MatchCondition match_condition, ReadHandler& handler)
  2839. : base_from_cancellation_state<ReadHandler>(
  2840. handler, enable_partial_cancellation()),
  2841. stream_(stream),
  2842. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  2843. match_condition_(match_condition),
  2844. start_(0),
  2845. search_position_(0),
  2846. bytes_to_read_(0),
  2847. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  2848. {
  2849. }
  2850. #if defined(BOOST_ASIO_HAS_MOVE)
  2851. read_until_match_op_v2(const read_until_match_op_v2& other)
  2852. : base_from_cancellation_state<ReadHandler>(other),
  2853. stream_(other.stream_),
  2854. buffers_(other.buffers_),
  2855. match_condition_(other.match_condition_),
  2856. start_(other.start_),
  2857. search_position_(other.search_position_),
  2858. bytes_to_read_(other.bytes_to_read_),
  2859. handler_(other.handler_)
  2860. {
  2861. }
  2862. read_until_match_op_v2(read_until_match_op_v2&& other)
  2863. : base_from_cancellation_state<ReadHandler>(
  2864. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  2865. ReadHandler>)(other)),
  2866. stream_(other.stream_),
  2867. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  2868. match_condition_(other.match_condition_),
  2869. start_(other.start_),
  2870. search_position_(other.search_position_),
  2871. bytes_to_read_(other.bytes_to_read_),
  2872. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  2873. {
  2874. }
  2875. #endif // defined(BOOST_ASIO_HAS_MOVE)
  2876. void operator()(boost::system::error_code ec,
  2877. std::size_t bytes_transferred, int start = 0)
  2878. {
  2879. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  2880. std::size_t pos;
  2881. switch (start_ = start)
  2882. {
  2883. case 1:
  2884. for (;;)
  2885. {
  2886. {
  2887. // Determine the range of the data to be searched.
  2888. typedef typename DynamicBuffer_v2::const_buffers_type
  2889. buffers_type;
  2890. typedef buffers_iterator<buffers_type> iterator;
  2891. buffers_type data_buffers =
  2892. const_cast<const DynamicBuffer_v2&>(buffers_).data(
  2893. 0, buffers_.size());
  2894. iterator begin = iterator::begin(data_buffers);
  2895. iterator start_pos = begin + search_position_;
  2896. iterator end = iterator::end(data_buffers);
  2897. // Look for a match.
  2898. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  2899. if (result.second)
  2900. {
  2901. // Full match. We're done.
  2902. search_position_ = result.first - begin;
  2903. bytes_to_read_ = 0;
  2904. }
  2905. // No match yet. Check if buffer is full.
  2906. else if (buffers_.size() == buffers_.max_size())
  2907. {
  2908. search_position_ = not_found;
  2909. bytes_to_read_ = 0;
  2910. }
  2911. // Need to read some more data.
  2912. else
  2913. {
  2914. if (result.first != end)
  2915. {
  2916. // Partial match. Next search needs to start from beginning of
  2917. // match.
  2918. search_position_ = result.first - begin;
  2919. }
  2920. else
  2921. {
  2922. // Next search can start with the new data.
  2923. search_position_ = end - begin;
  2924. }
  2925. bytes_to_read_ = std::min<std::size_t>(
  2926. std::max<std::size_t>(512,
  2927. buffers_.capacity() - buffers_.size()),
  2928. std::min<std::size_t>(65536,
  2929. buffers_.max_size() - buffers_.size()));
  2930. }
  2931. }
  2932. // Check if we're done.
  2933. if (!start && bytes_to_read_ == 0)
  2934. break;
  2935. // Start a new asynchronous read operation to obtain more data.
  2936. pos = buffers_.size();
  2937. buffers_.grow(bytes_to_read_);
  2938. {
  2939. BOOST_ASIO_HANDLER_LOCATION((
  2940. __FILE__, __LINE__, "async_read_until"));
  2941. stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
  2942. BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this));
  2943. }
  2944. return; default:
  2945. buffers_.shrink(bytes_to_read_ - bytes_transferred);
  2946. if (ec || bytes_transferred == 0)
  2947. break;
  2948. if (this->cancelled() != cancellation_type::none)
  2949. {
  2950. ec = error::operation_aborted;
  2951. break;
  2952. }
  2953. }
  2954. const boost::system::error_code result_ec =
  2955. (search_position_ == not_found)
  2956. ? error::not_found : ec;
  2957. const std::size_t result_n =
  2958. (ec || search_position_ == not_found)
  2959. ? 0 : search_position_;
  2960. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
  2961. }
  2962. }
  2963. //private:
  2964. AsyncReadStream& stream_;
  2965. DynamicBuffer_v2 buffers_;
  2966. MatchCondition match_condition_;
  2967. int start_;
  2968. std::size_t search_position_;
  2969. std::size_t bytes_to_read_;
  2970. ReadHandler handler_;
  2971. };
  2972. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2973. typename MatchCondition, typename ReadHandler>
  2974. inline asio_handler_allocate_is_deprecated
  2975. asio_handler_allocate(std::size_t size,
  2976. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  2977. MatchCondition, ReadHandler>* this_handler)
  2978. {
  2979. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2980. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  2981. return asio_handler_allocate_is_no_longer_used();
  2982. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  2983. return boost_asio_handler_alloc_helpers::allocate(
  2984. size, this_handler->handler_);
  2985. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2986. }
  2987. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  2988. typename MatchCondition, typename ReadHandler>
  2989. inline asio_handler_deallocate_is_deprecated
  2990. asio_handler_deallocate(void* pointer, std::size_t size,
  2991. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  2992. MatchCondition, ReadHandler>* this_handler)
  2993. {
  2994. boost_asio_handler_alloc_helpers::deallocate(
  2995. pointer, size, this_handler->handler_);
  2996. #if defined(BOOST_ASIO_NO_DEPRECATED)
  2997. return asio_handler_deallocate_is_no_longer_used();
  2998. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  2999. }
  3000. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  3001. typename MatchCondition, typename ReadHandler>
  3002. inline bool asio_handler_is_continuation(
  3003. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  3004. MatchCondition, ReadHandler>* this_handler)
  3005. {
  3006. return this_handler->start_ == 0 ? true
  3007. : boost_asio_handler_cont_helpers::is_continuation(
  3008. this_handler->handler_);
  3009. }
  3010. template <typename Function, typename AsyncReadStream,
  3011. typename DynamicBuffer_v2, typename MatchCondition,
  3012. typename ReadHandler>
  3013. inline asio_handler_invoke_is_deprecated
  3014. asio_handler_invoke(Function& function,
  3015. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  3016. MatchCondition, ReadHandler>* this_handler)
  3017. {
  3018. boost_asio_handler_invoke_helpers::invoke(
  3019. function, this_handler->handler_);
  3020. #if defined(BOOST_ASIO_NO_DEPRECATED)
  3021. return asio_handler_invoke_is_no_longer_used();
  3022. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  3023. }
  3024. template <typename Function, typename AsyncReadStream,
  3025. typename DynamicBuffer_v2, typename MatchCondition,
  3026. typename ReadHandler>
  3027. inline asio_handler_invoke_is_deprecated
  3028. asio_handler_invoke(const Function& function,
  3029. read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
  3030. MatchCondition, ReadHandler>* this_handler)
  3031. {
  3032. boost_asio_handler_invoke_helpers::invoke(
  3033. function, this_handler->handler_);
  3034. #if defined(BOOST_ASIO_NO_DEPRECATED)
  3035. return asio_handler_invoke_is_no_longer_used();
  3036. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  3037. }
  3038. template <typename AsyncReadStream>
  3039. class initiate_async_read_until_match_v2
  3040. {
  3041. public:
  3042. typedef typename AsyncReadStream::executor_type executor_type;
  3043. explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)
  3044. : stream_(stream)
  3045. {
  3046. }
  3047. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  3048. {
  3049. return stream_.get_executor();
  3050. }
  3051. template <typename ReadHandler,
  3052. typename DynamicBuffer_v2, typename MatchCondition>
  3053. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  3054. BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  3055. MatchCondition match_condition) const
  3056. {
  3057. // If you get an error on the following line it means that your handler
  3058. // does not meet the documented type requirements for a ReadHandler.
  3059. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  3060. non_const_lvalue<ReadHandler> handler2(handler);
  3061. read_until_match_op_v2<AsyncReadStream,
  3062. typename decay<DynamicBuffer_v2>::type,
  3063. MatchCondition, typename decay<ReadHandler>::type>(
  3064. stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  3065. match_condition, handler2.value)(boost::system::error_code(), 0, 1);
  3066. }
  3067. private:
  3068. AsyncReadStream& stream_;
  3069. };
  3070. } // namespace detail
  3071. #if !defined(GENERATING_DOCUMENTATION)
  3072. template <template <typename, typename> class Associator,
  3073. typename AsyncReadStream, typename DynamicBuffer_v2,
  3074. typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
  3075. struct associator<Associator,
  3076. detail::read_until_match_op_v2<AsyncReadStream,
  3077. DynamicBuffer_v2, MatchCondition, ReadHandler>,
  3078. DefaultCandidate>
  3079. : Associator<ReadHandler, DefaultCandidate>
  3080. {
  3081. static typename Associator<ReadHandler, DefaultCandidate>::type
  3082. get(const detail::read_until_match_op_v2<AsyncReadStream,
  3083. DynamicBuffer_v2, MatchCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  3084. {
  3085. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  3086. }
  3087. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  3088. typename Associator<ReadHandler, DefaultCandidate>::type)
  3089. get(const detail::read_until_match_op_v2<AsyncReadStream,
  3090. DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
  3091. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  3092. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  3093. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  3094. {
  3095. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  3096. }
  3097. };
  3098. #endif // !defined(GENERATING_DOCUMENTATION)
  3099. template <typename AsyncReadStream,
  3100. typename DynamicBuffer_v2, typename MatchCondition,
  3101. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  3102. std::size_t)) ReadToken>
  3103. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  3104. void (boost::system::error_code, std::size_t))
  3105. async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  3106. MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
  3107. typename constraint<
  3108. is_match_condition<MatchCondition>::value
  3109. >::type,
  3110. typename constraint<
  3111. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  3112. >::type)
  3113. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  3114. async_initiate<ReadToken,
  3115. void (boost::system::error_code, std::size_t)>(
  3116. declval<detail::initiate_async_read_until_match_v2<AsyncReadStream> >(),
  3117. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  3118. match_condition)))
  3119. {
  3120. return async_initiate<ReadToken,
  3121. void (boost::system::error_code, std::size_t)>(
  3122. detail::initiate_async_read_until_match_v2<AsyncReadStream>(s),
  3123. token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  3124. match_condition);
  3125. }
  3126. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  3127. } // namespace asio
  3128. } // namespace boost
  3129. #include <boost/asio/detail/pop_options.hpp>
  3130. #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP