5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_IMPL_READ_UNTIL_HPP
12 #define BOOST_ASIO_IMPL_READ_UNTIL_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
22 #include <boost/asio/associated_allocator.hpp>
23 #include <boost/asio/associated_executor.hpp>
24 #include <boost/asio/buffer.hpp>
25 #include <boost/asio/buffers_iterator.hpp>
26 #include <boost/asio/detail/bind_handler.hpp>
27 #include <boost/asio/detail/handler_alloc_helpers.hpp>
28 #include <boost/asio/detail/handler_cont_helpers.hpp>
29 #include <boost/asio/detail/handler_invoke_helpers.hpp>
30 #include <boost/asio/detail/handler_type_requirements.hpp>
31 #include <boost/asio/detail/limits.hpp>
32 #include <boost/asio/detail/non_const_lvalue.hpp>
33 #include <boost/asio/detail/throw_error.hpp>
35 #include <boost/asio/detail/push_options.hpp>
42 // Algorithm that finds a subsequence of equal values in a sequence. Returns
43 // (iterator,true) if a full match was found, in which case the iterator
44 // points to the beginning of the match. Returns (iterator,false) if a
45 // partial match was found at the end of the first sequence, in which case
46 // the iterator points to the beginning of the partial match. Returns
47 // (last1,false) if no full or partial match was found.
48 template <typename Iterator1, typename Iterator2>
49 std::pair<Iterator1, bool> partial_search(
50 Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
52 for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
54 Iterator1 test_iter1 = iter1;
55 Iterator2 test_iter2 = first2;
56 for (;; ++test_iter1, ++test_iter2)
58 if (test_iter2 == last2)
59 return std::make_pair(iter1, true);
60 if (test_iter1 == last1)
62 if (test_iter2 != first2)
63 return std::make_pair(iter1, false);
67 if (*test_iter1 != *test_iter2)
71 return std::make_pair(last1, false);
75 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
77 template <typename SyncReadStream, typename DynamicBuffer_v1>
78 inline std::size_t read_until(SyncReadStream& s,
79 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,
81 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
82 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
85 boost::system::error_code ec;
86 std::size_t bytes_transferred = read_until(s,
87 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
88 boost::asio::detail::throw_error(ec, "read_until");
89 return bytes_transferred;
92 template <typename SyncReadStream, typename DynamicBuffer_v1>
93 std::size_t read_until(SyncReadStream& s,
94 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
95 char delim, boost::system::error_code& ec,
97 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
98 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
101 typename decay<DynamicBuffer_v1>::type b(
102 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
104 std::size_t search_position = 0;
107 // Determine the range of the data to be searched.
108 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
109 typedef buffers_iterator<buffers_type> iterator;
110 buffers_type data_buffers = b.data();
111 iterator begin = iterator::begin(data_buffers);
112 iterator start_pos = begin + search_position;
113 iterator end = iterator::end(data_buffers);
116 iterator iter = std::find(start_pos, end, delim);
119 // Found a match. We're done.
120 ec = boost::system::error_code();
121 return iter - begin + 1;
125 // No match. Next search can start with the new data.
126 search_position = end - begin;
129 // Check if buffer is full.
130 if (b.size() == b.max_size())
132 ec = error::not_found;
137 std::size_t bytes_to_read = std::min<std::size_t>(
138 std::max<std::size_t>(512, b.capacity() - b.size()),
139 std::min<std::size_t>(65536, b.max_size() - b.size()));
140 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
146 template <typename SyncReadStream, typename DynamicBuffer_v1>
147 inline std::size_t read_until(SyncReadStream& s,
148 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
149 BOOST_ASIO_STRING_VIEW_PARAM delim,
151 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
152 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
155 boost::system::error_code ec;
156 std::size_t bytes_transferred = read_until(s,
157 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
158 boost::asio::detail::throw_error(ec, "read_until");
159 return bytes_transferred;
162 template <typename SyncReadStream, typename DynamicBuffer_v1>
163 std::size_t read_until(SyncReadStream& s,
164 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
165 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
167 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
168 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
171 typename decay<DynamicBuffer_v1>::type b(
172 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
174 std::size_t search_position = 0;
177 // Determine the range of the data to be searched.
178 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
179 typedef buffers_iterator<buffers_type> iterator;
180 buffers_type data_buffers = b.data();
181 iterator begin = iterator::begin(data_buffers);
182 iterator start_pos = begin + search_position;
183 iterator end = iterator::end(data_buffers);
186 std::pair<iterator, bool> result = detail::partial_search(
187 start_pos, end, delim.begin(), delim.end());
188 if (result.first != end)
192 // Full match. We're done.
193 ec = boost::system::error_code();
194 return result.first - begin + delim.length();
198 // Partial match. Next search needs to start from beginning of match.
199 search_position = result.first - begin;
204 // No match. Next search can start with the new data.
205 search_position = end - begin;
208 // Check if buffer is full.
209 if (b.size() == b.max_size())
211 ec = error::not_found;
216 std::size_t bytes_to_read = std::min<std::size_t>(
217 std::max<std::size_t>(512, b.capacity() - b.size()),
218 std::min<std::size_t>(65536, b.max_size() - b.size()));
219 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
225 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
226 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
228 template <typename SyncReadStream, typename DynamicBuffer_v1>
229 inline std::size_t read_until(SyncReadStream& s,
230 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
231 const boost::regex& expr,
233 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
234 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
237 boost::system::error_code ec;
238 std::size_t bytes_transferred = read_until(s,
239 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec);
240 boost::asio::detail::throw_error(ec, "read_until");
241 return bytes_transferred;
244 template <typename SyncReadStream, typename DynamicBuffer_v1>
245 std::size_t read_until(SyncReadStream& s,
246 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
247 const boost::regex& expr, boost::system::error_code& ec,
249 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
250 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
253 typename decay<DynamicBuffer_v1>::type b(
254 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
256 std::size_t search_position = 0;
259 // Determine the range of the data to be searched.
260 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
261 typedef buffers_iterator<buffers_type> iterator;
262 buffers_type data_buffers = b.data();
263 iterator begin = iterator::begin(data_buffers);
264 iterator start_pos = begin + search_position;
265 iterator end = iterator::end(data_buffers);
268 boost::match_results<iterator,
269 typename std::vector<boost::sub_match<iterator> >::allocator_type>
271 if (regex_search(start_pos, end, match_results, expr,
272 boost::match_default | boost::match_partial))
274 if (match_results[0].matched)
276 // Full match. We're done.
277 ec = boost::system::error_code();
278 return match_results[0].second - begin;
282 // Partial match. Next search needs to start from beginning of match.
283 search_position = match_results[0].first - begin;
288 // No match. Next search can start with the new data.
289 search_position = end - begin;
292 // Check if buffer is full.
293 if (b.size() == b.max_size())
295 ec = error::not_found;
300 std::size_t bytes_to_read = std::min<std::size_t>(
301 std::max<std::size_t>(512, b.capacity() - b.size()),
302 std::min<std::size_t>(65536, b.max_size() - b.size()));
303 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
309 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
311 template <typename SyncReadStream,
312 typename DynamicBuffer_v1, typename MatchCondition>
313 inline std::size_t read_until(SyncReadStream& s,
314 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
315 MatchCondition match_condition,
317 is_match_condition<MatchCondition>::value
318 && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
319 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
322 boost::system::error_code ec;
323 std::size_t bytes_transferred = read_until(s,
324 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
325 match_condition, ec);
326 boost::asio::detail::throw_error(ec, "read_until");
327 return bytes_transferred;
330 template <typename SyncReadStream,
331 typename DynamicBuffer_v1, typename MatchCondition>
332 std::size_t read_until(SyncReadStream& s,
333 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
334 MatchCondition match_condition, boost::system::error_code& ec,
336 is_match_condition<MatchCondition>::value
337 && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
338 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
341 typename decay<DynamicBuffer_v1>::type b(
342 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
344 std::size_t search_position = 0;
347 // Determine the range of the data to be searched.
348 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
349 typedef buffers_iterator<buffers_type> iterator;
350 buffers_type data_buffers = b.data();
351 iterator begin = iterator::begin(data_buffers);
352 iterator start_pos = begin + search_position;
353 iterator end = iterator::end(data_buffers);
356 std::pair<iterator, bool> result = match_condition(start_pos, end);
359 // Full match. We're done.
360 ec = boost::system::error_code();
361 return result.first - begin;
363 else if (result.first != end)
365 // Partial match. Next search needs to start from beginning of match.
366 search_position = result.first - begin;
370 // No match. Next search can start with the new data.
371 search_position = end - begin;
374 // Check if buffer is full.
375 if (b.size() == b.max_size())
377 ec = error::not_found;
382 std::size_t bytes_to_read = std::min<std::size_t>(
383 std::max<std::size_t>(512, b.capacity() - b.size()),
384 std::min<std::size_t>(65536, b.max_size() - b.size()));
385 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
391 #if !defined(BOOST_ASIO_NO_IOSTREAM)
393 template <typename SyncReadStream, typename Allocator>
394 inline std::size_t read_until(SyncReadStream& s,
395 boost::asio::basic_streambuf<Allocator>& b, char delim)
397 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
400 template <typename SyncReadStream, typename Allocator>
401 inline std::size_t read_until(SyncReadStream& s,
402 boost::asio::basic_streambuf<Allocator>& b, char delim,
403 boost::system::error_code& ec)
405 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
408 template <typename SyncReadStream, typename Allocator>
409 inline std::size_t read_until(SyncReadStream& s,
410 boost::asio::basic_streambuf<Allocator>& b,
411 BOOST_ASIO_STRING_VIEW_PARAM delim)
413 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
416 template <typename SyncReadStream, typename Allocator>
417 inline std::size_t read_until(SyncReadStream& s,
418 boost::asio::basic_streambuf<Allocator>& b,
419 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
421 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
424 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
426 template <typename SyncReadStream, typename Allocator>
427 inline std::size_t read_until(SyncReadStream& s,
428 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
430 return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
433 template <typename SyncReadStream, typename Allocator>
434 inline std::size_t read_until(SyncReadStream& s,
435 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
436 boost::system::error_code& ec)
438 return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
441 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
443 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
444 inline std::size_t read_until(SyncReadStream& s,
445 boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
446 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
448 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
451 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
452 inline std::size_t read_until(SyncReadStream& s,
453 boost::asio::basic_streambuf<Allocator>& b,
454 MatchCondition match_condition, boost::system::error_code& ec,
455 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
457 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
460 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
461 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
462 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
464 template <typename SyncReadStream, typename DynamicBuffer_v2>
465 inline std::size_t read_until(SyncReadStream& s,
466 DynamicBuffer_v2 buffers, char delim,
468 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
471 boost::system::error_code ec;
472 std::size_t bytes_transferred = read_until(s,
473 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
474 boost::asio::detail::throw_error(ec, "read_until");
475 return bytes_transferred;
478 template <typename SyncReadStream, typename DynamicBuffer_v2>
479 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
480 char delim, boost::system::error_code& ec,
482 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
485 DynamicBuffer_v2& b = buffers;
487 std::size_t search_position = 0;
490 // Determine the range of the data to be searched.
491 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
492 typedef buffers_iterator<buffers_type> iterator;
493 buffers_type data_buffers =
494 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
495 iterator begin = iterator::begin(data_buffers);
496 iterator start_pos = begin + search_position;
497 iterator end = iterator::end(data_buffers);
500 iterator iter = std::find(start_pos, end, delim);
503 // Found a match. We're done.
504 ec = boost::system::error_code();
505 return iter - begin + 1;
509 // No match. Next search can start with the new data.
510 search_position = end - begin;
513 // Check if buffer is full.
514 if (b.size() == b.max_size())
516 ec = error::not_found;
521 std::size_t bytes_to_read = std::min<std::size_t>(
522 std::max<std::size_t>(512, b.capacity() - b.size()),
523 std::min<std::size_t>(65536, b.max_size() - b.size()));
524 std::size_t pos = b.size();
525 b.grow(bytes_to_read);
526 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
527 b.shrink(bytes_to_read - bytes_transferred);
533 template <typename SyncReadStream, typename DynamicBuffer_v2>
534 inline std::size_t read_until(SyncReadStream& s,
535 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
537 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
540 boost::system::error_code ec;
541 std::size_t bytes_transferred = read_until(s,
542 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
543 boost::asio::detail::throw_error(ec, "read_until");
544 return bytes_transferred;
547 template <typename SyncReadStream, typename DynamicBuffer_v2>
548 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
549 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
551 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
554 DynamicBuffer_v2& b = buffers;
556 std::size_t search_position = 0;
559 // Determine the range of the data to be searched.
560 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
561 typedef buffers_iterator<buffers_type> iterator;
562 buffers_type data_buffers =
563 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
564 iterator begin = iterator::begin(data_buffers);
565 iterator start_pos = begin + search_position;
566 iterator end = iterator::end(data_buffers);
569 std::pair<iterator, bool> result = detail::partial_search(
570 start_pos, end, delim.begin(), delim.end());
571 if (result.first != end)
575 // Full match. We're done.
576 ec = boost::system::error_code();
577 return result.first - begin + delim.length();
581 // Partial match. Next search needs to start from beginning of match.
582 search_position = result.first - begin;
587 // No match. Next search can start with the new data.
588 search_position = end - begin;
591 // Check if buffer is full.
592 if (b.size() == b.max_size())
594 ec = error::not_found;
599 std::size_t bytes_to_read = std::min<std::size_t>(
600 std::max<std::size_t>(512, b.capacity() - b.size()),
601 std::min<std::size_t>(65536, b.max_size() - b.size()));
602 std::size_t pos = b.size();
603 b.grow(bytes_to_read);
604 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
605 b.shrink(bytes_to_read - bytes_transferred);
611 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
612 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
614 template <typename SyncReadStream, typename DynamicBuffer_v2>
615 inline std::size_t read_until(SyncReadStream& s,
616 DynamicBuffer_v2 buffers, const boost::regex& expr,
618 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
621 boost::system::error_code ec;
622 std::size_t bytes_transferred = read_until(s,
623 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec);
624 boost::asio::detail::throw_error(ec, "read_until");
625 return bytes_transferred;
628 template <typename SyncReadStream, typename DynamicBuffer_v2>
629 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
630 const boost::regex& expr, boost::system::error_code& ec,
632 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
635 DynamicBuffer_v2& b = buffers;
637 std::size_t search_position = 0;
640 // Determine the range of the data to be searched.
641 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
642 typedef buffers_iterator<buffers_type> iterator;
643 buffers_type data_buffers =
644 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
645 iterator begin = iterator::begin(data_buffers);
646 iterator start_pos = begin + search_position;
647 iterator end = iterator::end(data_buffers);
650 boost::match_results<iterator,
651 typename std::vector<boost::sub_match<iterator> >::allocator_type>
653 if (regex_search(start_pos, end, match_results, expr,
654 boost::match_default | boost::match_partial))
656 if (match_results[0].matched)
658 // Full match. We're done.
659 ec = boost::system::error_code();
660 return match_results[0].second - begin;
664 // Partial match. Next search needs to start from beginning of match.
665 search_position = match_results[0].first - begin;
670 // No match. Next search can start with the new data.
671 search_position = end - begin;
674 // Check if buffer is full.
675 if (b.size() == b.max_size())
677 ec = error::not_found;
682 std::size_t bytes_to_read = std::min<std::size_t>(
683 std::max<std::size_t>(512, b.capacity() - b.size()),
684 std::min<std::size_t>(65536, b.max_size() - b.size()));
685 std::size_t pos = b.size();
686 b.grow(bytes_to_read);
687 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
688 b.shrink(bytes_to_read - bytes_transferred);
694 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
696 template <typename SyncReadStream,
697 typename DynamicBuffer_v2, typename MatchCondition>
698 inline std::size_t read_until(SyncReadStream& s,
699 DynamicBuffer_v2 buffers, MatchCondition match_condition,
701 is_match_condition<MatchCondition>::value
702 && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
705 boost::system::error_code ec;
706 std::size_t bytes_transferred = read_until(s,
707 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
708 match_condition, ec);
709 boost::asio::detail::throw_error(ec, "read_until");
710 return bytes_transferred;
713 template <typename SyncReadStream,
714 typename DynamicBuffer_v2, typename MatchCondition>
715 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
716 MatchCondition match_condition, boost::system::error_code& ec,
718 is_match_condition<MatchCondition>::value
719 && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
722 DynamicBuffer_v2& b = buffers;
724 std::size_t search_position = 0;
727 // Determine the range of the data to be searched.
728 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
729 typedef buffers_iterator<buffers_type> iterator;
730 buffers_type data_buffers =
731 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
732 iterator begin = iterator::begin(data_buffers);
733 iterator start_pos = begin + search_position;
734 iterator end = iterator::end(data_buffers);
737 std::pair<iterator, bool> result = match_condition(start_pos, end);
740 // Full match. We're done.
741 ec = boost::system::error_code();
742 return result.first - begin;
744 else if (result.first != end)
746 // Partial match. Next search needs to start from beginning of match.
747 search_position = result.first - begin;
751 // No match. Next search can start with the new data.
752 search_position = end - begin;
755 // Check if buffer is full.
756 if (b.size() == b.max_size())
758 ec = error::not_found;
763 std::size_t bytes_to_read = std::min<std::size_t>(
764 std::max<std::size_t>(512, b.capacity() - b.size()),
765 std::min<std::size_t>(65536, b.max_size() - b.size()));
766 std::size_t pos = b.size();
767 b.grow(bytes_to_read);
768 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
769 b.shrink(bytes_to_read - bytes_transferred);
775 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
777 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
781 template <typename AsyncReadStream,
782 typename DynamicBuffer_v1, typename ReadHandler>
783 class read_until_delim_op_v1
786 template <typename BufferSequence>
787 read_until_delim_op_v1(AsyncReadStream& stream,
788 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
789 char delim, ReadHandler& handler)
791 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
795 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
799 #if defined(BOOST_ASIO_HAS_MOVE)
800 read_until_delim_op_v1(const read_until_delim_op_v1& other)
801 : stream_(other.stream_),
802 buffers_(other.buffers_),
803 delim_(other.delim_),
804 start_(other.start_),
805 search_position_(other.search_position_),
806 handler_(other.handler_)
810 read_until_delim_op_v1(read_until_delim_op_v1&& other)
811 : stream_(other.stream_),
812 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
813 delim_(other.delim_),
814 start_(other.start_),
815 search_position_(other.search_position_),
816 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
819 #endif // defined(BOOST_ASIO_HAS_MOVE)
821 void operator()(const boost::system::error_code& ec,
822 std::size_t bytes_transferred, int start = 0)
824 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
825 std::size_t bytes_to_read;
826 switch (start_ = start)
832 // Determine the range of the data to be searched.
833 typedef typename DynamicBuffer_v1::const_buffers_type
835 typedef buffers_iterator<buffers_type> iterator;
836 buffers_type data_buffers = buffers_.data();
837 iterator begin = iterator::begin(data_buffers);
838 iterator start_pos = begin + search_position_;
839 iterator end = iterator::end(data_buffers);
842 iterator iter = std::find(start_pos, end, delim_);
845 // Found a match. We're done.
846 search_position_ = iter - begin + 1;
850 // No match yet. Check if buffer is full.
851 else if (buffers_.size() == buffers_.max_size())
853 search_position_ = not_found;
857 // Need to read some more data.
860 // Next search can start with the new data.
861 search_position_ = end - begin;
862 bytes_to_read = std::min<std::size_t>(
863 std::max<std::size_t>(512,
864 buffers_.capacity() - buffers_.size()),
865 std::min<std::size_t>(65536,
866 buffers_.max_size() - buffers_.size()));
870 // Check if we're done.
871 if (!start && bytes_to_read == 0)
874 // Start a new asynchronous read op_v1eration to obtain more data.
875 stream_.async_read_some(buffers_.prepare(bytes_to_read),
876 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));
878 buffers_.commit(bytes_transferred);
879 if (ec || bytes_transferred == 0)
883 const boost::system::error_code result_ec =
884 (search_position_ == not_found)
885 ? error::not_found : ec;
887 const std::size_t result_n =
888 (ec || search_position_ == not_found)
889 ? 0 : search_position_;
891 handler_(result_ec, result_n);
896 AsyncReadStream& stream_;
897 DynamicBuffer_v1 buffers_;
900 std::size_t search_position_;
901 ReadHandler handler_;
904 template <typename AsyncReadStream,
905 typename DynamicBuffer_v1, typename ReadHandler>
906 inline void* asio_handler_allocate(std::size_t size,
907 read_until_delim_op_v1<AsyncReadStream,
908 DynamicBuffer_v1, ReadHandler>* this_handler)
910 return boost_asio_handler_alloc_helpers::allocate(
911 size, this_handler->handler_);
914 template <typename AsyncReadStream,
915 typename DynamicBuffer_v1, typename ReadHandler>
916 inline void asio_handler_deallocate(void* pointer, std::size_t size,
917 read_until_delim_op_v1<AsyncReadStream,
918 DynamicBuffer_v1, ReadHandler>* this_handler)
920 boost_asio_handler_alloc_helpers::deallocate(
921 pointer, size, this_handler->handler_);
924 template <typename AsyncReadStream,
925 typename DynamicBuffer_v1, typename ReadHandler>
926 inline bool asio_handler_is_continuation(
927 read_until_delim_op_v1<AsyncReadStream,
928 DynamicBuffer_v1, ReadHandler>* this_handler)
930 return this_handler->start_ == 0 ? true
931 : boost_asio_handler_cont_helpers::is_continuation(
932 this_handler->handler_);
935 template <typename Function, typename AsyncReadStream,
936 typename DynamicBuffer_v1, typename ReadHandler>
937 inline void asio_handler_invoke(Function& function,
938 read_until_delim_op_v1<AsyncReadStream,
939 DynamicBuffer_v1, ReadHandler>* this_handler)
941 boost_asio_handler_invoke_helpers::invoke(
942 function, this_handler->handler_);
945 template <typename Function, typename AsyncReadStream,
946 typename DynamicBuffer_v1, typename ReadHandler>
947 inline void asio_handler_invoke(const Function& function,
948 read_until_delim_op_v1<AsyncReadStream,
949 DynamicBuffer_v1, ReadHandler>* this_handler)
951 boost_asio_handler_invoke_helpers::invoke(
952 function, this_handler->handler_);
955 template <typename AsyncReadStream>
956 class initiate_async_read_until_delim_v1
959 typedef typename AsyncReadStream::executor_type executor_type;
961 explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)
966 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
968 return stream_.get_executor();
971 template <typename ReadHandler, typename DynamicBuffer_v1>
972 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
973 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
976 // If you get an error on the following line it means that your handler
977 // does not meet the documented type requirements for a ReadHandler.
978 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
980 non_const_lvalue<ReadHandler> handler2(handler);
981 read_until_delim_op_v1<AsyncReadStream,
982 typename decay<DynamicBuffer_v1>::type,
983 typename decay<ReadHandler>::type>(
984 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
985 delim, handler2.value)(boost::system::error_code(), 0, 1);
989 AsyncReadStream& stream_;
991 } // namespace detail
993 #if !defined(GENERATING_DOCUMENTATION)
995 template <typename AsyncReadStream, typename DynamicBuffer_v1,
996 typename ReadHandler, typename Allocator>
997 struct associated_allocator<
998 detail::read_until_delim_op_v1<AsyncReadStream,
999 DynamicBuffer_v1, ReadHandler>,
1002 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1005 const detail::read_until_delim_op_v1<AsyncReadStream,
1006 DynamicBuffer_v1, ReadHandler>& h,
1007 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1009 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1013 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1014 typename ReadHandler, typename Executor>
1015 struct associated_executor<
1016 detail::read_until_delim_op_v1<AsyncReadStream,
1017 DynamicBuffer_v1, ReadHandler>,
1020 typedef typename associated_executor<ReadHandler, Executor>::type type;
1023 const detail::read_until_delim_op_v1<AsyncReadStream,
1024 DynamicBuffer_v1, ReadHandler>& h,
1025 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1027 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1031 #endif // !defined(GENERATING_DOCUMENTATION)
1033 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1034 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1035 std::size_t)) ReadHandler>
1036 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1037 void (boost::system::error_code, std::size_t))
1038 async_read_until(AsyncReadStream& s,
1039 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1040 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1042 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1043 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1046 return async_initiate<ReadHandler,
1047 void (boost::system::error_code, std::size_t)>(
1048 detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
1049 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);
1054 template <typename AsyncReadStream,
1055 typename DynamicBuffer_v1, typename ReadHandler>
1056 class read_until_delim_string_op_v1
1059 template <typename BufferSequence>
1060 read_until_delim_string_op_v1(AsyncReadStream& stream,
1061 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1062 const std::string& delim, ReadHandler& handler)
1064 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1067 search_position_(0),
1068 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1072 #if defined(BOOST_ASIO_HAS_MOVE)
1073 read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
1074 : stream_(other.stream_),
1075 buffers_(other.buffers_),
1076 delim_(other.delim_),
1077 start_(other.start_),
1078 search_position_(other.search_position_),
1079 handler_(other.handler_)
1083 read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)
1084 : stream_(other.stream_),
1085 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1086 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
1087 start_(other.start_),
1088 search_position_(other.search_position_),
1089 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1092 #endif // defined(BOOST_ASIO_HAS_MOVE)
1094 void operator()(const boost::system::error_code& ec,
1095 std::size_t bytes_transferred, int start = 0)
1097 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1098 std::size_t bytes_to_read;
1099 switch (start_ = start)
1105 // Determine the range of the data to be searched.
1106 typedef typename DynamicBuffer_v1::const_buffers_type
1108 typedef buffers_iterator<buffers_type> iterator;
1109 buffers_type data_buffers = buffers_.data();
1110 iterator begin = iterator::begin(data_buffers);
1111 iterator start_pos = begin + search_position_;
1112 iterator end = iterator::end(data_buffers);
1114 // Look for a match.
1115 std::pair<iterator, bool> result = detail::partial_search(
1116 start_pos, end, delim_.begin(), delim_.end());
1117 if (result.first != end && result.second)
1119 // Full match. We're done.
1120 search_position_ = result.first - begin + delim_.length();
1124 // No match yet. Check if buffer is full.
1125 else if (buffers_.size() == buffers_.max_size())
1127 search_position_ = not_found;
1131 // Need to read some more data.
1134 if (result.first != end)
1136 // Partial match. Next search needs to start from beginning of
1138 search_position_ = result.first - begin;
1142 // Next search can start with the new data.
1143 search_position_ = end - begin;
1146 bytes_to_read = std::min<std::size_t>(
1147 std::max<std::size_t>(512,
1148 buffers_.capacity() - buffers_.size()),
1149 std::min<std::size_t>(65536,
1150 buffers_.max_size() - buffers_.size()));
1154 // Check if we're done.
1155 if (!start && bytes_to_read == 0)
1158 // Start a new asynchronous read op_v1eration to obtain more data.
1159 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1160 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this));
1162 buffers_.commit(bytes_transferred);
1163 if (ec || bytes_transferred == 0)
1167 const boost::system::error_code result_ec =
1168 (search_position_ == not_found)
1169 ? error::not_found : ec;
1171 const std::size_t result_n =
1172 (ec || search_position_ == not_found)
1173 ? 0 : search_position_;
1175 handler_(result_ec, result_n);
1180 AsyncReadStream& stream_;
1181 DynamicBuffer_v1 buffers_;
1184 std::size_t search_position_;
1185 ReadHandler handler_;
1188 template <typename AsyncReadStream,
1189 typename DynamicBuffer_v1, typename ReadHandler>
1190 inline void* asio_handler_allocate(std::size_t size,
1191 read_until_delim_string_op_v1<AsyncReadStream,
1192 DynamicBuffer_v1, ReadHandler>* this_handler)
1194 return boost_asio_handler_alloc_helpers::allocate(
1195 size, this_handler->handler_);
1198 template <typename AsyncReadStream,
1199 typename DynamicBuffer_v1, typename ReadHandler>
1200 inline void asio_handler_deallocate(void* pointer, std::size_t size,
1201 read_until_delim_string_op_v1<AsyncReadStream,
1202 DynamicBuffer_v1, ReadHandler>* this_handler)
1204 boost_asio_handler_alloc_helpers::deallocate(
1205 pointer, size, this_handler->handler_);
1208 template <typename AsyncReadStream,
1209 typename DynamicBuffer_v1, typename ReadHandler>
1210 inline bool asio_handler_is_continuation(
1211 read_until_delim_string_op_v1<AsyncReadStream,
1212 DynamicBuffer_v1, ReadHandler>* this_handler)
1214 return this_handler->start_ == 0 ? true
1215 : boost_asio_handler_cont_helpers::is_continuation(
1216 this_handler->handler_);
1219 template <typename Function, typename AsyncReadStream,
1220 typename DynamicBuffer_v1, typename ReadHandler>
1221 inline void asio_handler_invoke(Function& function,
1222 read_until_delim_string_op_v1<AsyncReadStream,
1223 DynamicBuffer_v1, ReadHandler>* this_handler)
1225 boost_asio_handler_invoke_helpers::invoke(
1226 function, this_handler->handler_);
1229 template <typename Function, typename AsyncReadStream,
1230 typename DynamicBuffer_v1, typename ReadHandler>
1231 inline void asio_handler_invoke(const Function& function,
1232 read_until_delim_string_op_v1<AsyncReadStream,
1233 DynamicBuffer_v1, ReadHandler>* this_handler)
1235 boost_asio_handler_invoke_helpers::invoke(
1236 function, this_handler->handler_);
1239 template <typename AsyncReadStream>
1240 class initiate_async_read_until_delim_string_v1
1243 typedef typename AsyncReadStream::executor_type executor_type;
1245 explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)
1250 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1252 return stream_.get_executor();
1255 template <typename ReadHandler, typename DynamicBuffer_v1>
1256 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1257 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1258 const std::string& delim) const
1260 // If you get an error on the following line it means that your handler
1261 // does not meet the documented type requirements for a ReadHandler.
1262 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1264 non_const_lvalue<ReadHandler> handler2(handler);
1265 read_until_delim_string_op_v1<AsyncReadStream,
1266 typename decay<DynamicBuffer_v1>::type,
1267 typename decay<ReadHandler>::type>(
1268 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1269 delim, handler2.value)(boost::system::error_code(), 0, 1);
1273 AsyncReadStream& stream_;
1275 } // namespace detail
1277 #if !defined(GENERATING_DOCUMENTATION)
1279 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1280 typename ReadHandler, typename Allocator>
1281 struct associated_allocator<
1282 detail::read_until_delim_string_op_v1<AsyncReadStream,
1283 DynamicBuffer_v1, ReadHandler>,
1286 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1289 const detail::read_until_delim_string_op_v1<AsyncReadStream,
1290 DynamicBuffer_v1, ReadHandler>& h,
1291 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1293 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1297 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1298 typename ReadHandler, typename Executor>
1299 struct associated_executor<
1300 detail::read_until_delim_string_op_v1<AsyncReadStream,
1301 DynamicBuffer_v1, ReadHandler>,
1304 typedef typename associated_executor<ReadHandler, Executor>::type type;
1307 const detail::read_until_delim_string_op_v1<AsyncReadStream,
1308 DynamicBuffer_v1, ReadHandler>& h,
1309 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1311 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1315 #endif // !defined(GENERATING_DOCUMENTATION)
1317 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1318 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1319 std::size_t)) ReadHandler>
1320 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1321 void (boost::system::error_code, std::size_t))
1322 async_read_until(AsyncReadStream& s,
1323 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1324 BOOST_ASIO_STRING_VIEW_PARAM delim,
1325 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1327 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1328 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1331 return async_initiate<ReadHandler,
1332 void (boost::system::error_code, std::size_t)>(
1333 detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
1334 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1335 static_cast<std::string>(delim));
1338 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
1339 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
1343 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1344 typename RegEx, typename ReadHandler>
1345 class read_until_expr_op_v1
1348 template <typename BufferSequence>
1349 read_until_expr_op_v1(AsyncReadStream& stream,
1350 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1351 const boost::regex& expr, ReadHandler& handler)
1353 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1356 search_position_(0),
1357 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1361 #if defined(BOOST_ASIO_HAS_MOVE)
1362 read_until_expr_op_v1(const read_until_expr_op_v1& other)
1363 : stream_(other.stream_),
1364 buffers_(other.buffers_),
1366 start_(other.start_),
1367 search_position_(other.search_position_),
1368 handler_(other.handler_)
1372 read_until_expr_op_v1(read_until_expr_op_v1&& other)
1373 : stream_(other.stream_),
1374 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1376 start_(other.start_),
1377 search_position_(other.search_position_),
1378 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1381 #endif // defined(BOOST_ASIO_HAS_MOVE)
1383 void operator()(const boost::system::error_code& ec,
1384 std::size_t bytes_transferred, int start = 0)
1386 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1387 std::size_t bytes_to_read;
1388 switch (start_ = start)
1394 // Determine the range of the data to be searched.
1395 typedef typename DynamicBuffer_v1::const_buffers_type
1397 typedef buffers_iterator<buffers_type> iterator;
1398 buffers_type data_buffers = buffers_.data();
1399 iterator begin = iterator::begin(data_buffers);
1400 iterator start_pos = begin + search_position_;
1401 iterator end = iterator::end(data_buffers);
1403 // Look for a match.
1404 boost::match_results<iterator,
1405 typename std::vector<boost::sub_match<iterator> >::allocator_type>
1407 bool match = regex_search(start_pos, end, match_results, expr_,
1408 boost::match_default | boost::match_partial);
1409 if (match && match_results[0].matched)
1411 // Full match. We're done.
1412 search_position_ = match_results[0].second - begin;
1416 // No match yet. Check if buffer is full.
1417 else if (buffers_.size() == buffers_.max_size())
1419 search_position_ = not_found;
1423 // Need to read some more data.
1428 // Partial match. Next search needs to start from beginning of
1430 search_position_ = match_results[0].first - begin;
1434 // Next search can start with the new data.
1435 search_position_ = end - begin;
1438 bytes_to_read = std::min<std::size_t>(
1439 std::max<std::size_t>(512,
1440 buffers_.capacity() - buffers_.size()),
1441 std::min<std::size_t>(65536,
1442 buffers_.max_size() - buffers_.size()));
1446 // Check if we're done.
1447 if (!start && bytes_to_read == 0)
1450 // Start a new asynchronous read op_v1eration to obtain more data.
1451 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1452 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));
1454 buffers_.commit(bytes_transferred);
1455 if (ec || bytes_transferred == 0)
1459 const boost::system::error_code result_ec =
1460 (search_position_ == not_found)
1461 ? error::not_found : ec;
1463 const std::size_t result_n =
1464 (ec || search_position_ == not_found)
1465 ? 0 : search_position_;
1467 handler_(result_ec, result_n);
1472 AsyncReadStream& stream_;
1473 DynamicBuffer_v1 buffers_;
1476 std::size_t search_position_;
1477 ReadHandler handler_;
1480 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1481 typename RegEx, typename ReadHandler>
1482 inline void* asio_handler_allocate(std::size_t size,
1483 read_until_expr_op_v1<AsyncReadStream,
1484 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1486 return boost_asio_handler_alloc_helpers::allocate(
1487 size, this_handler->handler_);
1490 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1491 typename RegEx, typename ReadHandler>
1492 inline void asio_handler_deallocate(void* pointer, std::size_t size,
1493 read_until_expr_op_v1<AsyncReadStream,
1494 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1496 boost_asio_handler_alloc_helpers::deallocate(
1497 pointer, size, this_handler->handler_);
1500 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1501 typename RegEx, typename ReadHandler>
1502 inline bool asio_handler_is_continuation(
1503 read_until_expr_op_v1<AsyncReadStream,
1504 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1506 return this_handler->start_ == 0 ? true
1507 : boost_asio_handler_cont_helpers::is_continuation(
1508 this_handler->handler_);
1511 template <typename Function, typename AsyncReadStream,
1512 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1513 inline void asio_handler_invoke(Function& function,
1514 read_until_expr_op_v1<AsyncReadStream,
1515 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1517 boost_asio_handler_invoke_helpers::invoke(
1518 function, this_handler->handler_);
1521 template <typename Function, typename AsyncReadStream,
1522 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1523 inline void asio_handler_invoke(const Function& function,
1524 read_until_expr_op_v1<AsyncReadStream,
1525 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1527 boost_asio_handler_invoke_helpers::invoke(
1528 function, this_handler->handler_);
1531 template <typename AsyncReadStream>
1532 class initiate_async_read_until_expr_v1
1535 typedef typename AsyncReadStream::executor_type executor_type;
1537 explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)
1542 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1544 return stream_.get_executor();
1547 template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>
1548 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1549 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) const
1551 // If you get an error on the following line it means that your handler
1552 // does not meet the documented type requirements for a ReadHandler.
1553 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1555 non_const_lvalue<ReadHandler> handler2(handler);
1556 read_until_expr_op_v1<AsyncReadStream,
1557 typename decay<DynamicBuffer_v1>::type,
1558 RegEx, typename decay<ReadHandler>::type>(
1559 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1560 expr, handler2.value)(boost::system::error_code(), 0, 1);
1564 AsyncReadStream& stream_;
1566 } // namespace detail
1568 #if !defined(GENERATING_DOCUMENTATION)
1570 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1571 typename RegEx, typename ReadHandler, typename Allocator>
1572 struct associated_allocator<
1573 detail::read_until_expr_op_v1<AsyncReadStream,
1574 DynamicBuffer_v1, RegEx, ReadHandler>,
1577 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1580 const detail::read_until_expr_op_v1<AsyncReadStream,
1581 DynamicBuffer_v1, RegEx, ReadHandler>& h,
1582 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1584 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1588 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1589 typename RegEx, typename ReadHandler, typename Executor>
1590 struct associated_executor<
1591 detail::read_until_expr_op_v1<AsyncReadStream,
1592 DynamicBuffer_v1, RegEx, ReadHandler>,
1595 typedef typename associated_executor<ReadHandler, Executor>::type type;
1598 const detail::read_until_expr_op_v1<AsyncReadStream,
1599 DynamicBuffer_v1, RegEx, ReadHandler>& h,
1600 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1602 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1606 #endif // !defined(GENERATING_DOCUMENTATION)
1608 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1609 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1610 std::size_t)) ReadHandler>
1611 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1612 void (boost::system::error_code, std::size_t))
1613 async_read_until(AsyncReadStream& s,
1614 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1615 const boost::regex& expr,
1616 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1618 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1619 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1622 return async_initiate<ReadHandler,
1623 void (boost::system::error_code, std::size_t)>(
1624 detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
1625 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);
1628 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
1632 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1633 typename MatchCondition, typename ReadHandler>
1634 class read_until_match_op_v1
1637 template <typename BufferSequence>
1638 read_until_match_op_v1(AsyncReadStream& stream,
1639 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1640 MatchCondition match_condition, ReadHandler& handler)
1642 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1643 match_condition_(match_condition),
1645 search_position_(0),
1646 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1650 #if defined(BOOST_ASIO_HAS_MOVE)
1651 read_until_match_op_v1(const read_until_match_op_v1& other)
1652 : stream_(other.stream_),
1653 buffers_(other.buffers_),
1654 match_condition_(other.match_condition_),
1655 start_(other.start_),
1656 search_position_(other.search_position_),
1657 handler_(other.handler_)
1661 read_until_match_op_v1(read_until_match_op_v1&& other)
1662 : stream_(other.stream_),
1663 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1664 match_condition_(other.match_condition_),
1665 start_(other.start_),
1666 search_position_(other.search_position_),
1667 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1670 #endif // defined(BOOST_ASIO_HAS_MOVE)
1672 void operator()(const boost::system::error_code& ec,
1673 std::size_t bytes_transferred, int start = 0)
1675 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1676 std::size_t bytes_to_read;
1677 switch (start_ = start)
1683 // Determine the range of the data to be searched.
1684 typedef typename DynamicBuffer_v1::const_buffers_type
1686 typedef buffers_iterator<buffers_type> iterator;
1687 buffers_type data_buffers = buffers_.data();
1688 iterator begin = iterator::begin(data_buffers);
1689 iterator start_pos = begin + search_position_;
1690 iterator end = iterator::end(data_buffers);
1692 // Look for a match.
1693 std::pair<iterator, bool> result = match_condition_(start_pos, end);
1696 // Full match. We're done.
1697 search_position_ = result.first - begin;
1701 // No match yet. Check if buffer is full.
1702 else if (buffers_.size() == buffers_.max_size())
1704 search_position_ = not_found;
1708 // Need to read some more data.
1711 if (result.first != end)
1713 // Partial match. Next search needs to start from beginning of
1715 search_position_ = result.first - begin;
1719 // Next search can start with the new data.
1720 search_position_ = end - begin;
1723 bytes_to_read = std::min<std::size_t>(
1724 std::max<std::size_t>(512,
1725 buffers_.capacity() - buffers_.size()),
1726 std::min<std::size_t>(65536,
1727 buffers_.max_size() - buffers_.size()));
1731 // Check if we're done.
1732 if (!start && bytes_to_read == 0)
1735 // Start a new asynchronous read op_v1eration to obtain more data.
1736 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1737 BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this));
1739 buffers_.commit(bytes_transferred);
1740 if (ec || bytes_transferred == 0)
1744 const boost::system::error_code result_ec =
1745 (search_position_ == not_found)
1746 ? error::not_found : ec;
1748 const std::size_t result_n =
1749 (ec || search_position_ == not_found)
1750 ? 0 : search_position_;
1752 handler_(result_ec, result_n);
1757 AsyncReadStream& stream_;
1758 DynamicBuffer_v1 buffers_;
1759 MatchCondition match_condition_;
1761 std::size_t search_position_;
1762 ReadHandler handler_;
1765 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1766 typename MatchCondition, typename ReadHandler>
1767 inline void* asio_handler_allocate(std::size_t size,
1768 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1769 MatchCondition, ReadHandler>* this_handler)
1771 return boost_asio_handler_alloc_helpers::allocate(
1772 size, this_handler->handler_);
1775 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1776 typename MatchCondition, typename ReadHandler>
1777 inline void asio_handler_deallocate(void* pointer, std::size_t size,
1778 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1779 MatchCondition, ReadHandler>* this_handler)
1781 boost_asio_handler_alloc_helpers::deallocate(
1782 pointer, size, this_handler->handler_);
1785 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1786 typename MatchCondition, typename ReadHandler>
1787 inline bool asio_handler_is_continuation(
1788 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1789 MatchCondition, ReadHandler>* this_handler)
1791 return this_handler->start_ == 0 ? true
1792 : boost_asio_handler_cont_helpers::is_continuation(
1793 this_handler->handler_);
1796 template <typename Function, typename AsyncReadStream,
1797 typename DynamicBuffer_v1, typename MatchCondition,
1798 typename ReadHandler>
1799 inline void asio_handler_invoke(Function& function,
1800 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1801 MatchCondition, ReadHandler>* this_handler)
1803 boost_asio_handler_invoke_helpers::invoke(
1804 function, this_handler->handler_);
1807 template <typename Function, typename AsyncReadStream,
1808 typename DynamicBuffer_v1, typename MatchCondition,
1809 typename ReadHandler>
1810 inline void asio_handler_invoke(const Function& function,
1811 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1812 MatchCondition, ReadHandler>* this_handler)
1814 boost_asio_handler_invoke_helpers::invoke(
1815 function, this_handler->handler_);
1818 template <typename AsyncReadStream>
1819 class initiate_async_read_until_match_v1
1822 typedef typename AsyncReadStream::executor_type executor_type;
1824 explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)
1829 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1831 return stream_.get_executor();
1834 template <typename ReadHandler,
1835 typename DynamicBuffer_v1, typename MatchCondition>
1836 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1837 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1838 MatchCondition match_condition) const
1840 // If you get an error on the following line it means that your handler
1841 // does not meet the documented type requirements for a ReadHandler.
1842 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1844 non_const_lvalue<ReadHandler> handler2(handler);
1845 read_until_match_op_v1<AsyncReadStream,
1846 typename decay<DynamicBuffer_v1>::type,
1847 MatchCondition, typename decay<ReadHandler>::type>(
1848 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1849 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
1853 AsyncReadStream& stream_;
1855 } // namespace detail
1857 #if !defined(GENERATING_DOCUMENTATION)
1859 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1860 typename MatchCondition, typename ReadHandler, typename Allocator>
1861 struct associated_allocator<
1862 detail::read_until_match_op_v1<AsyncReadStream,
1863 DynamicBuffer_v1, MatchCondition, ReadHandler>,
1866 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1869 const detail::read_until_match_op_v1<AsyncReadStream,
1870 DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
1871 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1873 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1877 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1878 typename MatchCondition, typename ReadHandler, typename Executor>
1879 struct associated_executor<
1880 detail::read_until_match_op_v1<AsyncReadStream,
1881 DynamicBuffer_v1, MatchCondition, ReadHandler>,
1884 typedef typename associated_executor<ReadHandler, Executor>::type type;
1887 const detail::read_until_match_op_v1<AsyncReadStream,
1888 DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
1889 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1891 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1895 #endif // !defined(GENERATING_DOCUMENTATION)
1897 template <typename AsyncReadStream,
1898 typename DynamicBuffer_v1, typename MatchCondition,
1899 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1900 std::size_t)) ReadHandler>
1901 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1902 void (boost::system::error_code, std::size_t))
1903 async_read_until(AsyncReadStream& s,
1904 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1905 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1907 is_match_condition<MatchCondition>::value
1908 && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1909 && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1912 return async_initiate<ReadHandler,
1913 void (boost::system::error_code, std::size_t)>(
1914 detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), handler,
1915 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);
1918 #if !defined(BOOST_ASIO_NO_IOSTREAM)
1920 template <typename AsyncReadStream, typename Allocator,
1921 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1922 std::size_t)) ReadHandler>
1923 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1924 void (boost::system::error_code, std::size_t))
1925 async_read_until(AsyncReadStream& s,
1926 boost::asio::basic_streambuf<Allocator>& b,
1927 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
1929 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
1930 delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1933 template <typename AsyncReadStream, typename Allocator,
1934 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1935 std::size_t)) ReadHandler>
1936 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1937 void (boost::system::error_code, std::size_t))
1938 async_read_until(AsyncReadStream& s,
1939 boost::asio::basic_streambuf<Allocator>& b,
1940 BOOST_ASIO_STRING_VIEW_PARAM delim,
1941 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
1943 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
1944 delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1947 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
1949 template <typename AsyncReadStream, typename Allocator,
1950 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1951 std::size_t)) ReadHandler>
1952 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1953 void (boost::system::error_code, std::size_t))
1954 async_read_until(AsyncReadStream& s,
1955 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
1956 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
1958 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
1959 expr, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1962 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
1964 template <typename AsyncReadStream, typename Allocator, typename MatchCondition,
1965 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1966 std::size_t)) ReadHandler>
1967 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1968 void (boost::system::error_code, std::size_t))
1969 async_read_until(AsyncReadStream& s,
1970 boost::asio::basic_streambuf<Allocator>& b,
1971 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1972 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
1974 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
1975 match_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1978 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
1979 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
1980 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1984 template <typename AsyncReadStream,
1985 typename DynamicBuffer_v2, typename ReadHandler>
1986 class read_until_delim_op_v2
1989 template <typename BufferSequence>
1990 read_until_delim_op_v2(AsyncReadStream& stream,
1991 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1992 char delim, ReadHandler& handler)
1994 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1997 search_position_(0),
1999 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2003 #if defined(BOOST_ASIO_HAS_MOVE)
2004 read_until_delim_op_v2(const read_until_delim_op_v2& other)
2005 : stream_(other.stream_),
2006 buffers_(other.buffers_),
2007 delim_(other.delim_),
2008 start_(other.start_),
2009 search_position_(other.search_position_),
2010 bytes_to_read_(other.bytes_to_read_),
2011 handler_(other.handler_)
2015 read_until_delim_op_v2(read_until_delim_op_v2&& other)
2016 : stream_(other.stream_),
2017 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2018 delim_(other.delim_),
2019 start_(other.start_),
2020 search_position_(other.search_position_),
2021 bytes_to_read_(other.bytes_to_read_),
2022 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2025 #endif // defined(BOOST_ASIO_HAS_MOVE)
2027 void operator()(const boost::system::error_code& ec,
2028 std::size_t bytes_transferred, int start = 0)
2030 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2032 switch (start_ = start)
2038 // Determine the range of the data to be searched.
2039 typedef typename DynamicBuffer_v2::const_buffers_type
2041 typedef buffers_iterator<buffers_type> iterator;
2042 buffers_type data_buffers =
2043 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2044 0, buffers_.size());
2045 iterator begin = iterator::begin(data_buffers);
2046 iterator start_pos = begin + search_position_;
2047 iterator end = iterator::end(data_buffers);
2049 // Look for a match.
2050 iterator iter = std::find(start_pos, end, delim_);
2053 // Found a match. We're done.
2054 search_position_ = iter - begin + 1;
2058 // No match yet. Check if buffer is full.
2059 else if (buffers_.size() == buffers_.max_size())
2061 search_position_ = not_found;
2065 // Need to read some more data.
2068 // Next search can start with the new data.
2069 search_position_ = end - begin;
2070 bytes_to_read_ = std::min<std::size_t>(
2071 std::max<std::size_t>(512,
2072 buffers_.capacity() - buffers_.size()),
2073 std::min<std::size_t>(65536,
2074 buffers_.max_size() - buffers_.size()));
2078 // Check if we're done.
2079 if (!start && bytes_to_read_ == 0)
2082 // Start a new asynchronous read op_v2eration to obtain more data.
2083 pos = buffers_.size();
2084 buffers_.grow(bytes_to_read_);
2085 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2086 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));
2088 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2089 if (ec || bytes_transferred == 0)
2093 const boost::system::error_code result_ec =
2094 (search_position_ == not_found)
2095 ? error::not_found : ec;
2097 const std::size_t result_n =
2098 (ec || search_position_ == not_found)
2099 ? 0 : search_position_;
2101 handler_(result_ec, result_n);
2106 AsyncReadStream& stream_;
2107 DynamicBuffer_v2 buffers_;
2110 std::size_t search_position_;
2111 std::size_t bytes_to_read_;
2112 ReadHandler handler_;
2115 template <typename AsyncReadStream,
2116 typename DynamicBuffer_v2, typename ReadHandler>
2117 inline void* asio_handler_allocate(std::size_t size,
2118 read_until_delim_op_v2<AsyncReadStream,
2119 DynamicBuffer_v2, ReadHandler>* this_handler)
2121 return boost_asio_handler_alloc_helpers::allocate(
2122 size, this_handler->handler_);
2125 template <typename AsyncReadStream,
2126 typename DynamicBuffer_v2, typename ReadHandler>
2127 inline void asio_handler_deallocate(void* pointer, std::size_t size,
2128 read_until_delim_op_v2<AsyncReadStream,
2129 DynamicBuffer_v2, ReadHandler>* this_handler)
2131 boost_asio_handler_alloc_helpers::deallocate(
2132 pointer, size, this_handler->handler_);
2135 template <typename AsyncReadStream,
2136 typename DynamicBuffer_v2, typename ReadHandler>
2137 inline bool asio_handler_is_continuation(
2138 read_until_delim_op_v2<AsyncReadStream,
2139 DynamicBuffer_v2, ReadHandler>* this_handler)
2141 return this_handler->start_ == 0 ? true
2142 : boost_asio_handler_cont_helpers::is_continuation(
2143 this_handler->handler_);
2146 template <typename Function, typename AsyncReadStream,
2147 typename DynamicBuffer_v2, typename ReadHandler>
2148 inline void asio_handler_invoke(Function& function,
2149 read_until_delim_op_v2<AsyncReadStream,
2150 DynamicBuffer_v2, ReadHandler>* this_handler)
2152 boost_asio_handler_invoke_helpers::invoke(
2153 function, this_handler->handler_);
2156 template <typename Function, typename AsyncReadStream,
2157 typename DynamicBuffer_v2, typename ReadHandler>
2158 inline void asio_handler_invoke(const Function& function,
2159 read_until_delim_op_v2<AsyncReadStream,
2160 DynamicBuffer_v2, ReadHandler>* this_handler)
2162 boost_asio_handler_invoke_helpers::invoke(
2163 function, this_handler->handler_);
2166 template <typename AsyncReadStream>
2167 class initiate_async_read_until_delim_v2
2170 typedef typename AsyncReadStream::executor_type executor_type;
2172 explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)
2177 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2179 return stream_.get_executor();
2182 template <typename ReadHandler, typename DynamicBuffer_v2>
2183 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2184 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) const
2186 // If you get an error on the following line it means that your handler
2187 // does not meet the documented type requirements for a ReadHandler.
2188 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2190 non_const_lvalue<ReadHandler> handler2(handler);
2191 read_until_delim_op_v2<AsyncReadStream,
2192 typename decay<DynamicBuffer_v2>::type,
2193 typename decay<ReadHandler>::type>(
2194 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2195 delim, handler2.value)(boost::system::error_code(), 0, 1);
2199 AsyncReadStream& stream_;
2201 } // namespace detail
2203 #if !defined(GENERATING_DOCUMENTATION)
2205 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2206 typename ReadHandler, typename Allocator>
2207 struct associated_allocator<
2208 detail::read_until_delim_op_v2<AsyncReadStream,
2209 DynamicBuffer_v2, ReadHandler>,
2212 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2215 const detail::read_until_delim_op_v2<AsyncReadStream,
2216 DynamicBuffer_v2, ReadHandler>& h,
2217 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
2219 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
2223 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2224 typename ReadHandler, typename Executor>
2225 struct associated_executor<
2226 detail::read_until_delim_op_v2<AsyncReadStream,
2227 DynamicBuffer_v2, ReadHandler>,
2230 typedef typename associated_executor<ReadHandler, Executor>::type type;
2233 const detail::read_until_delim_op_v2<AsyncReadStream,
2234 DynamicBuffer_v2, ReadHandler>& h,
2235 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2237 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2241 #endif // !defined(GENERATING_DOCUMENTATION)
2243 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2244 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2245 std::size_t)) ReadHandler>
2246 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2247 void (boost::system::error_code, std::size_t))
2248 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
2249 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2251 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2254 return async_initiate<ReadHandler,
2255 void (boost::system::error_code, std::size_t)>(
2256 detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),
2257 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);
2262 template <typename AsyncReadStream,
2263 typename DynamicBuffer_v2, typename ReadHandler>
2264 class read_until_delim_string_op_v2
2267 template <typename BufferSequence>
2268 read_until_delim_string_op_v2(AsyncReadStream& stream,
2269 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2270 const std::string& delim, ReadHandler& handler)
2272 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2275 search_position_(0),
2277 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2281 #if defined(BOOST_ASIO_HAS_MOVE)
2282 read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
2283 : stream_(other.stream_),
2284 buffers_(other.buffers_),
2285 delim_(other.delim_),
2286 start_(other.start_),
2287 search_position_(other.search_position_),
2288 bytes_to_read_(other.bytes_to_read_),
2289 handler_(other.handler_)
2293 read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
2294 : stream_(other.stream_),
2295 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2296 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
2297 start_(other.start_),
2298 search_position_(other.search_position_),
2299 bytes_to_read_(other.bytes_to_read_),
2300 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2303 #endif // defined(BOOST_ASIO_HAS_MOVE)
2305 void operator()(const boost::system::error_code& ec,
2306 std::size_t bytes_transferred, int start = 0)
2308 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2310 switch (start_ = start)
2316 // Determine the range of the data to be searched.
2317 typedef typename DynamicBuffer_v2::const_buffers_type
2319 typedef buffers_iterator<buffers_type> iterator;
2320 buffers_type data_buffers =
2321 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2322 0, buffers_.size());
2323 iterator begin = iterator::begin(data_buffers);
2324 iterator start_pos = begin + search_position_;
2325 iterator end = iterator::end(data_buffers);
2327 // Look for a match.
2328 std::pair<iterator, bool> result = detail::partial_search(
2329 start_pos, end, delim_.begin(), delim_.end());
2330 if (result.first != end && result.second)
2332 // Full match. We're done.
2333 search_position_ = result.first - begin + delim_.length();
2337 // No match yet. Check if buffer is full.
2338 else if (buffers_.size() == buffers_.max_size())
2340 search_position_ = not_found;
2344 // Need to read some more data.
2347 if (result.first != end)
2349 // Partial match. Next search needs to start from beginning of
2351 search_position_ = result.first - begin;
2355 // Next search can start with the new data.
2356 search_position_ = end - begin;
2359 bytes_to_read_ = std::min<std::size_t>(
2360 std::max<std::size_t>(512,
2361 buffers_.capacity() - buffers_.size()),
2362 std::min<std::size_t>(65536,
2363 buffers_.max_size() - buffers_.size()));
2367 // Check if we're done.
2368 if (!start && bytes_to_read_ == 0)
2371 // Start a new asynchronous read op_v2eration to obtain more data.
2372 pos = buffers_.size();
2373 buffers_.grow(bytes_to_read_);
2374 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2375 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));
2377 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2378 if (ec || bytes_transferred == 0)
2382 const boost::system::error_code result_ec =
2383 (search_position_ == not_found)
2384 ? error::not_found : ec;
2386 const std::size_t result_n =
2387 (ec || search_position_ == not_found)
2388 ? 0 : search_position_;
2390 handler_(result_ec, result_n);
2395 AsyncReadStream& stream_;
2396 DynamicBuffer_v2 buffers_;
2399 std::size_t search_position_;
2400 std::size_t bytes_to_read_;
2401 ReadHandler handler_;
2404 template <typename AsyncReadStream,
2405 typename DynamicBuffer_v2, typename ReadHandler>
2406 inline void* asio_handler_allocate(std::size_t size,
2407 read_until_delim_string_op_v2<AsyncReadStream,
2408 DynamicBuffer_v2, ReadHandler>* this_handler)
2410 return boost_asio_handler_alloc_helpers::allocate(
2411 size, this_handler->handler_);
2414 template <typename AsyncReadStream,
2415 typename DynamicBuffer_v2, typename ReadHandler>
2416 inline void asio_handler_deallocate(void* pointer, std::size_t size,
2417 read_until_delim_string_op_v2<AsyncReadStream,
2418 DynamicBuffer_v2, ReadHandler>* this_handler)
2420 boost_asio_handler_alloc_helpers::deallocate(
2421 pointer, size, this_handler->handler_);
2424 template <typename AsyncReadStream,
2425 typename DynamicBuffer_v2, typename ReadHandler>
2426 inline bool asio_handler_is_continuation(
2427 read_until_delim_string_op_v2<AsyncReadStream,
2428 DynamicBuffer_v2, ReadHandler>* this_handler)
2430 return this_handler->start_ == 0 ? true
2431 : boost_asio_handler_cont_helpers::is_continuation(
2432 this_handler->handler_);
2435 template <typename Function, typename AsyncReadStream,
2436 typename DynamicBuffer_v2, typename ReadHandler>
2437 inline void asio_handler_invoke(Function& function,
2438 read_until_delim_string_op_v2<AsyncReadStream,
2439 DynamicBuffer_v2, ReadHandler>* this_handler)
2441 boost_asio_handler_invoke_helpers::invoke(
2442 function, this_handler->handler_);
2445 template <typename Function, typename AsyncReadStream,
2446 typename DynamicBuffer_v2, typename ReadHandler>
2447 inline void asio_handler_invoke(const Function& function,
2448 read_until_delim_string_op_v2<AsyncReadStream,
2449 DynamicBuffer_v2, ReadHandler>* this_handler)
2451 boost_asio_handler_invoke_helpers::invoke(
2452 function, this_handler->handler_);
2455 template <typename AsyncReadStream>
2456 class initiate_async_read_until_delim_string_v2
2459 typedef typename AsyncReadStream::executor_type executor_type;
2461 explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)
2466 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2468 return stream_.get_executor();
2471 template <typename ReadHandler, typename DynamicBuffer_v2>
2472 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2473 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2474 const std::string& delim) const
2476 // If you get an error on the following line it means that your handler
2477 // does not meet the documented type requirements for a ReadHandler.
2478 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2480 non_const_lvalue<ReadHandler> handler2(handler);
2481 read_until_delim_string_op_v2<AsyncReadStream,
2482 typename decay<DynamicBuffer_v2>::type,
2483 typename decay<ReadHandler>::type>(
2484 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2485 delim, handler2.value)(boost::system::error_code(), 0, 1);
2489 AsyncReadStream& stream_;
2491 } // namespace detail
2493 #if !defined(GENERATING_DOCUMENTATION)
2495 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2496 typename ReadHandler, typename Allocator>
2497 struct associated_allocator<
2498 detail::read_until_delim_string_op_v2<AsyncReadStream,
2499 DynamicBuffer_v2, ReadHandler>,
2502 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2505 const detail::read_until_delim_string_op_v2<AsyncReadStream,
2506 DynamicBuffer_v2, ReadHandler>& h,
2507 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
2509 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
2513 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2514 typename ReadHandler, typename Executor>
2515 struct associated_executor<
2516 detail::read_until_delim_string_op_v2<AsyncReadStream,
2517 DynamicBuffer_v2, ReadHandler>,
2520 typedef typename associated_executor<ReadHandler, Executor>::type type;
2523 const detail::read_until_delim_string_op_v2<AsyncReadStream,
2524 DynamicBuffer_v2, ReadHandler>& h,
2525 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2527 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2531 #endif // !defined(GENERATING_DOCUMENTATION)
2533 template <typename AsyncReadStream,
2534 typename DynamicBuffer_v2,
2535 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2536 std::size_t)) ReadHandler>
2537 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2538 void (boost::system::error_code, std::size_t))
2539 async_read_until(AsyncReadStream& s,
2540 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
2541 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2543 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2546 return async_initiate<ReadHandler,
2547 void (boost::system::error_code, std::size_t)>(
2548 detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),
2549 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2550 static_cast<std::string>(delim));
2553 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
2554 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
2558 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2559 typename RegEx, typename ReadHandler>
2560 class read_until_expr_op_v2
2563 template <typename BufferSequence>
2564 read_until_expr_op_v2(AsyncReadStream& stream,
2565 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2566 const boost::regex& expr, ReadHandler& handler)
2568 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2571 search_position_(0),
2573 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2577 #if defined(BOOST_ASIO_HAS_MOVE)
2578 read_until_expr_op_v2(const read_until_expr_op_v2& other)
2579 : stream_(other.stream_),
2580 buffers_(other.buffers_),
2582 start_(other.start_),
2583 search_position_(other.search_position_),
2584 bytes_to_read_(other.bytes_to_read_),
2585 handler_(other.handler_)
2589 read_until_expr_op_v2(read_until_expr_op_v2&& other)
2590 : stream_(other.stream_),
2591 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2593 start_(other.start_),
2594 search_position_(other.search_position_),
2595 bytes_to_read_(other.bytes_to_read_),
2596 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2599 #endif // defined(BOOST_ASIO_HAS_MOVE)
2601 void operator()(const boost::system::error_code& ec,
2602 std::size_t bytes_transferred, int start = 0)
2604 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2606 switch (start_ = start)
2612 // Determine the range of the data to be searched.
2613 typedef typename DynamicBuffer_v2::const_buffers_type
2615 typedef buffers_iterator<buffers_type> iterator;
2616 buffers_type data_buffers =
2617 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2618 0, buffers_.size());
2619 iterator begin = iterator::begin(data_buffers);
2620 iterator start_pos = begin + search_position_;
2621 iterator end = iterator::end(data_buffers);
2623 // Look for a match.
2624 boost::match_results<iterator,
2625 typename std::vector<boost::sub_match<iterator> >::allocator_type>
2627 bool match = regex_search(start_pos, end, match_results, expr_,
2628 boost::match_default | boost::match_partial);
2629 if (match && match_results[0].matched)
2631 // Full match. We're done.
2632 search_position_ = match_results[0].second - begin;
2636 // No match yet. Check if buffer is full.
2637 else if (buffers_.size() == buffers_.max_size())
2639 search_position_ = not_found;
2643 // Need to read some more data.
2648 // Partial match. Next search needs to start from beginning of
2650 search_position_ = match_results[0].first - begin;
2654 // Next search can start with the new data.
2655 search_position_ = end - begin;
2658 bytes_to_read_ = std::min<std::size_t>(
2659 std::max<std::size_t>(512,
2660 buffers_.capacity() - buffers_.size()),
2661 std::min<std::size_t>(65536,
2662 buffers_.max_size() - buffers_.size()));
2666 // Check if we're done.
2667 if (!start && bytes_to_read_ == 0)
2670 // Start a new asynchronous read op_v2eration to obtain more data.
2671 pos = buffers_.size();
2672 buffers_.grow(bytes_to_read_);
2673 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2674 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));
2676 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2677 if (ec || bytes_transferred == 0)
2681 const boost::system::error_code result_ec =
2682 (search_position_ == not_found)
2683 ? error::not_found : ec;
2685 const std::size_t result_n =
2686 (ec || search_position_ == not_found)
2687 ? 0 : search_position_;
2689 handler_(result_ec, result_n);
2694 AsyncReadStream& stream_;
2695 DynamicBuffer_v2 buffers_;
2698 std::size_t search_position_;
2699 std::size_t bytes_to_read_;
2700 ReadHandler handler_;
2703 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2704 typename RegEx, typename ReadHandler>
2705 inline void* asio_handler_allocate(std::size_t size,
2706 read_until_expr_op_v2<AsyncReadStream,
2707 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2709 return boost_asio_handler_alloc_helpers::allocate(
2710 size, this_handler->handler_);
2713 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2714 typename RegEx, typename ReadHandler>
2715 inline void asio_handler_deallocate(void* pointer, std::size_t size,
2716 read_until_expr_op_v2<AsyncReadStream,
2717 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2719 boost_asio_handler_alloc_helpers::deallocate(
2720 pointer, size, this_handler->handler_);
2723 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2724 typename RegEx, typename ReadHandler>
2725 inline bool asio_handler_is_continuation(
2726 read_until_expr_op_v2<AsyncReadStream,
2727 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2729 return this_handler->start_ == 0 ? true
2730 : boost_asio_handler_cont_helpers::is_continuation(
2731 this_handler->handler_);
2734 template <typename Function, typename AsyncReadStream,
2735 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2736 inline void asio_handler_invoke(Function& function,
2737 read_until_expr_op_v2<AsyncReadStream,
2738 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2740 boost_asio_handler_invoke_helpers::invoke(
2741 function, this_handler->handler_);
2744 template <typename Function, typename AsyncReadStream,
2745 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2746 inline void asio_handler_invoke(const Function& function,
2747 read_until_expr_op_v2<AsyncReadStream,
2748 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2750 boost_asio_handler_invoke_helpers::invoke(
2751 function, this_handler->handler_);
2754 template <typename AsyncReadStream>
2755 class initiate_async_read_until_expr_v2
2758 typedef typename AsyncReadStream::executor_type executor_type;
2760 explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)
2765 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2767 return stream_.get_executor();
2770 template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>
2771 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2772 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2773 const RegEx& expr) const
2775 // If you get an error on the following line it means that your handler
2776 // does not meet the documented type requirements for a ReadHandler.
2777 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2779 non_const_lvalue<ReadHandler> handler2(handler);
2780 read_until_expr_op_v2<AsyncReadStream,
2781 typename decay<DynamicBuffer_v2>::type,
2782 RegEx, typename decay<ReadHandler>::type>(
2783 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2784 expr, handler2.value)(boost::system::error_code(), 0, 1);
2788 AsyncReadStream& stream_;
2790 } // namespace detail
2792 #if !defined(GENERATING_DOCUMENTATION)
2794 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2795 typename RegEx, typename ReadHandler, typename Allocator>
2796 struct associated_allocator<
2797 detail::read_until_expr_op_v2<AsyncReadStream,
2798 DynamicBuffer_v2, RegEx, ReadHandler>,
2801 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2804 const detail::read_until_expr_op_v2<AsyncReadStream,
2805 DynamicBuffer_v2, RegEx, ReadHandler>& h,
2806 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
2808 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
2812 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2813 typename RegEx, typename ReadHandler, typename Executor>
2814 struct associated_executor<
2815 detail::read_until_expr_op_v2<AsyncReadStream,
2816 DynamicBuffer_v2, RegEx, ReadHandler>,
2819 typedef typename associated_executor<ReadHandler, Executor>::type type;
2822 const detail::read_until_expr_op_v2<AsyncReadStream,
2823 DynamicBuffer_v2, RegEx, ReadHandler>& h,
2824 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2826 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2830 #endif // !defined(GENERATING_DOCUMENTATION)
2832 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2833 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2834 std::size_t)) ReadHandler>
2835 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2836 void (boost::system::error_code, std::size_t))
2837 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
2838 const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2840 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2843 return async_initiate<ReadHandler,
2844 void (boost::system::error_code, std::size_t)>(
2845 detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),
2846 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);
2849 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
2853 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2854 typename MatchCondition, typename ReadHandler>
2855 class read_until_match_op_v2
2858 template <typename BufferSequence>
2859 read_until_match_op_v2(AsyncReadStream& stream,
2860 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2861 MatchCondition match_condition, ReadHandler& handler)
2863 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2864 match_condition_(match_condition),
2866 search_position_(0),
2868 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2872 #if defined(BOOST_ASIO_HAS_MOVE)
2873 read_until_match_op_v2(const read_until_match_op_v2& other)
2874 : stream_(other.stream_),
2875 buffers_(other.buffers_),
2876 match_condition_(other.match_condition_),
2877 start_(other.start_),
2878 search_position_(other.search_position_),
2879 bytes_to_read_(other.bytes_to_read_),
2880 handler_(other.handler_)
2884 read_until_match_op_v2(read_until_match_op_v2&& other)
2885 : stream_(other.stream_),
2886 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2887 match_condition_(other.match_condition_),
2888 start_(other.start_),
2889 search_position_(other.search_position_),
2890 bytes_to_read_(other.bytes_to_read_),
2891 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2894 #endif // defined(BOOST_ASIO_HAS_MOVE)
2896 void operator()(const boost::system::error_code& ec,
2897 std::size_t bytes_transferred, int start = 0)
2899 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2901 switch (start_ = start)
2907 // Determine the range of the data to be searched.
2908 typedef typename DynamicBuffer_v2::const_buffers_type
2910 typedef buffers_iterator<buffers_type> iterator;
2911 buffers_type data_buffers =
2912 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2913 0, buffers_.size());
2914 iterator begin = iterator::begin(data_buffers);
2915 iterator start_pos = begin + search_position_;
2916 iterator end = iterator::end(data_buffers);
2918 // Look for a match.
2919 std::pair<iterator, bool> result = match_condition_(start_pos, end);
2922 // Full match. We're done.
2923 search_position_ = result.first - begin;
2927 // No match yet. Check if buffer is full.
2928 else if (buffers_.size() == buffers_.max_size())
2930 search_position_ = not_found;
2934 // Need to read some more data.
2937 if (result.first != end)
2939 // Partial match. Next search needs to start from beginning of
2941 search_position_ = result.first - begin;
2945 // Next search can start with the new data.
2946 search_position_ = end - begin;
2949 bytes_to_read_ = std::min<std::size_t>(
2950 std::max<std::size_t>(512,
2951 buffers_.capacity() - buffers_.size()),
2952 std::min<std::size_t>(65536,
2953 buffers_.max_size() - buffers_.size()));
2957 // Check if we're done.
2958 if (!start && bytes_to_read_ == 0)
2961 // Start a new asynchronous read op_v2eration to obtain more data.
2962 pos = buffers_.size();
2963 buffers_.grow(bytes_to_read_);
2964 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2965 BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this));
2967 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2968 if (ec || bytes_transferred == 0)
2972 const boost::system::error_code result_ec =
2973 (search_position_ == not_found)
2974 ? error::not_found : ec;
2976 const std::size_t result_n =
2977 (ec || search_position_ == not_found)
2978 ? 0 : search_position_;
2980 handler_(result_ec, result_n);
2985 AsyncReadStream& stream_;
2986 DynamicBuffer_v2 buffers_;
2987 MatchCondition match_condition_;
2989 std::size_t search_position_;
2990 std::size_t bytes_to_read_;
2991 ReadHandler handler_;
2994 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2995 typename MatchCondition, typename ReadHandler>
2996 inline void* asio_handler_allocate(std::size_t size,
2997 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
2998 MatchCondition, ReadHandler>* this_handler)
3000 return boost_asio_handler_alloc_helpers::allocate(
3001 size, this_handler->handler_);
3004 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3005 typename MatchCondition, typename ReadHandler>
3006 inline void asio_handler_deallocate(void* pointer, std::size_t size,
3007 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3008 MatchCondition, ReadHandler>* this_handler)
3010 boost_asio_handler_alloc_helpers::deallocate(
3011 pointer, size, this_handler->handler_);
3014 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3015 typename MatchCondition, typename ReadHandler>
3016 inline bool asio_handler_is_continuation(
3017 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3018 MatchCondition, ReadHandler>* this_handler)
3020 return this_handler->start_ == 0 ? true
3021 : boost_asio_handler_cont_helpers::is_continuation(
3022 this_handler->handler_);
3025 template <typename Function, typename AsyncReadStream,
3026 typename DynamicBuffer_v2, typename MatchCondition,
3027 typename ReadHandler>
3028 inline void asio_handler_invoke(Function& function,
3029 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3030 MatchCondition, ReadHandler>* this_handler)
3032 boost_asio_handler_invoke_helpers::invoke(
3033 function, this_handler->handler_);
3036 template <typename Function, typename AsyncReadStream,
3037 typename DynamicBuffer_v2, typename MatchCondition,
3038 typename ReadHandler>
3039 inline void asio_handler_invoke(const Function& function,
3040 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3041 MatchCondition, ReadHandler>* this_handler)
3043 boost_asio_handler_invoke_helpers::invoke(
3044 function, this_handler->handler_);
3047 template <typename AsyncReadStream>
3048 class initiate_async_read_until_match_v2
3051 typedef typename AsyncReadStream::executor_type executor_type;
3053 explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)
3058 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
3060 return stream_.get_executor();
3063 template <typename ReadHandler,
3064 typename DynamicBuffer_v2, typename MatchCondition>
3065 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3066 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
3067 MatchCondition match_condition) const
3069 // If you get an error on the following line it means that your handler
3070 // does not meet the documented type requirements for a ReadHandler.
3071 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
3073 non_const_lvalue<ReadHandler> handler2(handler);
3074 read_until_match_op_v2<AsyncReadStream,
3075 typename decay<DynamicBuffer_v2>::type,
3076 MatchCondition, typename decay<ReadHandler>::type>(
3077 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
3078 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
3082 AsyncReadStream& stream_;
3084 } // namespace detail
3086 #if !defined(GENERATING_DOCUMENTATION)
3088 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3089 typename MatchCondition, typename ReadHandler, typename Allocator>
3090 struct associated_allocator<
3091 detail::read_until_match_op_v2<AsyncReadStream,
3092 DynamicBuffer_v2, MatchCondition, ReadHandler>,
3095 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
3098 const detail::read_until_match_op_v2<AsyncReadStream,
3099 DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
3100 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
3102 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
3106 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3107 typename MatchCondition, typename ReadHandler, typename Executor>
3108 struct associated_executor<
3109 detail::read_until_match_op_v2<AsyncReadStream,
3110 DynamicBuffer_v2, MatchCondition, ReadHandler>,
3113 typedef typename associated_executor<ReadHandler, Executor>::type type;
3116 const detail::read_until_match_op_v2<AsyncReadStream,
3117 DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
3118 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
3120 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
3124 #endif // !defined(GENERATING_DOCUMENTATION)
3126 template <typename AsyncReadStream,
3127 typename DynamicBuffer_v2, typename MatchCondition,
3128 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
3129 std::size_t)) ReadHandler>
3130 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
3131 void (boost::system::error_code, std::size_t))
3132 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
3133 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3135 is_match_condition<MatchCondition>::value
3136 && is_dynamic_buffer_v2<DynamicBuffer_v2>::value
3139 return async_initiate<ReadHandler,
3140 void (boost::system::error_code, std::size_t)>(
3141 detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), handler,
3142 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);
3145 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
3148 } // namespace boost
3150 #include <boost/asio/detail/pop_options.hpp>
3152 #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP