Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1492 lines
49KB

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