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.

3005 lines
99KB

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