read_until.hpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503
  1. //
  2. // impl/read_until.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_IMPL_READ_UNTIL_HPP
  11. #define BOOST_ASIO_IMPL_READ_UNTIL_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include <string>
  17. #include <vector>
  18. #include <utility>
  19. #include <boost/asio/associated_allocator.hpp>
  20. #include <boost/asio/associated_executor.hpp>
  21. #include <boost/asio/buffer.hpp>
  22. #include <boost/asio/buffers_iterator.hpp>
  23. #include <boost/asio/detail/bind_handler.hpp>
  24. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  25. #include <boost/asio/detail/handler_cont_helpers.hpp>
  26. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  27. #include <boost/asio/detail/handler_type_requirements.hpp>
  28. #include <boost/asio/detail/limits.hpp>
  29. #include <boost/asio/detail/throw_error.hpp>
  30. #include <boost/asio/detail/push_options.hpp>
  31. namespace boost {
  32. namespace asio {
  33. template <typename SyncReadStream, typename DynamicBuffer>
  34. inline std::size_t read_until(SyncReadStream& s,
  35. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim)
  36. {
  37. boost::system::error_code ec;
  38. std::size_t bytes_transferred = read_until(s,
  39. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
  40. boost::asio::detail::throw_error(ec, "read_until");
  41. return bytes_transferred;
  42. }
  43. template <typename SyncReadStream, typename DynamicBuffer>
  44. std::size_t read_until(SyncReadStream& s,
  45. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  46. char delim, boost::system::error_code& ec)
  47. {
  48. typename decay<DynamicBuffer>::type b(
  49. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  50. std::size_t search_position = 0;
  51. for (;;)
  52. {
  53. // Determine the range of the data to be searched.
  54. typedef typename DynamicBuffer::const_buffers_type buffers_type;
  55. typedef buffers_iterator<buffers_type> iterator;
  56. buffers_type data_buffers = b.data();
  57. iterator begin = iterator::begin(data_buffers);
  58. iterator start_pos = begin + search_position;
  59. iterator end = iterator::end(data_buffers);
  60. // Look for a match.
  61. iterator iter = std::find(start_pos, end, delim);
  62. if (iter != end)
  63. {
  64. // Found a match. We're done.
  65. ec = boost::system::error_code();
  66. return iter - begin + 1;
  67. }
  68. else
  69. {
  70. // No match. Next search can start with the new data.
  71. search_position = end - begin;
  72. }
  73. // Check if buffer is full.
  74. if (b.size() == b.max_size())
  75. {
  76. ec = error::not_found;
  77. return 0;
  78. }
  79. // Need more data.
  80. std::size_t bytes_to_read = std::min<std::size_t>(
  81. std::max<std::size_t>(512, b.capacity() - b.size()),
  82. std::min<std::size_t>(65536, b.max_size() - b.size()));
  83. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  84. if (ec)
  85. return 0;
  86. }
  87. }
  88. template <typename SyncReadStream, typename DynamicBuffer>
  89. inline std::size_t read_until(SyncReadStream& s,
  90. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  91. BOOST_ASIO_STRING_VIEW_PARAM delim)
  92. {
  93. boost::system::error_code ec;
  94. std::size_t bytes_transferred = read_until(s,
  95. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
  96. boost::asio::detail::throw_error(ec, "read_until");
  97. return bytes_transferred;
  98. }
  99. namespace detail
  100. {
  101. // Algorithm that finds a subsequence of equal values in a sequence. Returns
  102. // (iterator,true) if a full match was found, in which case the iterator
  103. // points to the beginning of the match. Returns (iterator,false) if a
  104. // partial match was found at the end of the first sequence, in which case
  105. // the iterator points to the beginning of the partial match. Returns
  106. // (last1,false) if no full or partial match was found.
  107. template <typename Iterator1, typename Iterator2>
  108. std::pair<Iterator1, bool> partial_search(
  109. Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
  110. {
  111. for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
  112. {
  113. Iterator1 test_iter1 = iter1;
  114. Iterator2 test_iter2 = first2;
  115. for (;; ++test_iter1, ++test_iter2)
  116. {
  117. if (test_iter2 == last2)
  118. return std::make_pair(iter1, true);
  119. if (test_iter1 == last1)
  120. {
  121. if (test_iter2 != first2)
  122. return std::make_pair(iter1, false);
  123. else
  124. break;
  125. }
  126. if (*test_iter1 != *test_iter2)
  127. break;
  128. }
  129. }
  130. return std::make_pair(last1, false);
  131. }
  132. } // namespace detail
  133. template <typename SyncReadStream, typename DynamicBuffer>
  134. std::size_t read_until(SyncReadStream& s,
  135. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  136. BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
  137. {
  138. typename decay<DynamicBuffer>::type b(
  139. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  140. std::size_t search_position = 0;
  141. for (;;)
  142. {
  143. // Determine the range of the data to be searched.
  144. typedef typename DynamicBuffer::const_buffers_type buffers_type;
  145. typedef buffers_iterator<buffers_type> iterator;
  146. buffers_type data_buffers = b.data();
  147. iterator begin = iterator::begin(data_buffers);
  148. iterator start_pos = begin + search_position;
  149. iterator end = iterator::end(data_buffers);
  150. // Look for a match.
  151. std::pair<iterator, bool> result = detail::partial_search(
  152. start_pos, end, delim.begin(), delim.end());
  153. if (result.first != end)
  154. {
  155. if (result.second)
  156. {
  157. // Full match. We're done.
  158. ec = boost::system::error_code();
  159. return result.first - begin + delim.length();
  160. }
  161. else
  162. {
  163. // Partial match. Next search needs to start from beginning of match.
  164. search_position = result.first - begin;
  165. }
  166. }
  167. else
  168. {
  169. // No match. Next search can start with the new data.
  170. search_position = end - begin;
  171. }
  172. // Check if buffer is full.
  173. if (b.size() == b.max_size())
  174. {
  175. ec = error::not_found;
  176. return 0;
  177. }
  178. // Need more data.
  179. std::size_t bytes_to_read = std::min<std::size_t>(
  180. std::max<std::size_t>(512, b.capacity() - b.size()),
  181. std::min<std::size_t>(65536, b.max_size() - b.size()));
  182. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  183. if (ec)
  184. return 0;
  185. }
  186. }
  187. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  188. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  189. template <typename SyncReadStream, typename DynamicBuffer>
  190. inline std::size_t read_until(SyncReadStream& s,
  191. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  192. const boost::regex& expr)
  193. {
  194. boost::system::error_code ec;
  195. std::size_t bytes_transferred = read_until(s,
  196. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), expr, ec);
  197. boost::asio::detail::throw_error(ec, "read_until");
  198. return bytes_transferred;
  199. }
  200. template <typename SyncReadStream, typename DynamicBuffer>
  201. std::size_t read_until(SyncReadStream& s,
  202. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  203. const boost::regex& expr, boost::system::error_code& ec)
  204. {
  205. typename decay<DynamicBuffer>::type b(
  206. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  207. std::size_t search_position = 0;
  208. for (;;)
  209. {
  210. // Determine the range of the data to be searched.
  211. typedef typename DynamicBuffer::const_buffers_type buffers_type;
  212. typedef buffers_iterator<buffers_type> iterator;
  213. buffers_type data_buffers = b.data();
  214. iterator begin = iterator::begin(data_buffers);
  215. iterator start_pos = begin + search_position;
  216. iterator end = iterator::end(data_buffers);
  217. // Look for a match.
  218. boost::match_results<iterator,
  219. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  220. match_results;
  221. if (regex_search(start_pos, end, match_results, expr,
  222. boost::match_default | boost::match_partial))
  223. {
  224. if (match_results[0].matched)
  225. {
  226. // Full match. We're done.
  227. ec = boost::system::error_code();
  228. return match_results[0].second - begin;
  229. }
  230. else
  231. {
  232. // Partial match. Next search needs to start from beginning of match.
  233. search_position = match_results[0].first - begin;
  234. }
  235. }
  236. else
  237. {
  238. // No match. Next search can start with the new data.
  239. search_position = end - begin;
  240. }
  241. // Check if buffer is full.
  242. if (b.size() == b.max_size())
  243. {
  244. ec = error::not_found;
  245. return 0;
  246. }
  247. // Need more data.
  248. std::size_t bytes_to_read = read_size_helper(b, 65536);
  249. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  250. if (ec)
  251. return 0;
  252. }
  253. }
  254. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  255. template <typename SyncReadStream,
  256. typename DynamicBuffer, typename MatchCondition>
  257. inline std::size_t read_until(SyncReadStream& s,
  258. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  259. MatchCondition match_condition,
  260. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  261. {
  262. boost::system::error_code ec;
  263. std::size_t bytes_transferred = read_until(s,
  264. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  265. match_condition, ec);
  266. boost::asio::detail::throw_error(ec, "read_until");
  267. return bytes_transferred;
  268. }
  269. template <typename SyncReadStream,
  270. typename DynamicBuffer, typename MatchCondition>
  271. std::size_t read_until(SyncReadStream& s,
  272. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  273. MatchCondition match_condition, boost::system::error_code& ec,
  274. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  275. {
  276. typename decay<DynamicBuffer>::type b(
  277. BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
  278. std::size_t search_position = 0;
  279. for (;;)
  280. {
  281. // Determine the range of the data to be searched.
  282. typedef typename DynamicBuffer::const_buffers_type buffers_type;
  283. typedef buffers_iterator<buffers_type> iterator;
  284. buffers_type data_buffers = b.data();
  285. iterator begin = iterator::begin(data_buffers);
  286. iterator start_pos = begin + search_position;
  287. iterator end = iterator::end(data_buffers);
  288. // Look for a match.
  289. std::pair<iterator, bool> result = match_condition(start_pos, end);
  290. if (result.second)
  291. {
  292. // Full match. We're done.
  293. ec = boost::system::error_code();
  294. return result.first - begin;
  295. }
  296. else if (result.first != end)
  297. {
  298. // Partial match. Next search needs to start from beginning of match.
  299. search_position = result.first - begin;
  300. }
  301. else
  302. {
  303. // No match. Next search can start with the new data.
  304. search_position = end - begin;
  305. }
  306. // Check if buffer is full.
  307. if (b.size() == b.max_size())
  308. {
  309. ec = error::not_found;
  310. return 0;
  311. }
  312. // Need more data.
  313. std::size_t bytes_to_read = std::min<std::size_t>(
  314. std::max<std::size_t>(512, b.capacity() - b.size()),
  315. std::min<std::size_t>(65536, b.max_size() - b.size()));
  316. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  317. if (ec)
  318. return 0;
  319. }
  320. }
  321. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  322. template <typename SyncReadStream, typename Allocator>
  323. inline std::size_t read_until(SyncReadStream& s,
  324. boost::asio::basic_streambuf<Allocator>& b, char delim)
  325. {
  326. return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
  327. }
  328. template <typename SyncReadStream, typename Allocator>
  329. inline std::size_t read_until(SyncReadStream& s,
  330. boost::asio::basic_streambuf<Allocator>& b, char delim,
  331. boost::system::error_code& ec)
  332. {
  333. return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
  334. }
  335. template <typename SyncReadStream, typename Allocator>
  336. inline std::size_t read_until(SyncReadStream& s,
  337. boost::asio::basic_streambuf<Allocator>& b,
  338. BOOST_ASIO_STRING_VIEW_PARAM delim)
  339. {
  340. return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
  341. }
  342. template <typename SyncReadStream, typename Allocator>
  343. inline std::size_t read_until(SyncReadStream& s,
  344. boost::asio::basic_streambuf<Allocator>& b,
  345. BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
  346. {
  347. return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
  348. }
  349. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  350. template <typename SyncReadStream, typename Allocator>
  351. inline std::size_t read_until(SyncReadStream& s,
  352. boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
  353. {
  354. return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
  355. }
  356. template <typename SyncReadStream, typename Allocator>
  357. inline std::size_t read_until(SyncReadStream& s,
  358. boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
  359. boost::system::error_code& ec)
  360. {
  361. return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
  362. }
  363. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  364. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  365. inline std::size_t read_until(SyncReadStream& s,
  366. boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
  367. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  368. {
  369. return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
  370. }
  371. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  372. inline std::size_t read_until(SyncReadStream& s,
  373. boost::asio::basic_streambuf<Allocator>& b,
  374. MatchCondition match_condition, boost::system::error_code& ec,
  375. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  376. {
  377. return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
  378. }
  379. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  380. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  381. namespace detail
  382. {
  383. template <typename AsyncReadStream,
  384. typename DynamicBuffer, typename ReadHandler>
  385. class read_until_delim_op
  386. {
  387. public:
  388. template <typename BufferSequence>
  389. read_until_delim_op(AsyncReadStream& stream,
  390. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  391. char delim, ReadHandler& handler)
  392. : stream_(stream),
  393. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  394. delim_(delim),
  395. start_(0),
  396. search_position_(0),
  397. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  398. {
  399. }
  400. #if defined(BOOST_ASIO_HAS_MOVE)
  401. read_until_delim_op(const read_until_delim_op& other)
  402. : stream_(other.stream_),
  403. buffers_(other.buffers_),
  404. delim_(other.delim_),
  405. start_(other.start_),
  406. search_position_(other.search_position_),
  407. handler_(other.handler_)
  408. {
  409. }
  410. read_until_delim_op(read_until_delim_op&& other)
  411. : stream_(other.stream_),
  412. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  413. delim_(other.delim_),
  414. start_(other.start_),
  415. search_position_(other.search_position_),
  416. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  417. {
  418. }
  419. #endif // defined(BOOST_ASIO_HAS_MOVE)
  420. void operator()(const boost::system::error_code& ec,
  421. std::size_t bytes_transferred, int start = 0)
  422. {
  423. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  424. std::size_t bytes_to_read;
  425. switch (start_ = start)
  426. {
  427. case 1:
  428. for (;;)
  429. {
  430. {
  431. // Determine the range of the data to be searched.
  432. typedef typename DynamicBuffer::const_buffers_type
  433. buffers_type;
  434. typedef buffers_iterator<buffers_type> iterator;
  435. buffers_type data_buffers = buffers_.data();
  436. iterator begin = iterator::begin(data_buffers);
  437. iterator start_pos = begin + search_position_;
  438. iterator end = iterator::end(data_buffers);
  439. // Look for a match.
  440. iterator iter = std::find(start_pos, end, delim_);
  441. if (iter != end)
  442. {
  443. // Found a match. We're done.
  444. search_position_ = iter - begin + 1;
  445. bytes_to_read = 0;
  446. }
  447. // No match yet. Check if buffer is full.
  448. else if (buffers_.size() == buffers_.max_size())
  449. {
  450. search_position_ = not_found;
  451. bytes_to_read = 0;
  452. }
  453. // Need to read some more data.
  454. else
  455. {
  456. // Next search can start with the new data.
  457. search_position_ = end - begin;
  458. bytes_to_read = std::min<std::size_t>(
  459. std::max<std::size_t>(512,
  460. buffers_.capacity() - buffers_.size()),
  461. std::min<std::size_t>(65536,
  462. buffers_.max_size() - buffers_.size()));
  463. }
  464. }
  465. // Check if we're done.
  466. if (!start && bytes_to_read == 0)
  467. break;
  468. // Start a new asynchronous read operation to obtain more data.
  469. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  470. BOOST_ASIO_MOVE_CAST(read_until_delim_op)(*this));
  471. return; default:
  472. buffers_.commit(bytes_transferred);
  473. if (ec || bytes_transferred == 0)
  474. break;
  475. }
  476. const boost::system::error_code result_ec =
  477. (search_position_ == not_found)
  478. ? error::not_found : ec;
  479. const std::size_t result_n =
  480. (ec || search_position_ == not_found)
  481. ? 0 : search_position_;
  482. handler_(result_ec, result_n);
  483. }
  484. }
  485. //private:
  486. AsyncReadStream& stream_;
  487. DynamicBuffer buffers_;
  488. char delim_;
  489. int start_;
  490. std::size_t search_position_;
  491. ReadHandler handler_;
  492. };
  493. template <typename AsyncReadStream,
  494. typename DynamicBuffer, typename ReadHandler>
  495. inline void* asio_handler_allocate(std::size_t size,
  496. read_until_delim_op<AsyncReadStream,
  497. DynamicBuffer, ReadHandler>* this_handler)
  498. {
  499. return boost_asio_handler_alloc_helpers::allocate(
  500. size, this_handler->handler_);
  501. }
  502. template <typename AsyncReadStream,
  503. typename DynamicBuffer, typename ReadHandler>
  504. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  505. read_until_delim_op<AsyncReadStream,
  506. DynamicBuffer, ReadHandler>* this_handler)
  507. {
  508. boost_asio_handler_alloc_helpers::deallocate(
  509. pointer, size, this_handler->handler_);
  510. }
  511. template <typename AsyncReadStream,
  512. typename DynamicBuffer, typename ReadHandler>
  513. inline bool asio_handler_is_continuation(
  514. read_until_delim_op<AsyncReadStream,
  515. DynamicBuffer, ReadHandler>* this_handler)
  516. {
  517. return this_handler->start_ == 0 ? true
  518. : boost_asio_handler_cont_helpers::is_continuation(
  519. this_handler->handler_);
  520. }
  521. template <typename Function, typename AsyncReadStream,
  522. typename DynamicBuffer, typename ReadHandler>
  523. inline void asio_handler_invoke(Function& function,
  524. read_until_delim_op<AsyncReadStream,
  525. DynamicBuffer, ReadHandler>* this_handler)
  526. {
  527. boost_asio_handler_invoke_helpers::invoke(
  528. function, this_handler->handler_);
  529. }
  530. template <typename Function, typename AsyncReadStream,
  531. typename DynamicBuffer, typename ReadHandler>
  532. inline void asio_handler_invoke(const Function& function,
  533. read_until_delim_op<AsyncReadStream,
  534. DynamicBuffer, ReadHandler>* this_handler)
  535. {
  536. boost_asio_handler_invoke_helpers::invoke(
  537. function, this_handler->handler_);
  538. }
  539. } // namespace detail
  540. #if !defined(GENERATING_DOCUMENTATION)
  541. template <typename AsyncReadStream, typename DynamicBuffer,
  542. typename ReadHandler, typename Allocator>
  543. struct associated_allocator<
  544. detail::read_until_delim_op<AsyncReadStream,
  545. DynamicBuffer, ReadHandler>,
  546. Allocator>
  547. {
  548. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  549. static type get(
  550. const detail::read_until_delim_op<AsyncReadStream,
  551. DynamicBuffer, ReadHandler>& h,
  552. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  553. {
  554. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  555. }
  556. };
  557. template <typename AsyncReadStream, typename DynamicBuffer,
  558. typename ReadHandler, typename Executor>
  559. struct associated_executor<
  560. detail::read_until_delim_op<AsyncReadStream,
  561. DynamicBuffer, ReadHandler>,
  562. Executor>
  563. {
  564. typedef typename associated_executor<ReadHandler, Executor>::type type;
  565. static type get(
  566. const detail::read_until_delim_op<AsyncReadStream,
  567. DynamicBuffer, ReadHandler>& h,
  568. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  569. {
  570. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  571. }
  572. };
  573. #endif // !defined(GENERATING_DOCUMENTATION)
  574. template <typename AsyncReadStream,
  575. typename DynamicBuffer, typename ReadHandler>
  576. BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  577. void (boost::system::error_code, std::size_t))
  578. async_read_until(AsyncReadStream& s,
  579. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  580. char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  581. {
  582. // If you get an error on the following line it means that your handler does
  583. // not meet the documented type requirements for a ReadHandler.
  584. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  585. async_completion<ReadHandler,
  586. void (boost::system::error_code, std::size_t)> init(handler);
  587. detail::read_until_delim_op<AsyncReadStream,
  588. typename decay<DynamicBuffer>::type,
  589. BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  590. void (boost::system::error_code, std::size_t))>(
  591. s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  592. delim, init.completion_handler)(boost::system::error_code(), 0, 1);
  593. return init.result.get();
  594. }
  595. namespace detail
  596. {
  597. template <typename AsyncReadStream,
  598. typename DynamicBuffer, typename ReadHandler>
  599. class read_until_delim_string_op
  600. {
  601. public:
  602. template <typename BufferSequence>
  603. read_until_delim_string_op(AsyncReadStream& stream,
  604. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  605. const std::string& delim, ReadHandler& handler)
  606. : stream_(stream),
  607. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  608. delim_(delim),
  609. start_(0),
  610. search_position_(0),
  611. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  612. {
  613. }
  614. #if defined(BOOST_ASIO_HAS_MOVE)
  615. read_until_delim_string_op(const read_until_delim_string_op& other)
  616. : stream_(other.stream_),
  617. buffers_(other.buffers_),
  618. delim_(other.delim_),
  619. start_(other.start_),
  620. search_position_(other.search_position_),
  621. handler_(other.handler_)
  622. {
  623. }
  624. read_until_delim_string_op(read_until_delim_string_op&& other)
  625. : stream_(other.stream_),
  626. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  627. delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
  628. start_(other.start_),
  629. search_position_(other.search_position_),
  630. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  631. {
  632. }
  633. #endif // defined(BOOST_ASIO_HAS_MOVE)
  634. void operator()(const boost::system::error_code& ec,
  635. std::size_t bytes_transferred, int start = 0)
  636. {
  637. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  638. std::size_t bytes_to_read;
  639. switch (start_ = start)
  640. {
  641. case 1:
  642. for (;;)
  643. {
  644. {
  645. // Determine the range of the data to be searched.
  646. typedef typename DynamicBuffer::const_buffers_type
  647. buffers_type;
  648. typedef buffers_iterator<buffers_type> iterator;
  649. buffers_type data_buffers = buffers_.data();
  650. iterator begin = iterator::begin(data_buffers);
  651. iterator start_pos = begin + search_position_;
  652. iterator end = iterator::end(data_buffers);
  653. // Look for a match.
  654. std::pair<iterator, bool> result = detail::partial_search(
  655. start_pos, end, delim_.begin(), delim_.end());
  656. if (result.first != end && result.second)
  657. {
  658. // Full match. We're done.
  659. search_position_ = result.first - begin + delim_.length();
  660. bytes_to_read = 0;
  661. }
  662. // No match yet. Check if buffer is full.
  663. else if (buffers_.size() == buffers_.max_size())
  664. {
  665. search_position_ = not_found;
  666. bytes_to_read = 0;
  667. }
  668. // Need to read some more data.
  669. else
  670. {
  671. if (result.first != end)
  672. {
  673. // Partial match. Next search needs to start from beginning of
  674. // match.
  675. search_position_ = result.first - begin;
  676. }
  677. else
  678. {
  679. // Next search can start with the new data.
  680. search_position_ = end - begin;
  681. }
  682. bytes_to_read = std::min<std::size_t>(
  683. std::max<std::size_t>(512,
  684. buffers_.capacity() - buffers_.size()),
  685. std::min<std::size_t>(65536,
  686. buffers_.max_size() - buffers_.size()));
  687. }
  688. }
  689. // Check if we're done.
  690. if (!start && bytes_to_read == 0)
  691. break;
  692. // Start a new asynchronous read operation to obtain more data.
  693. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  694. BOOST_ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
  695. return; default:
  696. buffers_.commit(bytes_transferred);
  697. if (ec || bytes_transferred == 0)
  698. break;
  699. }
  700. const boost::system::error_code result_ec =
  701. (search_position_ == not_found)
  702. ? error::not_found : ec;
  703. const std::size_t result_n =
  704. (ec || search_position_ == not_found)
  705. ? 0 : search_position_;
  706. handler_(result_ec, result_n);
  707. }
  708. }
  709. //private:
  710. AsyncReadStream& stream_;
  711. DynamicBuffer buffers_;
  712. std::string delim_;
  713. int start_;
  714. std::size_t search_position_;
  715. ReadHandler handler_;
  716. };
  717. template <typename AsyncReadStream,
  718. typename DynamicBuffer, typename ReadHandler>
  719. inline void* asio_handler_allocate(std::size_t size,
  720. read_until_delim_string_op<AsyncReadStream,
  721. DynamicBuffer, ReadHandler>* this_handler)
  722. {
  723. return boost_asio_handler_alloc_helpers::allocate(
  724. size, this_handler->handler_);
  725. }
  726. template <typename AsyncReadStream,
  727. typename DynamicBuffer, typename ReadHandler>
  728. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  729. read_until_delim_string_op<AsyncReadStream,
  730. DynamicBuffer, ReadHandler>* this_handler)
  731. {
  732. boost_asio_handler_alloc_helpers::deallocate(
  733. pointer, size, this_handler->handler_);
  734. }
  735. template <typename AsyncReadStream,
  736. typename DynamicBuffer, typename ReadHandler>
  737. inline bool asio_handler_is_continuation(
  738. read_until_delim_string_op<AsyncReadStream,
  739. DynamicBuffer, ReadHandler>* this_handler)
  740. {
  741. return this_handler->start_ == 0 ? true
  742. : boost_asio_handler_cont_helpers::is_continuation(
  743. this_handler->handler_);
  744. }
  745. template <typename Function, typename AsyncReadStream,
  746. typename DynamicBuffer, typename ReadHandler>
  747. inline void asio_handler_invoke(Function& function,
  748. read_until_delim_string_op<AsyncReadStream,
  749. DynamicBuffer, ReadHandler>* this_handler)
  750. {
  751. boost_asio_handler_invoke_helpers::invoke(
  752. function, this_handler->handler_);
  753. }
  754. template <typename Function, typename AsyncReadStream,
  755. typename DynamicBuffer, typename ReadHandler>
  756. inline void asio_handler_invoke(const Function& function,
  757. read_until_delim_string_op<AsyncReadStream,
  758. DynamicBuffer, ReadHandler>* this_handler)
  759. {
  760. boost_asio_handler_invoke_helpers::invoke(
  761. function, this_handler->handler_);
  762. }
  763. } // namespace detail
  764. #if !defined(GENERATING_DOCUMENTATION)
  765. template <typename AsyncReadStream, typename DynamicBuffer,
  766. typename ReadHandler, typename Allocator>
  767. struct associated_allocator<
  768. detail::read_until_delim_string_op<AsyncReadStream,
  769. DynamicBuffer, ReadHandler>,
  770. Allocator>
  771. {
  772. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  773. static type get(
  774. const detail::read_until_delim_string_op<AsyncReadStream,
  775. DynamicBuffer, ReadHandler>& h,
  776. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  777. {
  778. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  779. }
  780. };
  781. template <typename AsyncReadStream, typename DynamicBuffer,
  782. typename ReadHandler, typename Executor>
  783. struct associated_executor<
  784. detail::read_until_delim_string_op<AsyncReadStream,
  785. DynamicBuffer, ReadHandler>,
  786. Executor>
  787. {
  788. typedef typename associated_executor<ReadHandler, Executor>::type type;
  789. static type get(
  790. const detail::read_until_delim_string_op<AsyncReadStream,
  791. DynamicBuffer, ReadHandler>& h,
  792. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  793. {
  794. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  795. }
  796. };
  797. #endif // !defined(GENERATING_DOCUMENTATION)
  798. template <typename AsyncReadStream,
  799. typename DynamicBuffer, typename ReadHandler>
  800. BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  801. void (boost::system::error_code, std::size_t))
  802. async_read_until(AsyncReadStream& s,
  803. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  804. BOOST_ASIO_STRING_VIEW_PARAM delim,
  805. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  806. {
  807. // If you get an error on the following line it means that your handler does
  808. // not meet the documented type requirements for a ReadHandler.
  809. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  810. async_completion<ReadHandler,
  811. void (boost::system::error_code, std::size_t)> init(handler);
  812. detail::read_until_delim_string_op<AsyncReadStream,
  813. typename decay<DynamicBuffer>::type,
  814. BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  815. void (boost::system::error_code, std::size_t))>(
  816. s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  817. static_cast<std::string>(delim),
  818. init.completion_handler)(boost::system::error_code(), 0, 1);
  819. return init.result.get();
  820. }
  821. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  822. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  823. namespace detail
  824. {
  825. template <typename AsyncReadStream, typename DynamicBuffer,
  826. typename RegEx, typename ReadHandler>
  827. class read_until_expr_op
  828. {
  829. public:
  830. template <typename BufferSequence>
  831. read_until_expr_op(AsyncReadStream& stream,
  832. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  833. const boost::regex& expr, ReadHandler& handler)
  834. : stream_(stream),
  835. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  836. expr_(expr),
  837. start_(0),
  838. search_position_(0),
  839. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  840. {
  841. }
  842. #if defined(BOOST_ASIO_HAS_MOVE)
  843. read_until_expr_op(const read_until_expr_op& other)
  844. : stream_(other.stream_),
  845. buffers_(other.buffers_),
  846. expr_(other.expr_),
  847. start_(other.start_),
  848. search_position_(other.search_position_),
  849. handler_(other.handler_)
  850. {
  851. }
  852. read_until_expr_op(read_until_expr_op&& other)
  853. : stream_(other.stream_),
  854. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  855. expr_(other.expr_),
  856. start_(other.start_),
  857. search_position_(other.search_position_),
  858. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  859. {
  860. }
  861. #endif // defined(BOOST_ASIO_HAS_MOVE)
  862. void operator()(const boost::system::error_code& ec,
  863. std::size_t bytes_transferred, int start = 0)
  864. {
  865. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  866. std::size_t bytes_to_read;
  867. switch (start_ = start)
  868. {
  869. case 1:
  870. for (;;)
  871. {
  872. {
  873. // Determine the range of the data to be searched.
  874. typedef typename DynamicBuffer::const_buffers_type
  875. buffers_type;
  876. typedef buffers_iterator<buffers_type> iterator;
  877. buffers_type data_buffers = buffers_.data();
  878. iterator begin = iterator::begin(data_buffers);
  879. iterator start_pos = begin + search_position_;
  880. iterator end = iterator::end(data_buffers);
  881. // Look for a match.
  882. boost::match_results<iterator,
  883. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  884. match_results;
  885. bool match = regex_search(start_pos, end, match_results, expr_,
  886. boost::match_default | boost::match_partial);
  887. if (match && match_results[0].matched)
  888. {
  889. // Full match. We're done.
  890. search_position_ = match_results[0].second - begin;
  891. bytes_to_read = 0;
  892. }
  893. // No match yet. Check if buffer is full.
  894. else if (buffers_.size() == buffers_.max_size())
  895. {
  896. search_position_ = not_found;
  897. bytes_to_read = 0;
  898. }
  899. // Need to read some more data.
  900. else
  901. {
  902. if (match)
  903. {
  904. // Partial match. Next search needs to start from beginning of
  905. // match.
  906. search_position_ = match_results[0].first - begin;
  907. }
  908. else
  909. {
  910. // Next search can start with the new data.
  911. search_position_ = end - begin;
  912. }
  913. bytes_to_read = std::min<std::size_t>(
  914. std::max<std::size_t>(512,
  915. buffers_.capacity() - buffers_.size()),
  916. std::min<std::size_t>(65536,
  917. buffers_.max_size() - buffers_.size()));
  918. }
  919. }
  920. // Check if we're done.
  921. if (!start && bytes_to_read == 0)
  922. break;
  923. // Start a new asynchronous read operation to obtain more data.
  924. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  925. BOOST_ASIO_MOVE_CAST(read_until_expr_op)(*this));
  926. return; default:
  927. buffers_.commit(bytes_transferred);
  928. if (ec || bytes_transferred == 0)
  929. break;
  930. }
  931. const boost::system::error_code result_ec =
  932. (search_position_ == not_found)
  933. ? error::not_found : ec;
  934. const std::size_t result_n =
  935. (ec || search_position_ == not_found)
  936. ? 0 : search_position_;
  937. handler_(result_ec, result_n);
  938. }
  939. }
  940. //private:
  941. AsyncReadStream& stream_;
  942. DynamicBuffer buffers_;
  943. RegEx expr_;
  944. int start_;
  945. std::size_t search_position_;
  946. ReadHandler handler_;
  947. };
  948. template <typename AsyncReadStream, typename DynamicBuffer,
  949. typename RegEx, typename ReadHandler>
  950. inline void* asio_handler_allocate(std::size_t size,
  951. read_until_expr_op<AsyncReadStream,
  952. DynamicBuffer, RegEx, ReadHandler>* this_handler)
  953. {
  954. return boost_asio_handler_alloc_helpers::allocate(
  955. size, this_handler->handler_);
  956. }
  957. template <typename AsyncReadStream, typename DynamicBuffer,
  958. typename RegEx, typename ReadHandler>
  959. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  960. read_until_expr_op<AsyncReadStream,
  961. DynamicBuffer, RegEx, ReadHandler>* this_handler)
  962. {
  963. boost_asio_handler_alloc_helpers::deallocate(
  964. pointer, size, this_handler->handler_);
  965. }
  966. template <typename AsyncReadStream, typename DynamicBuffer,
  967. typename RegEx, typename ReadHandler>
  968. inline bool asio_handler_is_continuation(
  969. read_until_expr_op<AsyncReadStream,
  970. DynamicBuffer, RegEx, ReadHandler>* this_handler)
  971. {
  972. return this_handler->start_ == 0 ? true
  973. : boost_asio_handler_cont_helpers::is_continuation(
  974. this_handler->handler_);
  975. }
  976. template <typename Function, typename AsyncReadStream,
  977. typename DynamicBuffer, typename RegEx, typename ReadHandler>
  978. inline void asio_handler_invoke(Function& function,
  979. read_until_expr_op<AsyncReadStream,
  980. DynamicBuffer, RegEx, ReadHandler>* this_handler)
  981. {
  982. boost_asio_handler_invoke_helpers::invoke(
  983. function, this_handler->handler_);
  984. }
  985. template <typename Function, typename AsyncReadStream,
  986. typename DynamicBuffer, typename RegEx, typename ReadHandler>
  987. inline void asio_handler_invoke(const Function& function,
  988. read_until_expr_op<AsyncReadStream,
  989. DynamicBuffer, RegEx, ReadHandler>* this_handler)
  990. {
  991. boost_asio_handler_invoke_helpers::invoke(
  992. function, this_handler->handler_);
  993. }
  994. } // namespace detail
  995. #if !defined(GENERATING_DOCUMENTATION)
  996. template <typename AsyncReadStream, typename DynamicBuffer,
  997. typename RegEx, typename ReadHandler, typename Allocator>
  998. struct associated_allocator<
  999. detail::read_until_expr_op<AsyncReadStream,
  1000. DynamicBuffer, RegEx, ReadHandler>,
  1001. Allocator>
  1002. {
  1003. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  1004. static type get(
  1005. const detail::read_until_expr_op<AsyncReadStream,
  1006. DynamicBuffer, RegEx, ReadHandler>& h,
  1007. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  1008. {
  1009. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  1010. }
  1011. };
  1012. template <typename AsyncReadStream, typename DynamicBuffer,
  1013. typename RegEx, typename ReadHandler, typename Executor>
  1014. struct associated_executor<
  1015. detail::read_until_expr_op<AsyncReadStream,
  1016. DynamicBuffer, RegEx, ReadHandler>,
  1017. Executor>
  1018. {
  1019. typedef typename associated_executor<ReadHandler, Executor>::type type;
  1020. static type get(
  1021. const detail::read_until_expr_op<AsyncReadStream,
  1022. DynamicBuffer, RegEx, ReadHandler>& h,
  1023. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  1024. {
  1025. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  1026. }
  1027. };
  1028. #endif // !defined(GENERATING_DOCUMENTATION)
  1029. template <typename AsyncReadStream,
  1030. typename DynamicBuffer, typename ReadHandler>
  1031. BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1032. void (boost::system::error_code, std::size_t))
  1033. async_read_until(AsyncReadStream& s,
  1034. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  1035. const boost::regex& expr,
  1036. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  1037. {
  1038. // If you get an error on the following line it means that your handler does
  1039. // not meet the documented type requirements for a ReadHandler.
  1040. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1041. async_completion<ReadHandler,
  1042. void (boost::system::error_code, std::size_t)> init(handler);
  1043. detail::read_until_expr_op<AsyncReadStream,
  1044. typename decay<DynamicBuffer>::type,
  1045. boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  1046. void (boost::system::error_code, std::size_t))>(
  1047. s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  1048. expr, init.completion_handler)(boost::system::error_code(), 0, 1);
  1049. return init.result.get();
  1050. }
  1051. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1052. namespace detail
  1053. {
  1054. template <typename AsyncReadStream, typename DynamicBuffer,
  1055. typename MatchCondition, typename ReadHandler>
  1056. class read_until_match_op
  1057. {
  1058. public:
  1059. template <typename BufferSequence>
  1060. read_until_match_op(AsyncReadStream& stream,
  1061. BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
  1062. MatchCondition match_condition, ReadHandler& handler)
  1063. : stream_(stream),
  1064. buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
  1065. match_condition_(match_condition),
  1066. start_(0),
  1067. search_position_(0),
  1068. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  1069. {
  1070. }
  1071. #if defined(BOOST_ASIO_HAS_MOVE)
  1072. read_until_match_op(const read_until_match_op& other)
  1073. : stream_(other.stream_),
  1074. buffers_(other.buffers_),
  1075. match_condition_(other.match_condition_),
  1076. start_(other.start_),
  1077. search_position_(other.search_position_),
  1078. handler_(other.handler_)
  1079. {
  1080. }
  1081. read_until_match_op(read_until_match_op&& other)
  1082. : stream_(other.stream_),
  1083. buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
  1084. match_condition_(other.match_condition_),
  1085. start_(other.start_),
  1086. search_position_(other.search_position_),
  1087. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  1088. {
  1089. }
  1090. #endif // defined(BOOST_ASIO_HAS_MOVE)
  1091. void operator()(const boost::system::error_code& ec,
  1092. std::size_t bytes_transferred, int start = 0)
  1093. {
  1094. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  1095. std::size_t bytes_to_read;
  1096. switch (start_ = start)
  1097. {
  1098. case 1:
  1099. for (;;)
  1100. {
  1101. {
  1102. // Determine the range of the data to be searched.
  1103. typedef typename DynamicBuffer::const_buffers_type
  1104. buffers_type;
  1105. typedef buffers_iterator<buffers_type> iterator;
  1106. buffers_type data_buffers = buffers_.data();
  1107. iterator begin = iterator::begin(data_buffers);
  1108. iterator start_pos = begin + search_position_;
  1109. iterator end = iterator::end(data_buffers);
  1110. // Look for a match.
  1111. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  1112. if (result.second)
  1113. {
  1114. // Full match. We're done.
  1115. search_position_ = result.first - begin;
  1116. bytes_to_read = 0;
  1117. }
  1118. // No match yet. Check if buffer is full.
  1119. else if (buffers_.size() == buffers_.max_size())
  1120. {
  1121. search_position_ = not_found;
  1122. bytes_to_read = 0;
  1123. }
  1124. // Need to read some more data.
  1125. else
  1126. {
  1127. if (result.first != end)
  1128. {
  1129. // Partial match. Next search needs to start from beginning of
  1130. // match.
  1131. search_position_ = result.first - begin;
  1132. }
  1133. else
  1134. {
  1135. // Next search can start with the new data.
  1136. search_position_ = end - begin;
  1137. }
  1138. bytes_to_read = std::min<std::size_t>(
  1139. std::max<std::size_t>(512,
  1140. buffers_.capacity() - buffers_.size()),
  1141. std::min<std::size_t>(65536,
  1142. buffers_.max_size() - buffers_.size()));
  1143. }
  1144. }
  1145. // Check if we're done.
  1146. if (!start && bytes_to_read == 0)
  1147. break;
  1148. // Start a new asynchronous read operation to obtain more data.
  1149. stream_.async_read_some(buffers_.prepare(bytes_to_read),
  1150. BOOST_ASIO_MOVE_CAST(read_until_match_op)(*this));
  1151. return; default:
  1152. buffers_.commit(bytes_transferred);
  1153. if (ec || bytes_transferred == 0)
  1154. break;
  1155. }
  1156. const boost::system::error_code result_ec =
  1157. (search_position_ == not_found)
  1158. ? error::not_found : ec;
  1159. const std::size_t result_n =
  1160. (ec || search_position_ == not_found)
  1161. ? 0 : search_position_;
  1162. handler_(result_ec, result_n);
  1163. }
  1164. }
  1165. //private:
  1166. AsyncReadStream& stream_;
  1167. DynamicBuffer buffers_;
  1168. MatchCondition match_condition_;
  1169. int start_;
  1170. std::size_t search_position_;
  1171. ReadHandler handler_;
  1172. };
  1173. template <typename AsyncReadStream, typename DynamicBuffer,
  1174. typename MatchCondition, typename ReadHandler>
  1175. inline void* asio_handler_allocate(std::size_t size,
  1176. read_until_match_op<AsyncReadStream, DynamicBuffer,
  1177. MatchCondition, ReadHandler>* this_handler)
  1178. {
  1179. return boost_asio_handler_alloc_helpers::allocate(
  1180. size, this_handler->handler_);
  1181. }
  1182. template <typename AsyncReadStream, typename DynamicBuffer,
  1183. typename MatchCondition, typename ReadHandler>
  1184. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  1185. read_until_match_op<AsyncReadStream, DynamicBuffer,
  1186. MatchCondition, ReadHandler>* this_handler)
  1187. {
  1188. boost_asio_handler_alloc_helpers::deallocate(
  1189. pointer, size, this_handler->handler_);
  1190. }
  1191. template <typename AsyncReadStream, typename DynamicBuffer,
  1192. typename MatchCondition, typename ReadHandler>
  1193. inline bool asio_handler_is_continuation(
  1194. read_until_match_op<AsyncReadStream, DynamicBuffer,
  1195. MatchCondition, ReadHandler>* this_handler)
  1196. {
  1197. return this_handler->start_ == 0 ? true
  1198. : boost_asio_handler_cont_helpers::is_continuation(
  1199. this_handler->handler_);
  1200. }
  1201. template <typename Function, typename AsyncReadStream,
  1202. typename DynamicBuffer, typename MatchCondition,
  1203. typename ReadHandler>
  1204. inline void asio_handler_invoke(Function& function,
  1205. read_until_match_op<AsyncReadStream, DynamicBuffer,
  1206. MatchCondition, ReadHandler>* this_handler)
  1207. {
  1208. boost_asio_handler_invoke_helpers::invoke(
  1209. function, this_handler->handler_);
  1210. }
  1211. template <typename Function, typename AsyncReadStream,
  1212. typename DynamicBuffer, typename MatchCondition,
  1213. typename ReadHandler>
  1214. inline void asio_handler_invoke(const Function& function,
  1215. read_until_match_op<AsyncReadStream, DynamicBuffer,
  1216. MatchCondition, ReadHandler>* this_handler)
  1217. {
  1218. boost_asio_handler_invoke_helpers::invoke(
  1219. function, this_handler->handler_);
  1220. }
  1221. } // namespace detail
  1222. #if !defined(GENERATING_DOCUMENTATION)
  1223. template <typename AsyncReadStream, typename DynamicBuffer,
  1224. typename MatchCondition, typename ReadHandler, typename Allocator>
  1225. struct associated_allocator<
  1226. detail::read_until_match_op<AsyncReadStream,
  1227. DynamicBuffer, MatchCondition, ReadHandler>,
  1228. Allocator>
  1229. {
  1230. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  1231. static type get(
  1232. const detail::read_until_match_op<AsyncReadStream,
  1233. DynamicBuffer, MatchCondition, ReadHandler>& h,
  1234. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  1235. {
  1236. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  1237. }
  1238. };
  1239. template <typename AsyncReadStream, typename DynamicBuffer,
  1240. typename MatchCondition, typename ReadHandler, typename Executor>
  1241. struct associated_executor<
  1242. detail::read_until_match_op<AsyncReadStream,
  1243. DynamicBuffer, MatchCondition, ReadHandler>,
  1244. Executor>
  1245. {
  1246. typedef typename associated_executor<ReadHandler, Executor>::type type;
  1247. static type get(
  1248. const detail::read_until_match_op<AsyncReadStream,
  1249. DynamicBuffer, MatchCondition, ReadHandler>& h,
  1250. const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
  1251. {
  1252. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  1253. }
  1254. };
  1255. #endif // !defined(GENERATING_DOCUMENTATION)
  1256. template <typename AsyncReadStream, typename DynamicBuffer,
  1257. typename MatchCondition, typename ReadHandler>
  1258. BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1259. void (boost::system::error_code, std::size_t))
  1260. async_read_until(AsyncReadStream& s,
  1261. BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
  1262. MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  1263. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  1264. {
  1265. // If you get an error on the following line it means that your handler does
  1266. // not meet the documented type requirements for a ReadHandler.
  1267. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1268. async_completion<ReadHandler,
  1269. void (boost::system::error_code, std::size_t)> init(handler);
  1270. detail::read_until_match_op<AsyncReadStream,
  1271. typename decay<DynamicBuffer>::type,
  1272. MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
  1273. void (boost::system::error_code, std::size_t))>(
  1274. s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
  1275. match_condition, init.completion_handler)(
  1276. boost::system::error_code(), 0, 1);
  1277. return init.result.get();
  1278. }
  1279. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  1280. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  1281. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1282. void (boost::system::error_code, std::size_t))
  1283. async_read_until(AsyncReadStream& s,
  1284. boost::asio::basic_streambuf<Allocator>& b,
  1285. char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  1286. {
  1287. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1288. delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  1289. }
  1290. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  1291. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1292. void (boost::system::error_code, std::size_t))
  1293. async_read_until(AsyncReadStream& s,
  1294. boost::asio::basic_streambuf<Allocator>& b,
  1295. BOOST_ASIO_STRING_VIEW_PARAM delim,
  1296. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  1297. {
  1298. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1299. delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  1300. }
  1301. #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1302. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  1303. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1304. void (boost::system::error_code, std::size_t))
  1305. async_read_until(AsyncReadStream& s,
  1306. boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
  1307. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  1308. {
  1309. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1310. expr, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  1311. }
  1312. #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
  1313. template <typename AsyncReadStream, typename Allocator,
  1314. typename MatchCondition, typename ReadHandler>
  1315. inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1316. void (boost::system::error_code, std::size_t))
  1317. async_read_until(AsyncReadStream& s,
  1318. boost::asio::basic_streambuf<Allocator>& b,
  1319. MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  1320. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  1321. {
  1322. return async_read_until(s, basic_streambuf_ref<Allocator>(b),
  1323. match_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
  1324. }
  1325. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  1326. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  1327. } // namespace asio
  1328. } // namespace boost
  1329. #include <boost/asio/detail/pop_options.hpp>
  1330. #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP