read_until.hpp 85 KB

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