read_until.hpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. //
  2. // impl/read_until.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_IMPL_READ_UNTIL_HPP
  11. #define ASIO_IMPL_READ_UNTIL_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include <string>
  17. #include <vector>
  18. #include <utility>
  19. #include "asio/buffer.hpp"
  20. #include "asio/buffers_iterator.hpp"
  21. #include "asio/detail/bind_handler.hpp"
  22. #include "asio/detail/handler_alloc_helpers.hpp"
  23. #include "asio/detail/handler_cont_helpers.hpp"
  24. #include "asio/detail/handler_invoke_helpers.hpp"
  25. #include "asio/detail/handler_type_requirements.hpp"
  26. #include "asio/detail/limits.hpp"
  27. #include "asio/detail/throw_error.hpp"
  28. #include "asio/detail/push_options.hpp"
  29. namespace asio {
  30. template <typename SyncReadStream, typename Allocator>
  31. inline std::size_t read_until(SyncReadStream& s,
  32. asio::basic_streambuf<Allocator>& b, char delim)
  33. {
  34. asio::error_code ec;
  35. std::size_t bytes_transferred = read_until(s, b, delim, ec);
  36. asio::detail::throw_error(ec, "read_until");
  37. return bytes_transferred;
  38. }
  39. template <typename SyncReadStream, typename Allocator>
  40. std::size_t read_until(SyncReadStream& s,
  41. asio::basic_streambuf<Allocator>& b, char delim,
  42. asio::error_code& ec)
  43. {
  44. std::size_t search_position = 0;
  45. for (;;)
  46. {
  47. // Determine the range of the data to be searched.
  48. typedef typename asio::basic_streambuf<
  49. Allocator>::const_buffers_type const_buffers_type;
  50. typedef asio::buffers_iterator<const_buffers_type> iterator;
  51. const_buffers_type buffers = b.data();
  52. iterator begin = iterator::begin(buffers);
  53. iterator start_pos = begin + search_position;
  54. iterator end = iterator::end(buffers);
  55. // Look for a match.
  56. iterator iter = std::find(start_pos, end, delim);
  57. if (iter != end)
  58. {
  59. // Found a match. We're done.
  60. ec = asio::error_code();
  61. return iter - begin + 1;
  62. }
  63. else
  64. {
  65. // No match. Next search can start with the new data.
  66. search_position = end - begin;
  67. }
  68. // Check if buffer is full.
  69. if (b.size() == b.max_size())
  70. {
  71. ec = error::not_found;
  72. return 0;
  73. }
  74. // Need more data.
  75. std::size_t bytes_to_read = read_size_helper(b, 65536);
  76. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  77. if (ec)
  78. return 0;
  79. }
  80. }
  81. template <typename SyncReadStream, typename Allocator>
  82. inline std::size_t read_until(SyncReadStream& s,
  83. asio::basic_streambuf<Allocator>& b, const std::string& delim)
  84. {
  85. asio::error_code ec;
  86. std::size_t bytes_transferred = read_until(s, b, delim, ec);
  87. asio::detail::throw_error(ec, "read_until");
  88. return bytes_transferred;
  89. }
  90. namespace detail
  91. {
  92. // Algorithm that finds a subsequence of equal values in a sequence. Returns
  93. // (iterator,true) if a full match was found, in which case the iterator
  94. // points to the beginning of the match. Returns (iterator,false) if a
  95. // partial match was found at the end of the first sequence, in which case
  96. // the iterator points to the beginning of the partial match. Returns
  97. // (last1,false) if no full or partial match was found.
  98. template <typename Iterator1, typename Iterator2>
  99. std::pair<Iterator1, bool> partial_search(
  100. Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
  101. {
  102. for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
  103. {
  104. Iterator1 test_iter1 = iter1;
  105. Iterator2 test_iter2 = first2;
  106. for (;; ++test_iter1, ++test_iter2)
  107. {
  108. if (test_iter2 == last2)
  109. return std::make_pair(iter1, true);
  110. if (test_iter1 == last1)
  111. {
  112. if (test_iter2 != first2)
  113. return std::make_pair(iter1, false);
  114. else
  115. break;
  116. }
  117. if (*test_iter1 != *test_iter2)
  118. break;
  119. }
  120. }
  121. return std::make_pair(last1, false);
  122. }
  123. } // namespace detail
  124. template <typename SyncReadStream, typename Allocator>
  125. std::size_t read_until(SyncReadStream& s,
  126. asio::basic_streambuf<Allocator>& b, const std::string& delim,
  127. asio::error_code& ec)
  128. {
  129. std::size_t search_position = 0;
  130. for (;;)
  131. {
  132. // Determine the range of the data to be searched.
  133. typedef typename asio::basic_streambuf<
  134. Allocator>::const_buffers_type const_buffers_type;
  135. typedef asio::buffers_iterator<const_buffers_type> iterator;
  136. const_buffers_type buffers = b.data();
  137. iterator begin = iterator::begin(buffers);
  138. iterator start_pos = begin + search_position;
  139. iterator end = iterator::end(buffers);
  140. // Look for a match.
  141. std::pair<iterator, bool> result = detail::partial_search(
  142. start_pos, end, delim.begin(), delim.end());
  143. if (result.first != end)
  144. {
  145. if (result.second)
  146. {
  147. // Full match. We're done.
  148. ec = asio::error_code();
  149. return result.first - begin + delim.length();
  150. }
  151. else
  152. {
  153. // Partial match. Next search needs to start from beginning of match.
  154. search_position = result.first - begin;
  155. }
  156. }
  157. else
  158. {
  159. // No match. Next search can start with the new data.
  160. search_position = end - begin;
  161. }
  162. // Check if buffer is full.
  163. if (b.size() == b.max_size())
  164. {
  165. ec = error::not_found;
  166. return 0;
  167. }
  168. // Need more data.
  169. std::size_t bytes_to_read = read_size_helper(b, 65536);
  170. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  171. if (ec)
  172. return 0;
  173. }
  174. }
  175. #if defined(ASIO_HAS_BOOST_REGEX)
  176. template <typename SyncReadStream, typename Allocator>
  177. inline std::size_t read_until(SyncReadStream& s,
  178. asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
  179. {
  180. asio::error_code ec;
  181. std::size_t bytes_transferred = read_until(s, b, expr, ec);
  182. asio::detail::throw_error(ec, "read_until");
  183. return bytes_transferred;
  184. }
  185. template <typename SyncReadStream, typename Allocator>
  186. std::size_t read_until(SyncReadStream& s,
  187. asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
  188. asio::error_code& ec)
  189. {
  190. std::size_t search_position = 0;
  191. for (;;)
  192. {
  193. // Determine the range of the data to be searched.
  194. typedef typename asio::basic_streambuf<
  195. Allocator>::const_buffers_type const_buffers_type;
  196. typedef asio::buffers_iterator<const_buffers_type> iterator;
  197. const_buffers_type buffers = b.data();
  198. iterator begin = iterator::begin(buffers);
  199. iterator start_pos = begin + search_position;
  200. iterator end = iterator::end(buffers);
  201. // Look for a match.
  202. boost::match_results<iterator,
  203. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  204. match_results;
  205. if (regex_search(start_pos, end, match_results, expr,
  206. boost::match_default | boost::match_partial))
  207. {
  208. if (match_results[0].matched)
  209. {
  210. // Full match. We're done.
  211. ec = asio::error_code();
  212. return match_results[0].second - begin;
  213. }
  214. else
  215. {
  216. // Partial match. Next search needs to start from beginning of match.
  217. search_position = match_results[0].first - begin;
  218. }
  219. }
  220. else
  221. {
  222. // No match. Next search can start with the new data.
  223. search_position = end - begin;
  224. }
  225. // Check if buffer is full.
  226. if (b.size() == b.max_size())
  227. {
  228. ec = error::not_found;
  229. return 0;
  230. }
  231. // Need more data.
  232. std::size_t bytes_to_read = read_size_helper(b, 65536);
  233. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  234. if (ec)
  235. return 0;
  236. }
  237. }
  238. #endif // defined(ASIO_HAS_BOOST_REGEX)
  239. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  240. std::size_t read_until(SyncReadStream& s,
  241. asio::basic_streambuf<Allocator>& b,
  242. MatchCondition match_condition, asio::error_code& ec,
  243. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  244. {
  245. std::size_t search_position = 0;
  246. for (;;)
  247. {
  248. // Determine the range of the data to be searched.
  249. typedef typename asio::basic_streambuf<
  250. Allocator>::const_buffers_type const_buffers_type;
  251. typedef asio::buffers_iterator<const_buffers_type> iterator;
  252. const_buffers_type buffers = b.data();
  253. iterator begin = iterator::begin(buffers);
  254. iterator start_pos = begin + search_position;
  255. iterator end = iterator::end(buffers);
  256. // Look for a match.
  257. std::pair<iterator, bool> result = match_condition(start_pos, end);
  258. if (result.second)
  259. {
  260. // Full match. We're done.
  261. ec = asio::error_code();
  262. return result.first - begin;
  263. }
  264. else if (result.first != end)
  265. {
  266. // Partial match. Next search needs to start from beginning of match.
  267. search_position = result.first - begin;
  268. }
  269. else
  270. {
  271. // No match. Next search can start with the new data.
  272. search_position = end - begin;
  273. }
  274. // Check if buffer is full.
  275. if (b.size() == b.max_size())
  276. {
  277. ec = error::not_found;
  278. return 0;
  279. }
  280. // Need more data.
  281. std::size_t bytes_to_read = read_size_helper(b, 65536);
  282. b.commit(s.read_some(b.prepare(bytes_to_read), ec));
  283. if (ec)
  284. return 0;
  285. }
  286. }
  287. template <typename SyncReadStream, typename Allocator, typename MatchCondition>
  288. inline std::size_t read_until(SyncReadStream& s,
  289. asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
  290. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  291. {
  292. asio::error_code ec;
  293. std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
  294. asio::detail::throw_error(ec, "read_until");
  295. return bytes_transferred;
  296. }
  297. namespace detail
  298. {
  299. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  300. class read_until_delim_op
  301. {
  302. public:
  303. read_until_delim_op(AsyncReadStream& stream,
  304. asio::basic_streambuf<Allocator>& streambuf,
  305. char delim, ReadHandler& handler)
  306. : stream_(stream),
  307. streambuf_(streambuf),
  308. delim_(delim),
  309. start_(0),
  310. search_position_(0),
  311. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  312. {
  313. }
  314. #if defined(ASIO_HAS_MOVE)
  315. read_until_delim_op(const read_until_delim_op& other)
  316. : stream_(other.stream_),
  317. streambuf_(other.streambuf_),
  318. delim_(other.delim_),
  319. start_(other.start_),
  320. search_position_(other.search_position_),
  321. handler_(other.handler_)
  322. {
  323. }
  324. read_until_delim_op(read_until_delim_op&& other)
  325. : stream_(other.stream_),
  326. streambuf_(other.streambuf_),
  327. delim_(other.delim_),
  328. start_(other.start_),
  329. search_position_(other.search_position_),
  330. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  331. {
  332. }
  333. #endif // defined(ASIO_HAS_MOVE)
  334. void operator()(const asio::error_code& ec,
  335. std::size_t bytes_transferred, int start = 0)
  336. {
  337. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  338. std::size_t bytes_to_read;
  339. switch (start_ = start)
  340. {
  341. case 1:
  342. for (;;)
  343. {
  344. {
  345. // Determine the range of the data to be searched.
  346. typedef typename asio::basic_streambuf<
  347. Allocator>::const_buffers_type const_buffers_type;
  348. typedef asio::buffers_iterator<const_buffers_type> iterator;
  349. const_buffers_type buffers = streambuf_.data();
  350. iterator begin = iterator::begin(buffers);
  351. iterator start_pos = begin + search_position_;
  352. iterator end = iterator::end(buffers);
  353. // Look for a match.
  354. iterator iter = std::find(start_pos, end, delim_);
  355. if (iter != end)
  356. {
  357. // Found a match. We're done.
  358. search_position_ = iter - begin + 1;
  359. bytes_to_read = 0;
  360. }
  361. // No match yet. Check if buffer is full.
  362. else if (streambuf_.size() == streambuf_.max_size())
  363. {
  364. search_position_ = not_found;
  365. bytes_to_read = 0;
  366. }
  367. // Need to read some more data.
  368. else
  369. {
  370. // Next search can start with the new data.
  371. search_position_ = end - begin;
  372. bytes_to_read = read_size_helper(streambuf_, 65536);
  373. }
  374. }
  375. // Check if we're done.
  376. if (!start && bytes_to_read == 0)
  377. break;
  378. // Start a new asynchronous read operation to obtain more data.
  379. stream_.async_read_some(streambuf_.prepare(bytes_to_read),
  380. ASIO_MOVE_CAST(read_until_delim_op)(*this));
  381. return; default:
  382. streambuf_.commit(bytes_transferred);
  383. if (ec || bytes_transferred == 0)
  384. break;
  385. }
  386. const asio::error_code result_ec =
  387. (search_position_ == not_found)
  388. ? error::not_found : ec;
  389. const std::size_t result_n =
  390. (ec || search_position_ == not_found)
  391. ? 0 : search_position_;
  392. handler_(result_ec, result_n);
  393. }
  394. }
  395. //private:
  396. AsyncReadStream& stream_;
  397. asio::basic_streambuf<Allocator>& streambuf_;
  398. char delim_;
  399. int start_;
  400. std::size_t search_position_;
  401. ReadHandler handler_;
  402. };
  403. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  404. inline void* asio_handler_allocate(std::size_t size,
  405. read_until_delim_op<AsyncReadStream,
  406. Allocator, ReadHandler>* this_handler)
  407. {
  408. return asio_handler_alloc_helpers::allocate(
  409. size, this_handler->handler_);
  410. }
  411. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  412. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  413. read_until_delim_op<AsyncReadStream,
  414. Allocator, ReadHandler>* this_handler)
  415. {
  416. asio_handler_alloc_helpers::deallocate(
  417. pointer, size, this_handler->handler_);
  418. }
  419. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  420. inline bool asio_handler_is_continuation(
  421. read_until_delim_op<AsyncReadStream,
  422. Allocator, ReadHandler>* this_handler)
  423. {
  424. return this_handler->start_ == 0 ? true
  425. : asio_handler_cont_helpers::is_continuation(
  426. this_handler->handler_);
  427. }
  428. template <typename Function, typename AsyncReadStream, typename Allocator,
  429. typename ReadHandler>
  430. inline void asio_handler_invoke(Function& function,
  431. read_until_delim_op<AsyncReadStream,
  432. Allocator, ReadHandler>* this_handler)
  433. {
  434. asio_handler_invoke_helpers::invoke(
  435. function, this_handler->handler_);
  436. }
  437. template <typename Function, typename AsyncReadStream, typename Allocator,
  438. typename ReadHandler>
  439. inline void asio_handler_invoke(const Function& function,
  440. read_until_delim_op<AsyncReadStream,
  441. Allocator, ReadHandler>* this_handler)
  442. {
  443. asio_handler_invoke_helpers::invoke(
  444. function, this_handler->handler_);
  445. }
  446. } // namespace detail
  447. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  448. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  449. void (asio::error_code, std::size_t))
  450. async_read_until(AsyncReadStream& s,
  451. asio::basic_streambuf<Allocator>& b, char delim,
  452. ASIO_MOVE_ARG(ReadHandler) handler)
  453. {
  454. // If you get an error on the following line it means that your handler does
  455. // not meet the documented type requirements for a ReadHandler.
  456. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  457. detail::async_result_init<
  458. ReadHandler, void (asio::error_code, std::size_t)> init(
  459. ASIO_MOVE_CAST(ReadHandler)(handler));
  460. detail::read_until_delim_op<AsyncReadStream,
  461. Allocator, ASIO_HANDLER_TYPE(ReadHandler,
  462. void (asio::error_code, std::size_t))>(
  463. s, b, delim, init.handler)(
  464. asio::error_code(), 0, 1);
  465. return init.result.get();
  466. }
  467. namespace detail
  468. {
  469. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  470. class read_until_delim_string_op
  471. {
  472. public:
  473. read_until_delim_string_op(AsyncReadStream& stream,
  474. asio::basic_streambuf<Allocator>& streambuf,
  475. const std::string& delim, ReadHandler& handler)
  476. : stream_(stream),
  477. streambuf_(streambuf),
  478. delim_(delim),
  479. start_(0),
  480. search_position_(0),
  481. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  482. {
  483. }
  484. #if defined(ASIO_HAS_MOVE)
  485. read_until_delim_string_op(const read_until_delim_string_op& other)
  486. : stream_(other.stream_),
  487. streambuf_(other.streambuf_),
  488. delim_(other.delim_),
  489. start_(other.start_),
  490. search_position_(other.search_position_),
  491. handler_(other.handler_)
  492. {
  493. }
  494. read_until_delim_string_op(read_until_delim_string_op&& other)
  495. : stream_(other.stream_),
  496. streambuf_(other.streambuf_),
  497. delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),
  498. start_(other.start_),
  499. search_position_(other.search_position_),
  500. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  501. {
  502. }
  503. #endif // defined(ASIO_HAS_MOVE)
  504. void operator()(const asio::error_code& ec,
  505. std::size_t bytes_transferred, int start = 0)
  506. {
  507. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  508. std::size_t bytes_to_read;
  509. switch (start_ = start)
  510. {
  511. case 1:
  512. for (;;)
  513. {
  514. {
  515. // Determine the range of the data to be searched.
  516. typedef typename asio::basic_streambuf<
  517. Allocator>::const_buffers_type const_buffers_type;
  518. typedef asio::buffers_iterator<const_buffers_type> iterator;
  519. const_buffers_type buffers = streambuf_.data();
  520. iterator begin = iterator::begin(buffers);
  521. iterator start_pos = begin + search_position_;
  522. iterator end = iterator::end(buffers);
  523. // Look for a match.
  524. std::pair<iterator, bool> result = detail::partial_search(
  525. start_pos, end, delim_.begin(), delim_.end());
  526. if (result.first != end && result.second)
  527. {
  528. // Full match. We're done.
  529. search_position_ = result.first - begin + delim_.length();
  530. bytes_to_read = 0;
  531. }
  532. // No match yet. Check if buffer is full.
  533. else if (streambuf_.size() == streambuf_.max_size())
  534. {
  535. search_position_ = not_found;
  536. bytes_to_read = 0;
  537. }
  538. // Need to read some more data.
  539. else
  540. {
  541. if (result.first != end)
  542. {
  543. // Partial match. Next search needs to start from beginning of
  544. // match.
  545. search_position_ = result.first - begin;
  546. }
  547. else
  548. {
  549. // Next search can start with the new data.
  550. search_position_ = end - begin;
  551. }
  552. bytes_to_read = read_size_helper(streambuf_, 65536);
  553. }
  554. }
  555. // Check if we're done.
  556. if (!start && bytes_to_read == 0)
  557. break;
  558. // Start a new asynchronous read operation to obtain more data.
  559. stream_.async_read_some(streambuf_.prepare(bytes_to_read),
  560. ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
  561. return; default:
  562. streambuf_.commit(bytes_transferred);
  563. if (ec || bytes_transferred == 0)
  564. break;
  565. }
  566. const asio::error_code result_ec =
  567. (search_position_ == not_found)
  568. ? error::not_found : ec;
  569. const std::size_t result_n =
  570. (ec || search_position_ == not_found)
  571. ? 0 : search_position_;
  572. handler_(result_ec, result_n);
  573. }
  574. }
  575. //private:
  576. AsyncReadStream& stream_;
  577. asio::basic_streambuf<Allocator>& streambuf_;
  578. std::string delim_;
  579. int start_;
  580. std::size_t search_position_;
  581. ReadHandler handler_;
  582. };
  583. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  584. inline void* asio_handler_allocate(std::size_t size,
  585. read_until_delim_string_op<AsyncReadStream,
  586. Allocator, ReadHandler>* this_handler)
  587. {
  588. return asio_handler_alloc_helpers::allocate(
  589. size, this_handler->handler_);
  590. }
  591. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  592. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  593. read_until_delim_string_op<AsyncReadStream,
  594. Allocator, ReadHandler>* this_handler)
  595. {
  596. asio_handler_alloc_helpers::deallocate(
  597. pointer, size, this_handler->handler_);
  598. }
  599. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  600. inline bool asio_handler_is_continuation(
  601. read_until_delim_string_op<AsyncReadStream,
  602. Allocator, ReadHandler>* this_handler)
  603. {
  604. return this_handler->start_ == 0 ? true
  605. : asio_handler_cont_helpers::is_continuation(
  606. this_handler->handler_);
  607. }
  608. template <typename Function, typename AsyncReadStream,
  609. typename Allocator, typename ReadHandler>
  610. inline void asio_handler_invoke(Function& function,
  611. read_until_delim_string_op<AsyncReadStream,
  612. Allocator, ReadHandler>* this_handler)
  613. {
  614. asio_handler_invoke_helpers::invoke(
  615. function, this_handler->handler_);
  616. }
  617. template <typename Function, typename AsyncReadStream,
  618. typename Allocator, typename ReadHandler>
  619. inline void asio_handler_invoke(const Function& function,
  620. read_until_delim_string_op<AsyncReadStream,
  621. Allocator, ReadHandler>* this_handler)
  622. {
  623. asio_handler_invoke_helpers::invoke(
  624. function, this_handler->handler_);
  625. }
  626. } // namespace detail
  627. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  628. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  629. void (asio::error_code, std::size_t))
  630. async_read_until(AsyncReadStream& s,
  631. asio::basic_streambuf<Allocator>& b, const std::string& delim,
  632. ASIO_MOVE_ARG(ReadHandler) handler)
  633. {
  634. // If you get an error on the following line it means that your handler does
  635. // not meet the documented type requirements for a ReadHandler.
  636. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  637. detail::async_result_init<
  638. ReadHandler, void (asio::error_code, std::size_t)> init(
  639. ASIO_MOVE_CAST(ReadHandler)(handler));
  640. detail::read_until_delim_string_op<AsyncReadStream,
  641. Allocator, ASIO_HANDLER_TYPE(ReadHandler,
  642. void (asio::error_code, std::size_t))>(
  643. s, b, delim, init.handler)(
  644. asio::error_code(), 0, 1);
  645. return init.result.get();
  646. }
  647. #if defined(ASIO_HAS_BOOST_REGEX)
  648. namespace detail
  649. {
  650. template <typename AsyncReadStream, typename Allocator,
  651. typename RegEx, typename ReadHandler>
  652. class read_until_expr_op
  653. {
  654. public:
  655. read_until_expr_op(AsyncReadStream& stream,
  656. asio::basic_streambuf<Allocator>& streambuf,
  657. const boost::regex& expr, ReadHandler& handler)
  658. : stream_(stream),
  659. streambuf_(streambuf),
  660. expr_(expr),
  661. start_(0),
  662. search_position_(0),
  663. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  664. {
  665. }
  666. #if defined(ASIO_HAS_MOVE)
  667. read_until_expr_op(const read_until_expr_op& other)
  668. : stream_(other.stream_),
  669. streambuf_(other.streambuf_),
  670. expr_(other.expr_),
  671. start_(other.start_),
  672. search_position_(other.search_position_),
  673. handler_(other.handler_)
  674. {
  675. }
  676. read_until_expr_op(read_until_expr_op&& other)
  677. : stream_(other.stream_),
  678. streambuf_(other.streambuf_),
  679. expr_(other.expr_),
  680. start_(other.start_),
  681. search_position_(other.search_position_),
  682. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  683. {
  684. }
  685. #endif // defined(ASIO_HAS_MOVE)
  686. void operator()(const asio::error_code& ec,
  687. std::size_t bytes_transferred, int start = 0)
  688. {
  689. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  690. std::size_t bytes_to_read;
  691. switch (start_ = start)
  692. {
  693. case 1:
  694. for (;;)
  695. {
  696. {
  697. // Determine the range of the data to be searched.
  698. typedef typename asio::basic_streambuf<
  699. Allocator>::const_buffers_type const_buffers_type;
  700. typedef asio::buffers_iterator<const_buffers_type> iterator;
  701. const_buffers_type buffers = streambuf_.data();
  702. iterator begin = iterator::begin(buffers);
  703. iterator start_pos = begin + search_position_;
  704. iterator end = iterator::end(buffers);
  705. // Look for a match.
  706. boost::match_results<iterator,
  707. typename std::vector<boost::sub_match<iterator> >::allocator_type>
  708. match_results;
  709. bool match = regex_search(start_pos, end, match_results, expr_,
  710. boost::match_default | boost::match_partial);
  711. if (match && match_results[0].matched)
  712. {
  713. // Full match. We're done.
  714. search_position_ = match_results[0].second - begin;
  715. bytes_to_read = 0;
  716. }
  717. // No match yet. Check if buffer is full.
  718. else if (streambuf_.size() == streambuf_.max_size())
  719. {
  720. search_position_ = not_found;
  721. bytes_to_read = 0;
  722. }
  723. // Need to read some more data.
  724. else
  725. {
  726. if (match)
  727. {
  728. // Partial match. Next search needs to start from beginning of
  729. // match.
  730. search_position_ = match_results[0].first - begin;
  731. }
  732. else
  733. {
  734. // Next search can start with the new data.
  735. search_position_ = end - begin;
  736. }
  737. bytes_to_read = read_size_helper(streambuf_, 65536);
  738. }
  739. }
  740. // Check if we're done.
  741. if (!start && bytes_to_read == 0)
  742. break;
  743. // Start a new asynchronous read operation to obtain more data.
  744. stream_.async_read_some(streambuf_.prepare(bytes_to_read),
  745. ASIO_MOVE_CAST(read_until_expr_op)(*this));
  746. return; default:
  747. streambuf_.commit(bytes_transferred);
  748. if (ec || bytes_transferred == 0)
  749. break;
  750. }
  751. const asio::error_code result_ec =
  752. (search_position_ == not_found)
  753. ? error::not_found : ec;
  754. const std::size_t result_n =
  755. (ec || search_position_ == not_found)
  756. ? 0 : search_position_;
  757. handler_(result_ec, result_n);
  758. }
  759. }
  760. //private:
  761. AsyncReadStream& stream_;
  762. asio::basic_streambuf<Allocator>& streambuf_;
  763. RegEx expr_;
  764. int start_;
  765. std::size_t search_position_;
  766. ReadHandler handler_;
  767. };
  768. template <typename AsyncReadStream, typename Allocator,
  769. typename RegEx, typename ReadHandler>
  770. inline void* asio_handler_allocate(std::size_t size,
  771. read_until_expr_op<AsyncReadStream,
  772. Allocator, RegEx, ReadHandler>* this_handler)
  773. {
  774. return asio_handler_alloc_helpers::allocate(
  775. size, this_handler->handler_);
  776. }
  777. template <typename AsyncReadStream, typename Allocator,
  778. typename RegEx, typename ReadHandler>
  779. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  780. read_until_expr_op<AsyncReadStream,
  781. Allocator, RegEx, ReadHandler>* this_handler)
  782. {
  783. asio_handler_alloc_helpers::deallocate(
  784. pointer, size, this_handler->handler_);
  785. }
  786. template <typename AsyncReadStream, typename Allocator,
  787. typename RegEx, typename ReadHandler>
  788. inline bool asio_handler_is_continuation(
  789. read_until_expr_op<AsyncReadStream,
  790. Allocator, RegEx, ReadHandler>* this_handler)
  791. {
  792. return this_handler->start_ == 0 ? true
  793. : asio_handler_cont_helpers::is_continuation(
  794. this_handler->handler_);
  795. }
  796. template <typename Function, typename AsyncReadStream, typename Allocator,
  797. typename RegEx, typename ReadHandler>
  798. inline void asio_handler_invoke(Function& function,
  799. read_until_expr_op<AsyncReadStream,
  800. Allocator, RegEx, ReadHandler>* this_handler)
  801. {
  802. asio_handler_invoke_helpers::invoke(
  803. function, this_handler->handler_);
  804. }
  805. template <typename Function, typename AsyncReadStream, typename Allocator,
  806. typename RegEx, typename ReadHandler>
  807. inline void asio_handler_invoke(const Function& function,
  808. read_until_expr_op<AsyncReadStream,
  809. Allocator, RegEx, ReadHandler>* this_handler)
  810. {
  811. asio_handler_invoke_helpers::invoke(
  812. function, this_handler->handler_);
  813. }
  814. } // namespace detail
  815. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  816. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  817. void (asio::error_code, std::size_t))
  818. async_read_until(AsyncReadStream& s,
  819. asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
  820. ASIO_MOVE_ARG(ReadHandler) handler)
  821. {
  822. // If you get an error on the following line it means that your handler does
  823. // not meet the documented type requirements for a ReadHandler.
  824. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  825. detail::async_result_init<
  826. ReadHandler, void (asio::error_code, std::size_t)> init(
  827. ASIO_MOVE_CAST(ReadHandler)(handler));
  828. detail::read_until_expr_op<AsyncReadStream, Allocator,
  829. boost::regex, ASIO_HANDLER_TYPE(ReadHandler,
  830. void (asio::error_code, std::size_t))>(
  831. s, b, expr, init.handler)(
  832. asio::error_code(), 0, 1);
  833. return init.result.get();
  834. }
  835. #endif // defined(ASIO_HAS_BOOST_REGEX)
  836. namespace detail
  837. {
  838. template <typename AsyncReadStream, typename Allocator,
  839. typename MatchCondition, typename ReadHandler>
  840. class read_until_match_op
  841. {
  842. public:
  843. read_until_match_op(AsyncReadStream& stream,
  844. asio::basic_streambuf<Allocator>& streambuf,
  845. MatchCondition match_condition, ReadHandler& handler)
  846. : stream_(stream),
  847. streambuf_(streambuf),
  848. match_condition_(match_condition),
  849. start_(0),
  850. search_position_(0),
  851. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  852. {
  853. }
  854. #if defined(ASIO_HAS_MOVE)
  855. read_until_match_op(const read_until_match_op& other)
  856. : stream_(other.stream_),
  857. streambuf_(other.streambuf_),
  858. match_condition_(other.match_condition_),
  859. start_(other.start_),
  860. search_position_(other.search_position_),
  861. handler_(other.handler_)
  862. {
  863. }
  864. read_until_match_op(read_until_match_op&& other)
  865. : stream_(other.stream_),
  866. streambuf_(other.streambuf_),
  867. match_condition_(other.match_condition_),
  868. start_(other.start_),
  869. search_position_(other.search_position_),
  870. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  871. {
  872. }
  873. #endif // defined(ASIO_HAS_MOVE)
  874. void operator()(const asio::error_code& ec,
  875. std::size_t bytes_transferred, int start = 0)
  876. {
  877. const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
  878. std::size_t bytes_to_read;
  879. switch (start_ = start)
  880. {
  881. case 1:
  882. for (;;)
  883. {
  884. {
  885. // Determine the range of the data to be searched.
  886. typedef typename asio::basic_streambuf<
  887. Allocator>::const_buffers_type const_buffers_type;
  888. typedef asio::buffers_iterator<const_buffers_type> iterator;
  889. const_buffers_type buffers = streambuf_.data();
  890. iterator begin = iterator::begin(buffers);
  891. iterator start_pos = begin + search_position_;
  892. iterator end = iterator::end(buffers);
  893. // Look for a match.
  894. std::pair<iterator, bool> result = match_condition_(start_pos, end);
  895. if (result.second)
  896. {
  897. // Full match. We're done.
  898. search_position_ = result.first - begin;
  899. bytes_to_read = 0;
  900. }
  901. // No match yet. Check if buffer is full.
  902. else if (streambuf_.size() == streambuf_.max_size())
  903. {
  904. search_position_ = not_found;
  905. bytes_to_read = 0;
  906. }
  907. // Need to read some more data.
  908. else
  909. {
  910. if (result.first != end)
  911. {
  912. // Partial match. Next search needs to start from beginning of
  913. // match.
  914. search_position_ = result.first - begin;
  915. }
  916. else
  917. {
  918. // Next search can start with the new data.
  919. search_position_ = end - begin;
  920. }
  921. bytes_to_read = read_size_helper(streambuf_, 65536);
  922. }
  923. }
  924. // Check if we're done.
  925. if (!start && bytes_to_read == 0)
  926. break;
  927. // Start a new asynchronous read operation to obtain more data.
  928. stream_.async_read_some(streambuf_.prepare(bytes_to_read),
  929. ASIO_MOVE_CAST(read_until_match_op)(*this));
  930. return; default:
  931. streambuf_.commit(bytes_transferred);
  932. if (ec || bytes_transferred == 0)
  933. break;
  934. }
  935. const asio::error_code result_ec =
  936. (search_position_ == not_found)
  937. ? error::not_found : ec;
  938. const std::size_t result_n =
  939. (ec || search_position_ == not_found)
  940. ? 0 : search_position_;
  941. handler_(result_ec, result_n);
  942. }
  943. }
  944. //private:
  945. AsyncReadStream& stream_;
  946. asio::basic_streambuf<Allocator>& streambuf_;
  947. MatchCondition match_condition_;
  948. int start_;
  949. std::size_t search_position_;
  950. ReadHandler handler_;
  951. };
  952. template <typename AsyncReadStream, typename Allocator,
  953. typename MatchCondition, typename ReadHandler>
  954. inline void* asio_handler_allocate(std::size_t size,
  955. read_until_match_op<AsyncReadStream,
  956. Allocator, MatchCondition, ReadHandler>* this_handler)
  957. {
  958. return asio_handler_alloc_helpers::allocate(
  959. size, this_handler->handler_);
  960. }
  961. template <typename AsyncReadStream, typename Allocator,
  962. typename MatchCondition, typename ReadHandler>
  963. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  964. read_until_match_op<AsyncReadStream,
  965. Allocator, MatchCondition, ReadHandler>* this_handler)
  966. {
  967. asio_handler_alloc_helpers::deallocate(
  968. pointer, size, this_handler->handler_);
  969. }
  970. template <typename AsyncReadStream, typename Allocator,
  971. typename MatchCondition, typename ReadHandler>
  972. inline bool asio_handler_is_continuation(
  973. read_until_match_op<AsyncReadStream,
  974. Allocator, MatchCondition, ReadHandler>* this_handler)
  975. {
  976. return this_handler->start_ == 0 ? true
  977. : asio_handler_cont_helpers::is_continuation(
  978. this_handler->handler_);
  979. }
  980. template <typename Function, typename AsyncReadStream, typename Allocator,
  981. typename MatchCondition, typename ReadHandler>
  982. inline void asio_handler_invoke(Function& function,
  983. read_until_match_op<AsyncReadStream,
  984. Allocator, MatchCondition, ReadHandler>* this_handler)
  985. {
  986. asio_handler_invoke_helpers::invoke(
  987. function, this_handler->handler_);
  988. }
  989. template <typename Function, typename AsyncReadStream, typename Allocator,
  990. typename MatchCondition, typename ReadHandler>
  991. inline void asio_handler_invoke(const Function& function,
  992. read_until_match_op<AsyncReadStream,
  993. Allocator, MatchCondition, ReadHandler>* this_handler)
  994. {
  995. asio_handler_invoke_helpers::invoke(
  996. function, this_handler->handler_);
  997. }
  998. } // namespace detail
  999. template <typename AsyncReadStream, typename Allocator,
  1000. typename MatchCondition, typename ReadHandler>
  1001. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  1002. void (asio::error_code, std::size_t))
  1003. async_read_until(AsyncReadStream& s,
  1004. asio::basic_streambuf<Allocator>& b,
  1005. MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,
  1006. typename enable_if<is_match_condition<MatchCondition>::value>::type*)
  1007. {
  1008. // If you get an error on the following line it means that your handler does
  1009. // not meet the documented type requirements for a ReadHandler.
  1010. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  1011. detail::async_result_init<
  1012. ReadHandler, void (asio::error_code, std::size_t)> init(
  1013. ASIO_MOVE_CAST(ReadHandler)(handler));
  1014. detail::read_until_match_op<AsyncReadStream, Allocator,
  1015. MatchCondition, ASIO_HANDLER_TYPE(ReadHandler,
  1016. void (asio::error_code, std::size_t))>(
  1017. s, b, match_condition, init.handler)(
  1018. asio::error_code(), 0, 1);
  1019. return init.result.get();
  1020. }
  1021. } // namespace asio
  1022. #include "asio/detail/pop_options.hpp"
  1023. #endif // ASIO_IMPL_READ_UNTIL_HPP