5 // Copyright (c) 2003-2022 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/associator.hpp>
23 #include <boost/asio/buffer.hpp>
24 #include <boost/asio/buffers_iterator.hpp>
25 #include <boost/asio/detail/base_from_cancellation_state.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_tracking.hpp>
31 #include <boost/asio/detail/handler_type_requirements.hpp>
32 #include <boost/asio/detail/limits.hpp>
33 #include <boost/asio/detail/non_const_lvalue.hpp>
34 #include <boost/asio/detail/throw_error.hpp>
36 #include <boost/asio/detail/push_options.hpp>
43 // Algorithm that finds a subsequence of equal values in a sequence. Returns
44 // (iterator,true) if a full match was found, in which case the iterator
45 // points to the beginning of the match. Returns (iterator,false) if a
46 // partial match was found at the end of the first sequence, in which case
47 // the iterator points to the beginning of the partial match. Returns
48 // (last1,false) if no full or partial match was found.
49 template <typename Iterator1, typename Iterator2>
50 std::pair<Iterator1, bool> partial_search(
51 Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
53 for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
55 Iterator1 test_iter1 = iter1;
56 Iterator2 test_iter2 = first2;
57 for (;; ++test_iter1, ++test_iter2)
59 if (test_iter2 == last2)
60 return std::make_pair(iter1, true);
61 if (test_iter1 == last1)
63 if (test_iter2 != first2)
64 return std::make_pair(iter1, false);
68 if (*test_iter1 != *test_iter2)
72 return std::make_pair(last1, false);
76 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
78 template <typename SyncReadStream, typename DynamicBuffer_v1>
79 inline std::size_t read_until(SyncReadStream& s,
80 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,
82 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
85 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
88 boost::system::error_code ec;
89 std::size_t bytes_transferred = read_until(s,
90 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
91 boost::asio::detail::throw_error(ec, "read_until");
92 return bytes_transferred;
95 template <typename SyncReadStream, typename DynamicBuffer_v1>
96 std::size_t read_until(SyncReadStream& s,
97 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
98 char delim, boost::system::error_code& ec,
100 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
103 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
106 typename decay<DynamicBuffer_v1>::type b(
107 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
109 std::size_t search_position = 0;
112 // Determine the range of the data to be searched.
113 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
114 typedef buffers_iterator<buffers_type> iterator;
115 buffers_type data_buffers = b.data();
116 iterator begin = iterator::begin(data_buffers);
117 iterator start_pos = begin + search_position;
118 iterator end = iterator::end(data_buffers);
121 iterator iter = std::find(start_pos, end, delim);
124 // Found a match. We're done.
125 ec = boost::system::error_code();
126 return iter - begin + 1;
130 // No match. Next search can start with the new data.
131 search_position = end - begin;
134 // Check if buffer is full.
135 if (b.size() == b.max_size())
137 ec = error::not_found;
142 std::size_t bytes_to_read = std::min<std::size_t>(
143 std::max<std::size_t>(512, b.capacity() - b.size()),
144 std::min<std::size_t>(65536, b.max_size() - b.size()));
145 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
151 template <typename SyncReadStream, typename DynamicBuffer_v1>
152 inline std::size_t read_until(SyncReadStream& s,
153 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
154 BOOST_ASIO_STRING_VIEW_PARAM delim,
156 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
159 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
162 boost::system::error_code ec;
163 std::size_t bytes_transferred = read_until(s,
164 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);
165 boost::asio::detail::throw_error(ec, "read_until");
166 return bytes_transferred;
169 template <typename SyncReadStream, typename DynamicBuffer_v1>
170 std::size_t read_until(SyncReadStream& s,
171 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
172 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
174 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
177 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
180 typename decay<DynamicBuffer_v1>::type b(
181 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
183 std::size_t search_position = 0;
186 // Determine the range of the data to be searched.
187 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
188 typedef buffers_iterator<buffers_type> iterator;
189 buffers_type data_buffers = b.data();
190 iterator begin = iterator::begin(data_buffers);
191 iterator start_pos = begin + search_position;
192 iterator end = iterator::end(data_buffers);
195 std::pair<iterator, bool> result = detail::partial_search(
196 start_pos, end, delim.begin(), delim.end());
197 if (result.first != end)
201 // Full match. We're done.
202 ec = boost::system::error_code();
203 return result.first - begin + delim.length();
207 // Partial match. Next search needs to start from beginning of match.
208 search_position = result.first - begin;
213 // No match. Next search can start with the new data.
214 search_position = end - begin;
217 // Check if buffer is full.
218 if (b.size() == b.max_size())
220 ec = error::not_found;
225 std::size_t bytes_to_read = std::min<std::size_t>(
226 std::max<std::size_t>(512, b.capacity() - b.size()),
227 std::min<std::size_t>(65536, b.max_size() - b.size()));
228 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
234 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
235 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
237 template <typename SyncReadStream, typename DynamicBuffer_v1>
238 inline std::size_t read_until(SyncReadStream& s,
239 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
240 const boost::regex& expr,
242 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
245 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
248 boost::system::error_code ec;
249 std::size_t bytes_transferred = read_until(s,
250 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec);
251 boost::asio::detail::throw_error(ec, "read_until");
252 return bytes_transferred;
255 template <typename SyncReadStream, typename DynamicBuffer_v1>
256 std::size_t read_until(SyncReadStream& s,
257 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
258 const boost::regex& expr, boost::system::error_code& ec,
260 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
263 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
266 typename decay<DynamicBuffer_v1>::type b(
267 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
269 std::size_t search_position = 0;
272 // Determine the range of the data to be searched.
273 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
274 typedef buffers_iterator<buffers_type> iterator;
275 buffers_type data_buffers = b.data();
276 iterator begin = iterator::begin(data_buffers);
277 iterator start_pos = begin + search_position;
278 iterator end = iterator::end(data_buffers);
281 boost::match_results<iterator,
282 typename std::vector<boost::sub_match<iterator> >::allocator_type>
284 if (regex_search(start_pos, end, match_results, expr,
285 boost::match_default | boost::match_partial))
287 if (match_results[0].matched)
289 // Full match. We're done.
290 ec = boost::system::error_code();
291 return match_results[0].second - begin;
295 // Partial match. Next search needs to start from beginning of match.
296 search_position = match_results[0].first - begin;
301 // No match. Next search can start with the new data.
302 search_position = end - begin;
305 // Check if buffer is full.
306 if (b.size() == b.max_size())
308 ec = error::not_found;
313 std::size_t bytes_to_read = std::min<std::size_t>(
314 std::max<std::size_t>(512, b.capacity() - b.size()),
315 std::min<std::size_t>(65536, b.max_size() - b.size()));
316 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
322 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
324 template <typename SyncReadStream,
325 typename DynamicBuffer_v1, typename MatchCondition>
326 inline std::size_t read_until(SyncReadStream& s,
327 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
328 MatchCondition match_condition,
330 is_match_condition<MatchCondition>::value
333 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
336 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
339 boost::system::error_code ec;
340 std::size_t bytes_transferred = read_until(s,
341 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
342 match_condition, ec);
343 boost::asio::detail::throw_error(ec, "read_until");
344 return bytes_transferred;
347 template <typename SyncReadStream,
348 typename DynamicBuffer_v1, typename MatchCondition>
349 std::size_t read_until(SyncReadStream& s,
350 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
351 MatchCondition match_condition, boost::system::error_code& ec,
353 is_match_condition<MatchCondition>::value
356 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
359 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
362 typename decay<DynamicBuffer_v1>::type b(
363 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
365 std::size_t search_position = 0;
368 // Determine the range of the data to be searched.
369 typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;
370 typedef buffers_iterator<buffers_type> iterator;
371 buffers_type data_buffers = b.data();
372 iterator begin = iterator::begin(data_buffers);
373 iterator start_pos = begin + search_position;
374 iterator end = iterator::end(data_buffers);
377 std::pair<iterator, bool> result = match_condition(start_pos, end);
380 // Full match. We're done.
381 ec = boost::system::error_code();
382 return result.first - begin;
384 else if (result.first != end)
386 // Partial match. Next search needs to start from beginning of match.
387 search_position = result.first - begin;
391 // No match. Next search can start with the new data.
392 search_position = end - begin;
395 // Check if buffer is full.
396 if (b.size() == b.max_size())
398 ec = error::not_found;
403 std::size_t bytes_to_read = std::min<std::size_t>(
404 std::max<std::size_t>(512, b.capacity() - b.size()),
405 std::min<std::size_t>(65536, b.max_size() - b.size()));
406 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
412 #if !defined(BOOST_ASIO_NO_IOSTREAM)
414 template <typename SyncReadStream, typename Allocator>
415 inline std::size_t read_until(SyncReadStream& s,
416 boost::asio::basic_streambuf<Allocator>& b, char delim)
418 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
421 template <typename SyncReadStream, typename Allocator>
422 inline std::size_t read_until(SyncReadStream& s,
423 boost::asio::basic_streambuf<Allocator>& b, char delim,
424 boost::system::error_code& ec)
426 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
429 template <typename SyncReadStream, typename Allocator>
430 inline std::size_t read_until(SyncReadStream& s,
431 boost::asio::basic_streambuf<Allocator>& b,
432 BOOST_ASIO_STRING_VIEW_PARAM delim)
434 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
437 template <typename SyncReadStream, typename Allocator>
438 inline std::size_t read_until(SyncReadStream& s,
439 boost::asio::basic_streambuf<Allocator>& b,
440 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
442 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
445 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
447 template <typename SyncReadStream, typename Allocator>
448 inline std::size_t read_until(SyncReadStream& s,
449 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
451 return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
454 template <typename SyncReadStream, typename Allocator>
455 inline std::size_t read_until(SyncReadStream& s,
456 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
457 boost::system::error_code& ec)
459 return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
462 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
464 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
465 inline std::size_t read_until(SyncReadStream& s,
466 boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
467 typename constraint<is_match_condition<MatchCondition>::value>::type)
469 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
472 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
473 inline std::size_t read_until(SyncReadStream& s,
474 boost::asio::basic_streambuf<Allocator>& b,
475 MatchCondition match_condition, boost::system::error_code& ec,
476 typename constraint<is_match_condition<MatchCondition>::value>::type)
478 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
481 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
482 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
483 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
485 template <typename SyncReadStream, typename DynamicBuffer_v2>
486 inline std::size_t read_until(SyncReadStream& s,
487 DynamicBuffer_v2 buffers, char delim,
489 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
492 boost::system::error_code ec;
493 std::size_t bytes_transferred = read_until(s,
494 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
495 boost::asio::detail::throw_error(ec, "read_until");
496 return bytes_transferred;
499 template <typename SyncReadStream, typename DynamicBuffer_v2>
500 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
501 char delim, boost::system::error_code& ec,
503 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
506 DynamicBuffer_v2& b = buffers;
508 std::size_t search_position = 0;
511 // Determine the range of the data to be searched.
512 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
513 typedef buffers_iterator<buffers_type> iterator;
514 buffers_type data_buffers =
515 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
516 iterator begin = iterator::begin(data_buffers);
517 iterator start_pos = begin + search_position;
518 iterator end = iterator::end(data_buffers);
521 iterator iter = std::find(start_pos, end, delim);
524 // Found a match. We're done.
525 ec = boost::system::error_code();
526 return iter - begin + 1;
530 // No match. Next search can start with the new data.
531 search_position = end - begin;
534 // Check if buffer is full.
535 if (b.size() == b.max_size())
537 ec = error::not_found;
542 std::size_t bytes_to_read = std::min<std::size_t>(
543 std::max<std::size_t>(512, b.capacity() - b.size()),
544 std::min<std::size_t>(65536, b.max_size() - b.size()));
545 std::size_t pos = b.size();
546 b.grow(bytes_to_read);
547 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
548 b.shrink(bytes_to_read - bytes_transferred);
554 template <typename SyncReadStream, typename DynamicBuffer_v2>
555 inline std::size_t read_until(SyncReadStream& s,
556 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
558 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
561 boost::system::error_code ec;
562 std::size_t bytes_transferred = read_until(s,
563 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);
564 boost::asio::detail::throw_error(ec, "read_until");
565 return bytes_transferred;
568 template <typename SyncReadStream, typename DynamicBuffer_v2>
569 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
570 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
572 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
575 DynamicBuffer_v2& b = buffers;
577 std::size_t search_position = 0;
580 // Determine the range of the data to be searched.
581 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
582 typedef buffers_iterator<buffers_type> iterator;
583 buffers_type data_buffers =
584 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
585 iterator begin = iterator::begin(data_buffers);
586 iterator start_pos = begin + search_position;
587 iterator end = iterator::end(data_buffers);
590 std::pair<iterator, bool> result = detail::partial_search(
591 start_pos, end, delim.begin(), delim.end());
592 if (result.first != end)
596 // Full match. We're done.
597 ec = boost::system::error_code();
598 return result.first - begin + delim.length();
602 // Partial match. Next search needs to start from beginning of match.
603 search_position = result.first - begin;
608 // No match. Next search can start with the new data.
609 search_position = end - begin;
612 // Check if buffer is full.
613 if (b.size() == b.max_size())
615 ec = error::not_found;
620 std::size_t bytes_to_read = std::min<std::size_t>(
621 std::max<std::size_t>(512, b.capacity() - b.size()),
622 std::min<std::size_t>(65536, b.max_size() - b.size()));
623 std::size_t pos = b.size();
624 b.grow(bytes_to_read);
625 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
626 b.shrink(bytes_to_read - bytes_transferred);
632 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
633 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
635 template <typename SyncReadStream, typename DynamicBuffer_v2>
636 inline std::size_t read_until(SyncReadStream& s,
637 DynamicBuffer_v2 buffers, const boost::regex& expr,
639 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
642 boost::system::error_code ec;
643 std::size_t bytes_transferred = read_until(s,
644 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec);
645 boost::asio::detail::throw_error(ec, "read_until");
646 return bytes_transferred;
649 template <typename SyncReadStream, typename DynamicBuffer_v2>
650 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
651 const boost::regex& expr, boost::system::error_code& ec,
653 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
656 DynamicBuffer_v2& b = buffers;
658 std::size_t search_position = 0;
661 // Determine the range of the data to be searched.
662 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
663 typedef buffers_iterator<buffers_type> iterator;
664 buffers_type data_buffers =
665 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
666 iterator begin = iterator::begin(data_buffers);
667 iterator start_pos = begin + search_position;
668 iterator end = iterator::end(data_buffers);
671 boost::match_results<iterator,
672 typename std::vector<boost::sub_match<iterator> >::allocator_type>
674 if (regex_search(start_pos, end, match_results, expr,
675 boost::match_default | boost::match_partial))
677 if (match_results[0].matched)
679 // Full match. We're done.
680 ec = boost::system::error_code();
681 return match_results[0].second - begin;
685 // Partial match. Next search needs to start from beginning of match.
686 search_position = match_results[0].first - begin;
691 // No match. Next search can start with the new data.
692 search_position = end - begin;
695 // Check if buffer is full.
696 if (b.size() == b.max_size())
698 ec = error::not_found;
703 std::size_t bytes_to_read = std::min<std::size_t>(
704 std::max<std::size_t>(512, b.capacity() - b.size()),
705 std::min<std::size_t>(65536, b.max_size() - b.size()));
706 std::size_t pos = b.size();
707 b.grow(bytes_to_read);
708 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
709 b.shrink(bytes_to_read - bytes_transferred);
715 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
717 template <typename SyncReadStream,
718 typename DynamicBuffer_v2, typename MatchCondition>
719 inline std::size_t read_until(SyncReadStream& s,
720 DynamicBuffer_v2 buffers, MatchCondition match_condition,
722 is_match_condition<MatchCondition>::value
725 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
728 boost::system::error_code ec;
729 std::size_t bytes_transferred = read_until(s,
730 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
731 match_condition, ec);
732 boost::asio::detail::throw_error(ec, "read_until");
733 return bytes_transferred;
736 template <typename SyncReadStream,
737 typename DynamicBuffer_v2, typename MatchCondition>
738 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
739 MatchCondition match_condition, boost::system::error_code& ec,
741 is_match_condition<MatchCondition>::value
744 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
747 DynamicBuffer_v2& b = buffers;
749 std::size_t search_position = 0;
752 // Determine the range of the data to be searched.
753 typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;
754 typedef buffers_iterator<buffers_type> iterator;
755 buffers_type data_buffers =
756 const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());
757 iterator begin = iterator::begin(data_buffers);
758 iterator start_pos = begin + search_position;
759 iterator end = iterator::end(data_buffers);
762 std::pair<iterator, bool> result = match_condition(start_pos, end);
765 // Full match. We're done.
766 ec = boost::system::error_code();
767 return result.first - begin;
769 else if (result.first != end)
771 // Partial match. Next search needs to start from beginning of match.
772 search_position = result.first - begin;
776 // No match. Next search can start with the new data.
777 search_position = end - begin;
780 // Check if buffer is full.
781 if (b.size() == b.max_size())
783 ec = error::not_found;
788 std::size_t bytes_to_read = std::min<std::size_t>(
789 std::max<std::size_t>(512, b.capacity() - b.size()),
790 std::min<std::size_t>(65536, b.max_size() - b.size()));
791 std::size_t pos = b.size();
792 b.grow(bytes_to_read);
793 std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);
794 b.shrink(bytes_to_read - bytes_transferred);
800 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
802 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
806 template <typename AsyncReadStream,
807 typename DynamicBuffer_v1, typename ReadHandler>
808 class read_until_delim_op_v1
809 : public base_from_cancellation_state<ReadHandler>
812 template <typename BufferSequence>
813 read_until_delim_op_v1(AsyncReadStream& stream,
814 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
815 char delim, ReadHandler& handler)
816 : base_from_cancellation_state<ReadHandler>(
817 handler, enable_partial_cancellation()),
819 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
823 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
827 #if defined(BOOST_ASIO_HAS_MOVE)
828 read_until_delim_op_v1(const read_until_delim_op_v1& other)
829 : base_from_cancellation_state<ReadHandler>(other),
830 stream_(other.stream_),
831 buffers_(other.buffers_),
832 delim_(other.delim_),
833 start_(other.start_),
834 search_position_(other.search_position_),
835 handler_(other.handler_)
839 read_until_delim_op_v1(read_until_delim_op_v1&& other)
840 : base_from_cancellation_state<ReadHandler>(
841 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
842 ReadHandler>)(other)),
843 stream_(other.stream_),
844 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
845 delim_(other.delim_),
846 start_(other.start_),
847 search_position_(other.search_position_),
848 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
851 #endif // defined(BOOST_ASIO_HAS_MOVE)
853 void operator()(boost::system::error_code ec,
854 std::size_t bytes_transferred, int start = 0)
856 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
857 std::size_t bytes_to_read;
858 switch (start_ = start)
864 // Determine the range of the data to be searched.
865 typedef typename DynamicBuffer_v1::const_buffers_type
867 typedef buffers_iterator<buffers_type> iterator;
868 buffers_type data_buffers = buffers_.data();
869 iterator begin = iterator::begin(data_buffers);
870 iterator start_pos = begin + search_position_;
871 iterator end = iterator::end(data_buffers);
874 iterator iter = std::find(start_pos, end, delim_);
877 // Found a match. We're done.
878 search_position_ = iter - begin + 1;
882 // No match yet. Check if buffer is full.
883 else if (buffers_.size() == buffers_.max_size())
885 search_position_ = not_found;
889 // Need to read some more data.
892 // Next search can start with the new data.
893 search_position_ = end - begin;
894 bytes_to_read = std::min<std::size_t>(
895 std::max<std::size_t>(512,
896 buffers_.capacity() - buffers_.size()),
897 std::min<std::size_t>(65536,
898 buffers_.max_size() - buffers_.size()));
902 // Check if we're done.
903 if (!start && bytes_to_read == 0)
906 // Start a new asynchronous read operation to obtain more data.
908 BOOST_ASIO_HANDLER_LOCATION((
909 __FILE__, __LINE__, "async_read_until"));
910 stream_.async_read_some(buffers_.prepare(bytes_to_read),
911 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));
914 buffers_.commit(bytes_transferred);
915 if (ec || bytes_transferred == 0)
917 if (this->cancelled() != cancellation_type::none)
919 ec = error::operation_aborted;
924 const boost::system::error_code result_ec =
925 (search_position_ == not_found)
926 ? error::not_found : ec;
928 const std::size_t result_n =
929 (ec || search_position_ == not_found)
930 ? 0 : search_position_;
932 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
937 AsyncReadStream& stream_;
938 DynamicBuffer_v1 buffers_;
941 std::size_t search_position_;
942 ReadHandler handler_;
945 template <typename AsyncReadStream,
946 typename DynamicBuffer_v1, typename ReadHandler>
947 inline asio_handler_allocate_is_deprecated
948 asio_handler_allocate(std::size_t size,
949 read_until_delim_op_v1<AsyncReadStream,
950 DynamicBuffer_v1, ReadHandler>* this_handler)
952 #if defined(BOOST_ASIO_NO_DEPRECATED)
953 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
954 return asio_handler_allocate_is_no_longer_used();
955 #else // defined(BOOST_ASIO_NO_DEPRECATED)
956 return boost_asio_handler_alloc_helpers::allocate(
957 size, this_handler->handler_);
958 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
961 template <typename AsyncReadStream,
962 typename DynamicBuffer_v1, typename ReadHandler>
963 inline asio_handler_deallocate_is_deprecated
964 asio_handler_deallocate(void* pointer, std::size_t size,
965 read_until_delim_op_v1<AsyncReadStream,
966 DynamicBuffer_v1, ReadHandler>* this_handler)
968 boost_asio_handler_alloc_helpers::deallocate(
969 pointer, size, this_handler->handler_);
970 #if defined(BOOST_ASIO_NO_DEPRECATED)
971 return asio_handler_deallocate_is_no_longer_used();
972 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
975 template <typename AsyncReadStream,
976 typename DynamicBuffer_v1, typename ReadHandler>
977 inline bool asio_handler_is_continuation(
978 read_until_delim_op_v1<AsyncReadStream,
979 DynamicBuffer_v1, ReadHandler>* this_handler)
981 return this_handler->start_ == 0 ? true
982 : boost_asio_handler_cont_helpers::is_continuation(
983 this_handler->handler_);
986 template <typename Function, typename AsyncReadStream,
987 typename DynamicBuffer_v1, typename ReadHandler>
988 inline asio_handler_invoke_is_deprecated
989 asio_handler_invoke(Function& function,
990 read_until_delim_op_v1<AsyncReadStream,
991 DynamicBuffer_v1, ReadHandler>* this_handler)
993 boost_asio_handler_invoke_helpers::invoke(
994 function, this_handler->handler_);
995 #if defined(BOOST_ASIO_NO_DEPRECATED)
996 return asio_handler_invoke_is_no_longer_used();
997 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1000 template <typename Function, typename AsyncReadStream,
1001 typename DynamicBuffer_v1, typename ReadHandler>
1002 inline asio_handler_invoke_is_deprecated
1003 asio_handler_invoke(const Function& function,
1004 read_until_delim_op_v1<AsyncReadStream,
1005 DynamicBuffer_v1, ReadHandler>* this_handler)
1007 boost_asio_handler_invoke_helpers::invoke(
1008 function, this_handler->handler_);
1009 #if defined(BOOST_ASIO_NO_DEPRECATED)
1010 return asio_handler_invoke_is_no_longer_used();
1011 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1014 template <typename AsyncReadStream>
1015 class initiate_async_read_until_delim_v1
1018 typedef typename AsyncReadStream::executor_type executor_type;
1020 explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)
1025 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1027 return stream_.get_executor();
1030 template <typename ReadHandler, typename DynamicBuffer_v1>
1031 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1032 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1035 // If you get an error on the following line it means that your handler
1036 // does not meet the documented type requirements for a ReadHandler.
1037 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1039 non_const_lvalue<ReadHandler> handler2(handler);
1040 read_until_delim_op_v1<AsyncReadStream,
1041 typename decay<DynamicBuffer_v1>::type,
1042 typename decay<ReadHandler>::type>(
1043 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1044 delim, handler2.value)(boost::system::error_code(), 0, 1);
1048 AsyncReadStream& stream_;
1050 } // namespace detail
1052 #if !defined(GENERATING_DOCUMENTATION)
1054 template <template <typename, typename> class Associator,
1055 typename AsyncReadStream, typename DynamicBuffer_v1,
1056 typename ReadHandler, typename DefaultCandidate>
1057 struct associator<Associator,
1058 detail::read_until_delim_op_v1<AsyncReadStream,
1059 DynamicBuffer_v1, ReadHandler>,
1061 : Associator<ReadHandler, DefaultCandidate>
1063 static typename Associator<ReadHandler, DefaultCandidate>::type get(
1064 const detail::read_until_delim_op_v1<AsyncReadStream,
1065 DynamicBuffer_v1, ReadHandler>& h,
1066 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
1068 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
1072 #endif // !defined(GENERATING_DOCUMENTATION)
1074 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1075 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1076 std::size_t)) ReadToken>
1077 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
1078 void (boost::system::error_code, std::size_t))
1079 async_read_until(AsyncReadStream& s,
1080 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1081 char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token,
1082 typename constraint<
1083 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1085 typename constraint<
1086 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1089 return async_initiate<ReadToken,
1090 void (boost::system::error_code, std::size_t)>(
1091 detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
1092 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);
1097 template <typename AsyncReadStream,
1098 typename DynamicBuffer_v1, typename ReadHandler>
1099 class read_until_delim_string_op_v1
1100 : public base_from_cancellation_state<ReadHandler>
1103 template <typename BufferSequence>
1104 read_until_delim_string_op_v1(AsyncReadStream& stream,
1105 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1106 const std::string& delim, ReadHandler& handler)
1107 : base_from_cancellation_state<ReadHandler>(
1108 handler, enable_partial_cancellation()),
1110 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1113 search_position_(0),
1114 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1118 #if defined(BOOST_ASIO_HAS_MOVE)
1119 read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
1120 : base_from_cancellation_state<ReadHandler>(other),
1121 stream_(other.stream_),
1122 buffers_(other.buffers_),
1123 delim_(other.delim_),
1124 start_(other.start_),
1125 search_position_(other.search_position_),
1126 handler_(other.handler_)
1130 read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)
1131 : base_from_cancellation_state<ReadHandler>(
1132 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
1133 ReadHandler>)(other)),
1134 stream_(other.stream_),
1135 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1136 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
1137 start_(other.start_),
1138 search_position_(other.search_position_),
1139 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1142 #endif // defined(BOOST_ASIO_HAS_MOVE)
1144 void operator()(boost::system::error_code ec,
1145 std::size_t bytes_transferred, int start = 0)
1147 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1148 std::size_t bytes_to_read;
1149 switch (start_ = start)
1155 // Determine the range of the data to be searched.
1156 typedef typename DynamicBuffer_v1::const_buffers_type
1158 typedef buffers_iterator<buffers_type> iterator;
1159 buffers_type data_buffers = buffers_.data();
1160 iterator begin = iterator::begin(data_buffers);
1161 iterator start_pos = begin + search_position_;
1162 iterator end = iterator::end(data_buffers);
1164 // Look for a match.
1165 std::pair<iterator, bool> result = detail::partial_search(
1166 start_pos, end, delim_.begin(), delim_.end());
1167 if (result.first != end && result.second)
1169 // Full match. We're done.
1170 search_position_ = result.first - begin + delim_.length();
1174 // No match yet. Check if buffer is full.
1175 else if (buffers_.size() == buffers_.max_size())
1177 search_position_ = not_found;
1181 // Need to read some more data.
1184 if (result.first != end)
1186 // Partial match. Next search needs to start from beginning of
1188 search_position_ = result.first - begin;
1192 // Next search can start with the new data.
1193 search_position_ = end - begin;
1196 bytes_to_read = std::min<std::size_t>(
1197 std::max<std::size_t>(512,
1198 buffers_.capacity() - buffers_.size()),
1199 std::min<std::size_t>(65536,
1200 buffers_.max_size() - buffers_.size()));
1204 // Check if we're done.
1205 if (!start && bytes_to_read == 0)
1208 // Start a new asynchronous read operation to obtain more data.
1210 BOOST_ASIO_HANDLER_LOCATION((
1211 __FILE__, __LINE__, "async_read_until"));
1212 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1213 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this));
1216 buffers_.commit(bytes_transferred);
1217 if (ec || bytes_transferred == 0)
1219 if (this->cancelled() != cancellation_type::none)
1221 ec = error::operation_aborted;
1226 const boost::system::error_code result_ec =
1227 (search_position_ == not_found)
1228 ? error::not_found : ec;
1230 const std::size_t result_n =
1231 (ec || search_position_ == not_found)
1232 ? 0 : search_position_;
1234 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
1239 AsyncReadStream& stream_;
1240 DynamicBuffer_v1 buffers_;
1243 std::size_t search_position_;
1244 ReadHandler handler_;
1247 template <typename AsyncReadStream,
1248 typename DynamicBuffer_v1, typename ReadHandler>
1249 inline asio_handler_allocate_is_deprecated
1250 asio_handler_allocate(std::size_t size,
1251 read_until_delim_string_op_v1<AsyncReadStream,
1252 DynamicBuffer_v1, ReadHandler>* this_handler)
1254 #if defined(BOOST_ASIO_NO_DEPRECATED)
1255 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1256 return asio_handler_allocate_is_no_longer_used();
1257 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1258 return boost_asio_handler_alloc_helpers::allocate(
1259 size, this_handler->handler_);
1260 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1263 template <typename AsyncReadStream,
1264 typename DynamicBuffer_v1, typename ReadHandler>
1265 inline asio_handler_deallocate_is_deprecated
1266 asio_handler_deallocate(void* pointer, std::size_t size,
1267 read_until_delim_string_op_v1<AsyncReadStream,
1268 DynamicBuffer_v1, ReadHandler>* this_handler)
1270 boost_asio_handler_alloc_helpers::deallocate(
1271 pointer, size, this_handler->handler_);
1272 #if defined(BOOST_ASIO_NO_DEPRECATED)
1273 return asio_handler_deallocate_is_no_longer_used();
1274 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1277 template <typename AsyncReadStream,
1278 typename DynamicBuffer_v1, typename ReadHandler>
1279 inline bool asio_handler_is_continuation(
1280 read_until_delim_string_op_v1<AsyncReadStream,
1281 DynamicBuffer_v1, ReadHandler>* this_handler)
1283 return this_handler->start_ == 0 ? true
1284 : boost_asio_handler_cont_helpers::is_continuation(
1285 this_handler->handler_);
1288 template <typename Function, typename AsyncReadStream,
1289 typename DynamicBuffer_v1, typename ReadHandler>
1290 inline asio_handler_invoke_is_deprecated
1291 asio_handler_invoke(Function& function,
1292 read_until_delim_string_op_v1<AsyncReadStream,
1293 DynamicBuffer_v1, ReadHandler>* this_handler)
1295 boost_asio_handler_invoke_helpers::invoke(
1296 function, this_handler->handler_);
1297 #if defined(BOOST_ASIO_NO_DEPRECATED)
1298 return asio_handler_invoke_is_no_longer_used();
1299 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1302 template <typename Function, typename AsyncReadStream,
1303 typename DynamicBuffer_v1, typename ReadHandler>
1304 inline asio_handler_invoke_is_deprecated
1305 asio_handler_invoke(const Function& function,
1306 read_until_delim_string_op_v1<AsyncReadStream,
1307 DynamicBuffer_v1, ReadHandler>* this_handler)
1309 boost_asio_handler_invoke_helpers::invoke(
1310 function, this_handler->handler_);
1311 #if defined(BOOST_ASIO_NO_DEPRECATED)
1312 return asio_handler_invoke_is_no_longer_used();
1313 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1316 template <typename AsyncReadStream>
1317 class initiate_async_read_until_delim_string_v1
1320 typedef typename AsyncReadStream::executor_type executor_type;
1322 explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)
1327 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1329 return stream_.get_executor();
1332 template <typename ReadHandler, typename DynamicBuffer_v1>
1333 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1334 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1335 const std::string& delim) const
1337 // If you get an error on the following line it means that your handler
1338 // does not meet the documented type requirements for a ReadHandler.
1339 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1341 non_const_lvalue<ReadHandler> handler2(handler);
1342 read_until_delim_string_op_v1<AsyncReadStream,
1343 typename decay<DynamicBuffer_v1>::type,
1344 typename decay<ReadHandler>::type>(
1345 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1346 delim, handler2.value)(boost::system::error_code(), 0, 1);
1350 AsyncReadStream& stream_;
1352 } // namespace detail
1354 #if !defined(GENERATING_DOCUMENTATION)
1356 template <template <typename, typename> class Associator,
1357 typename AsyncReadStream, typename DynamicBuffer_v1,
1358 typename ReadHandler, typename DefaultCandidate>
1359 struct associator<Associator,
1360 detail::read_until_delim_string_op_v1<AsyncReadStream,
1361 DynamicBuffer_v1, ReadHandler>,
1363 : Associator<ReadHandler, DefaultCandidate>
1365 static typename Associator<ReadHandler, DefaultCandidate>::type get(
1366 const detail::read_until_delim_string_op_v1<AsyncReadStream,
1367 DynamicBuffer_v1, ReadHandler>& h,
1368 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
1370 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
1374 #endif // !defined(GENERATING_DOCUMENTATION)
1376 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1377 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1378 std::size_t)) ReadToken>
1379 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
1380 void (boost::system::error_code, std::size_t))
1381 async_read_until(AsyncReadStream& s,
1382 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1383 BOOST_ASIO_STRING_VIEW_PARAM delim,
1384 BOOST_ASIO_MOVE_ARG(ReadToken) token,
1385 typename constraint<
1386 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1388 typename constraint<
1389 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1392 return async_initiate<ReadToken,
1393 void (boost::system::error_code, std::size_t)>(
1394 detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
1395 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1396 static_cast<std::string>(delim));
1399 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
1400 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
1404 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1405 typename RegEx, typename ReadHandler>
1406 class read_until_expr_op_v1
1407 : public base_from_cancellation_state<ReadHandler>
1410 template <typename BufferSequence>
1411 read_until_expr_op_v1(AsyncReadStream& stream,
1412 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1413 const boost::regex& expr, ReadHandler& handler)
1414 : base_from_cancellation_state<ReadHandler>(
1415 handler, enable_partial_cancellation()),
1417 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1420 search_position_(0),
1421 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1425 #if defined(BOOST_ASIO_HAS_MOVE)
1426 read_until_expr_op_v1(const read_until_expr_op_v1& other)
1427 : base_from_cancellation_state<ReadHandler>(other),
1428 stream_(other.stream_),
1429 buffers_(other.buffers_),
1431 start_(other.start_),
1432 search_position_(other.search_position_),
1433 handler_(other.handler_)
1437 read_until_expr_op_v1(read_until_expr_op_v1&& other)
1438 : base_from_cancellation_state<ReadHandler>(
1439 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
1440 ReadHandler>)(other)),
1441 stream_(other.stream_),
1442 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1444 start_(other.start_),
1445 search_position_(other.search_position_),
1446 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1449 #endif // defined(BOOST_ASIO_HAS_MOVE)
1451 void operator()(boost::system::error_code ec,
1452 std::size_t bytes_transferred, int start = 0)
1454 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1455 std::size_t bytes_to_read;
1456 switch (start_ = start)
1462 // Determine the range of the data to be searched.
1463 typedef typename DynamicBuffer_v1::const_buffers_type
1465 typedef buffers_iterator<buffers_type> iterator;
1466 buffers_type data_buffers = buffers_.data();
1467 iterator begin = iterator::begin(data_buffers);
1468 iterator start_pos = begin + search_position_;
1469 iterator end = iterator::end(data_buffers);
1471 // Look for a match.
1472 boost::match_results<iterator,
1473 typename std::vector<boost::sub_match<iterator> >::allocator_type>
1475 bool match = regex_search(start_pos, end, match_results, expr_,
1476 boost::match_default | boost::match_partial);
1477 if (match && match_results[0].matched)
1479 // Full match. We're done.
1480 search_position_ = match_results[0].second - begin;
1484 // No match yet. Check if buffer is full.
1485 else if (buffers_.size() == buffers_.max_size())
1487 search_position_ = not_found;
1491 // Need to read some more data.
1496 // Partial match. Next search needs to start from beginning of
1498 search_position_ = match_results[0].first - begin;
1502 // Next search can start with the new data.
1503 search_position_ = end - begin;
1506 bytes_to_read = std::min<std::size_t>(
1507 std::max<std::size_t>(512,
1508 buffers_.capacity() - buffers_.size()),
1509 std::min<std::size_t>(65536,
1510 buffers_.max_size() - buffers_.size()));
1514 // Check if we're done.
1515 if (!start && bytes_to_read == 0)
1518 // Start a new asynchronous read operation to obtain more data.
1520 BOOST_ASIO_HANDLER_LOCATION((
1521 __FILE__, __LINE__, "async_read_until"));
1522 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1523 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));
1526 buffers_.commit(bytes_transferred);
1527 if (ec || bytes_transferred == 0)
1529 if (this->cancelled() != cancellation_type::none)
1531 ec = error::operation_aborted;
1536 const boost::system::error_code result_ec =
1537 (search_position_ == not_found)
1538 ? error::not_found : ec;
1540 const std::size_t result_n =
1541 (ec || search_position_ == not_found)
1542 ? 0 : search_position_;
1544 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
1549 AsyncReadStream& stream_;
1550 DynamicBuffer_v1 buffers_;
1553 std::size_t search_position_;
1554 ReadHandler handler_;
1557 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1558 typename RegEx, typename ReadHandler>
1559 inline asio_handler_allocate_is_deprecated
1560 asio_handler_allocate(std::size_t size,
1561 read_until_expr_op_v1<AsyncReadStream,
1562 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1564 #if defined(BOOST_ASIO_NO_DEPRECATED)
1565 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1566 return asio_handler_allocate_is_no_longer_used();
1567 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1568 return boost_asio_handler_alloc_helpers::allocate(
1569 size, this_handler->handler_);
1570 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1573 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1574 typename RegEx, typename ReadHandler>
1575 inline asio_handler_deallocate_is_deprecated
1576 asio_handler_deallocate(void* pointer, std::size_t size,
1577 read_until_expr_op_v1<AsyncReadStream,
1578 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1580 boost_asio_handler_alloc_helpers::deallocate(
1581 pointer, size, this_handler->handler_);
1582 #if defined(BOOST_ASIO_NO_DEPRECATED)
1583 return asio_handler_deallocate_is_no_longer_used();
1584 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1587 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1588 typename RegEx, typename ReadHandler>
1589 inline bool asio_handler_is_continuation(
1590 read_until_expr_op_v1<AsyncReadStream,
1591 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1593 return this_handler->start_ == 0 ? true
1594 : boost_asio_handler_cont_helpers::is_continuation(
1595 this_handler->handler_);
1598 template <typename Function, typename AsyncReadStream,
1599 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1600 inline asio_handler_invoke_is_deprecated
1601 asio_handler_invoke(Function& function,
1602 read_until_expr_op_v1<AsyncReadStream,
1603 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1605 boost_asio_handler_invoke_helpers::invoke(
1606 function, this_handler->handler_);
1607 #if defined(BOOST_ASIO_NO_DEPRECATED)
1608 return asio_handler_invoke_is_no_longer_used();
1609 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1612 template <typename Function, typename AsyncReadStream,
1613 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1614 inline asio_handler_invoke_is_deprecated
1615 asio_handler_invoke(const Function& function,
1616 read_until_expr_op_v1<AsyncReadStream,
1617 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1619 boost_asio_handler_invoke_helpers::invoke(
1620 function, this_handler->handler_);
1621 #if defined(BOOST_ASIO_NO_DEPRECATED)
1622 return asio_handler_invoke_is_no_longer_used();
1623 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1626 template <typename AsyncReadStream>
1627 class initiate_async_read_until_expr_v1
1630 typedef typename AsyncReadStream::executor_type executor_type;
1632 explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)
1637 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1639 return stream_.get_executor();
1642 template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>
1643 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1644 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) const
1646 // If you get an error on the following line it means that your handler
1647 // does not meet the documented type requirements for a ReadHandler.
1648 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1650 non_const_lvalue<ReadHandler> handler2(handler);
1651 read_until_expr_op_v1<AsyncReadStream,
1652 typename decay<DynamicBuffer_v1>::type,
1653 RegEx, typename decay<ReadHandler>::type>(
1654 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1655 expr, handler2.value)(boost::system::error_code(), 0, 1);
1659 AsyncReadStream& stream_;
1661 } // namespace detail
1663 #if !defined(GENERATING_DOCUMENTATION)
1665 template <template <typename, typename> class Associator,
1666 typename AsyncReadStream, typename DynamicBuffer_v1,
1667 typename RegEx, typename ReadHandler, typename DefaultCandidate>
1668 struct associator<Associator,
1669 detail::read_until_expr_op_v1<AsyncReadStream,
1670 DynamicBuffer_v1, RegEx, ReadHandler>,
1672 : Associator<ReadHandler, DefaultCandidate>
1674 static typename Associator<ReadHandler, DefaultCandidate>::type get(
1675 const detail::read_until_expr_op_v1<AsyncReadStream,
1676 DynamicBuffer_v1, RegEx, ReadHandler>& h,
1677 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
1679 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
1683 #endif // !defined(GENERATING_DOCUMENTATION)
1685 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1686 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1687 std::size_t)) ReadToken>
1688 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
1689 void (boost::system::error_code, std::size_t))
1690 async_read_until(AsyncReadStream& s,
1691 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1692 const boost::regex& expr,
1693 BOOST_ASIO_MOVE_ARG(ReadToken) token,
1694 typename constraint<
1695 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1697 typename constraint<
1698 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1701 return async_initiate<ReadToken,
1702 void (boost::system::error_code, std::size_t)>(
1703 detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
1704 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);
1707 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
1711 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1712 typename MatchCondition, typename ReadHandler>
1713 class read_until_match_op_v1
1714 : public base_from_cancellation_state<ReadHandler>
1717 template <typename BufferSequence>
1718 read_until_match_op_v1(AsyncReadStream& stream,
1719 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1720 MatchCondition match_condition, ReadHandler& handler)
1721 : base_from_cancellation_state<ReadHandler>(
1722 handler, enable_partial_cancellation()),
1724 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1725 match_condition_(match_condition),
1727 search_position_(0),
1728 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1732 #if defined(BOOST_ASIO_HAS_MOVE)
1733 read_until_match_op_v1(const read_until_match_op_v1& other)
1734 : base_from_cancellation_state<ReadHandler>(other),
1735 stream_(other.stream_),
1736 buffers_(other.buffers_),
1737 match_condition_(other.match_condition_),
1738 start_(other.start_),
1739 search_position_(other.search_position_),
1740 handler_(other.handler_)
1744 read_until_match_op_v1(read_until_match_op_v1&& other)
1745 : base_from_cancellation_state<ReadHandler>(
1746 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
1747 ReadHandler>)(other)),
1748 stream_(other.stream_),
1749 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1750 match_condition_(other.match_condition_),
1751 start_(other.start_),
1752 search_position_(other.search_position_),
1753 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1756 #endif // defined(BOOST_ASIO_HAS_MOVE)
1758 void operator()(boost::system::error_code ec,
1759 std::size_t bytes_transferred, int start = 0)
1761 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1762 std::size_t bytes_to_read;
1763 switch (start_ = start)
1769 // Determine the range of the data to be searched.
1770 typedef typename DynamicBuffer_v1::const_buffers_type
1772 typedef buffers_iterator<buffers_type> iterator;
1773 buffers_type data_buffers = buffers_.data();
1774 iterator begin = iterator::begin(data_buffers);
1775 iterator start_pos = begin + search_position_;
1776 iterator end = iterator::end(data_buffers);
1778 // Look for a match.
1779 std::pair<iterator, bool> result = match_condition_(start_pos, end);
1782 // Full match. We're done.
1783 search_position_ = result.first - begin;
1787 // No match yet. Check if buffer is full.
1788 else if (buffers_.size() == buffers_.max_size())
1790 search_position_ = not_found;
1794 // Need to read some more data.
1797 if (result.first != end)
1799 // Partial match. Next search needs to start from beginning of
1801 search_position_ = result.first - begin;
1805 // Next search can start with the new data.
1806 search_position_ = end - begin;
1809 bytes_to_read = std::min<std::size_t>(
1810 std::max<std::size_t>(512,
1811 buffers_.capacity() - buffers_.size()),
1812 std::min<std::size_t>(65536,
1813 buffers_.max_size() - buffers_.size()));
1817 // Check if we're done.
1818 if (!start && bytes_to_read == 0)
1821 // Start a new asynchronous read operation to obtain more data.
1823 BOOST_ASIO_HANDLER_LOCATION((
1824 __FILE__, __LINE__, "async_read_until"));
1825 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1826 BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this));
1829 buffers_.commit(bytes_transferred);
1830 if (ec || bytes_transferred == 0)
1832 if (this->cancelled() != cancellation_type::none)
1834 ec = error::operation_aborted;
1839 const boost::system::error_code result_ec =
1840 (search_position_ == not_found)
1841 ? error::not_found : ec;
1843 const std::size_t result_n =
1844 (ec || search_position_ == not_found)
1845 ? 0 : search_position_;
1847 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
1852 AsyncReadStream& stream_;
1853 DynamicBuffer_v1 buffers_;
1854 MatchCondition match_condition_;
1856 std::size_t search_position_;
1857 ReadHandler handler_;
1860 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1861 typename MatchCondition, typename ReadHandler>
1862 inline asio_handler_allocate_is_deprecated
1863 asio_handler_allocate(std::size_t size,
1864 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1865 MatchCondition, ReadHandler>* this_handler)
1867 #if defined(BOOST_ASIO_NO_DEPRECATED)
1868 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1869 return asio_handler_allocate_is_no_longer_used();
1870 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1871 return boost_asio_handler_alloc_helpers::allocate(
1872 size, this_handler->handler_);
1873 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1876 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1877 typename MatchCondition, typename ReadHandler>
1878 inline asio_handler_deallocate_is_deprecated
1879 asio_handler_deallocate(void* pointer, std::size_t size,
1880 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1881 MatchCondition, ReadHandler>* this_handler)
1883 boost_asio_handler_alloc_helpers::deallocate(
1884 pointer, size, this_handler->handler_);
1885 #if defined(BOOST_ASIO_NO_DEPRECATED)
1886 return asio_handler_deallocate_is_no_longer_used();
1887 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1890 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1891 typename MatchCondition, typename ReadHandler>
1892 inline bool asio_handler_is_continuation(
1893 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1894 MatchCondition, ReadHandler>* this_handler)
1896 return this_handler->start_ == 0 ? true
1897 : boost_asio_handler_cont_helpers::is_continuation(
1898 this_handler->handler_);
1901 template <typename Function, typename AsyncReadStream,
1902 typename DynamicBuffer_v1, typename MatchCondition,
1903 typename ReadHandler>
1904 inline asio_handler_invoke_is_deprecated
1905 asio_handler_invoke(Function& function,
1906 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1907 MatchCondition, ReadHandler>* this_handler)
1909 boost_asio_handler_invoke_helpers::invoke(
1910 function, this_handler->handler_);
1911 #if defined(BOOST_ASIO_NO_DEPRECATED)
1912 return asio_handler_invoke_is_no_longer_used();
1913 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1916 template <typename Function, typename AsyncReadStream,
1917 typename DynamicBuffer_v1, typename MatchCondition,
1918 typename ReadHandler>
1919 inline asio_handler_invoke_is_deprecated
1920 asio_handler_invoke(const Function& function,
1921 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1922 MatchCondition, ReadHandler>* this_handler)
1924 boost_asio_handler_invoke_helpers::invoke(
1925 function, this_handler->handler_);
1926 #if defined(BOOST_ASIO_NO_DEPRECATED)
1927 return asio_handler_invoke_is_no_longer_used();
1928 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1931 template <typename AsyncReadStream>
1932 class initiate_async_read_until_match_v1
1935 typedef typename AsyncReadStream::executor_type executor_type;
1937 explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)
1942 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1944 return stream_.get_executor();
1947 template <typename ReadHandler,
1948 typename DynamicBuffer_v1, typename MatchCondition>
1949 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1950 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1951 MatchCondition match_condition) const
1953 // If you get an error on the following line it means that your handler
1954 // does not meet the documented type requirements for a ReadHandler.
1955 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1957 non_const_lvalue<ReadHandler> handler2(handler);
1958 read_until_match_op_v1<AsyncReadStream,
1959 typename decay<DynamicBuffer_v1>::type,
1960 MatchCondition, typename decay<ReadHandler>::type>(
1961 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1962 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
1966 AsyncReadStream& stream_;
1968 } // namespace detail
1970 #if !defined(GENERATING_DOCUMENTATION)
1972 template <template <typename, typename> class Associator,
1973 typename AsyncReadStream, typename DynamicBuffer_v1,
1974 typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
1975 struct associator<Associator,
1976 detail::read_until_match_op_v1<AsyncReadStream,
1977 DynamicBuffer_v1, MatchCondition, ReadHandler>,
1979 : Associator<ReadHandler, DefaultCandidate>
1981 static typename Associator<ReadHandler, DefaultCandidate>::type get(
1982 const detail::read_until_match_op_v1<AsyncReadStream,
1983 DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
1984 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
1986 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
1990 #endif // !defined(GENERATING_DOCUMENTATION)
1992 template <typename AsyncReadStream,
1993 typename DynamicBuffer_v1, typename MatchCondition,
1994 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1995 std::size_t)) ReadToken>
1996 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
1997 void (boost::system::error_code, std::size_t))
1998 async_read_until(AsyncReadStream& s,
1999 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
2000 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
2001 typename constraint<
2002 is_match_condition<MatchCondition>::value
2004 typename constraint<
2005 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
2007 typename constraint<
2008 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
2011 return async_initiate<ReadToken,
2012 void (boost::system::error_code, std::size_t)>(
2013 detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), token,
2014 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);
2017 #if !defined(BOOST_ASIO_NO_IOSTREAM)
2019 template <typename AsyncReadStream, typename Allocator,
2020 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2021 std::size_t)) ReadToken>
2022 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2023 void (boost::system::error_code, std::size_t))
2024 async_read_until(AsyncReadStream& s,
2025 boost::asio::basic_streambuf<Allocator>& b,
2026 char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token)
2028 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2029 delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
2032 template <typename AsyncReadStream, typename Allocator,
2033 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2034 std::size_t)) ReadToken>
2035 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2036 void (boost::system::error_code, std::size_t))
2037 async_read_until(AsyncReadStream& s,
2038 boost::asio::basic_streambuf<Allocator>& b,
2039 BOOST_ASIO_STRING_VIEW_PARAM delim,
2040 BOOST_ASIO_MOVE_ARG(ReadToken) token)
2042 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2043 delim, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
2046 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
2048 template <typename AsyncReadStream, typename Allocator,
2049 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2050 std::size_t)) ReadToken>
2051 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2052 void (boost::system::error_code, std::size_t))
2053 async_read_until(AsyncReadStream& s,
2054 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
2055 BOOST_ASIO_MOVE_ARG(ReadToken) token)
2057 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2058 expr, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
2061 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
2063 template <typename AsyncReadStream, typename Allocator, typename MatchCondition,
2064 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2065 std::size_t)) ReadToken>
2066 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2067 void (boost::system::error_code, std::size_t))
2068 async_read_until(AsyncReadStream& s,
2069 boost::asio::basic_streambuf<Allocator>& b,
2070 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
2071 typename constraint<is_match_condition<MatchCondition>::value>::type)
2073 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2074 match_condition, BOOST_ASIO_MOVE_CAST(ReadToken)(token));
2077 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
2078 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
2079 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2083 template <typename AsyncReadStream,
2084 typename DynamicBuffer_v2, typename ReadHandler>
2085 class read_until_delim_op_v2
2086 : public base_from_cancellation_state<ReadHandler>
2089 template <typename BufferSequence>
2090 read_until_delim_op_v2(AsyncReadStream& stream,
2091 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2092 char delim, ReadHandler& handler)
2093 : base_from_cancellation_state<ReadHandler>(
2094 handler, enable_partial_cancellation()),
2096 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2099 search_position_(0),
2101 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2105 #if defined(BOOST_ASIO_HAS_MOVE)
2106 read_until_delim_op_v2(const read_until_delim_op_v2& other)
2107 : base_from_cancellation_state<ReadHandler>(other),
2108 stream_(other.stream_),
2109 buffers_(other.buffers_),
2110 delim_(other.delim_),
2111 start_(other.start_),
2112 search_position_(other.search_position_),
2113 bytes_to_read_(other.bytes_to_read_),
2114 handler_(other.handler_)
2118 read_until_delim_op_v2(read_until_delim_op_v2&& other)
2119 : base_from_cancellation_state<ReadHandler>(
2120 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
2121 ReadHandler>)(other)),
2122 stream_(other.stream_),
2123 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2124 delim_(other.delim_),
2125 start_(other.start_),
2126 search_position_(other.search_position_),
2127 bytes_to_read_(other.bytes_to_read_),
2128 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2131 #endif // defined(BOOST_ASIO_HAS_MOVE)
2133 void operator()(boost::system::error_code ec,
2134 std::size_t bytes_transferred, int start = 0)
2136 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2138 switch (start_ = start)
2144 // Determine the range of the data to be searched.
2145 typedef typename DynamicBuffer_v2::const_buffers_type
2147 typedef buffers_iterator<buffers_type> iterator;
2148 buffers_type data_buffers =
2149 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2150 0, buffers_.size());
2151 iterator begin = iterator::begin(data_buffers);
2152 iterator start_pos = begin + search_position_;
2153 iterator end = iterator::end(data_buffers);
2155 // Look for a match.
2156 iterator iter = std::find(start_pos, end, delim_);
2159 // Found a match. We're done.
2160 search_position_ = iter - begin + 1;
2164 // No match yet. Check if buffer is full.
2165 else if (buffers_.size() == buffers_.max_size())
2167 search_position_ = not_found;
2171 // Need to read some more data.
2174 // Next search can start with the new data.
2175 search_position_ = end - begin;
2176 bytes_to_read_ = std::min<std::size_t>(
2177 std::max<std::size_t>(512,
2178 buffers_.capacity() - buffers_.size()),
2179 std::min<std::size_t>(65536,
2180 buffers_.max_size() - buffers_.size()));
2184 // Check if we're done.
2185 if (!start && bytes_to_read_ == 0)
2188 // Start a new asynchronous read operation to obtain more data.
2189 pos = buffers_.size();
2190 buffers_.grow(bytes_to_read_);
2192 BOOST_ASIO_HANDLER_LOCATION((
2193 __FILE__, __LINE__, "async_read_until"));
2194 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2195 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));
2198 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2199 if (ec || bytes_transferred == 0)
2201 if (this->cancelled() != cancellation_type::none)
2203 ec = error::operation_aborted;
2208 const boost::system::error_code result_ec =
2209 (search_position_ == not_found)
2210 ? error::not_found : ec;
2212 const std::size_t result_n =
2213 (ec || search_position_ == not_found)
2214 ? 0 : search_position_;
2216 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
2221 AsyncReadStream& stream_;
2222 DynamicBuffer_v2 buffers_;
2225 std::size_t search_position_;
2226 std::size_t bytes_to_read_;
2227 ReadHandler handler_;
2230 template <typename AsyncReadStream,
2231 typename DynamicBuffer_v2, typename ReadHandler>
2232 inline asio_handler_allocate_is_deprecated
2233 asio_handler_allocate(std::size_t size,
2234 read_until_delim_op_v2<AsyncReadStream,
2235 DynamicBuffer_v2, ReadHandler>* this_handler)
2237 #if defined(BOOST_ASIO_NO_DEPRECATED)
2238 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2239 return asio_handler_allocate_is_no_longer_used();
2240 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2241 return boost_asio_handler_alloc_helpers::allocate(
2242 size, this_handler->handler_);
2243 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2246 template <typename AsyncReadStream,
2247 typename DynamicBuffer_v2, typename ReadHandler>
2248 inline asio_handler_deallocate_is_deprecated
2249 asio_handler_deallocate(void* pointer, std::size_t size,
2250 read_until_delim_op_v2<AsyncReadStream,
2251 DynamicBuffer_v2, ReadHandler>* this_handler)
2253 boost_asio_handler_alloc_helpers::deallocate(
2254 pointer, size, this_handler->handler_);
2255 #if defined(BOOST_ASIO_NO_DEPRECATED)
2256 return asio_handler_deallocate_is_no_longer_used();
2257 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2260 template <typename AsyncReadStream,
2261 typename DynamicBuffer_v2, typename ReadHandler>
2262 inline bool asio_handler_is_continuation(
2263 read_until_delim_op_v2<AsyncReadStream,
2264 DynamicBuffer_v2, ReadHandler>* this_handler)
2266 return this_handler->start_ == 0 ? true
2267 : boost_asio_handler_cont_helpers::is_continuation(
2268 this_handler->handler_);
2271 template <typename Function, typename AsyncReadStream,
2272 typename DynamicBuffer_v2, typename ReadHandler>
2273 inline asio_handler_invoke_is_deprecated
2274 asio_handler_invoke(Function& function,
2275 read_until_delim_op_v2<AsyncReadStream,
2276 DynamicBuffer_v2, ReadHandler>* this_handler)
2278 boost_asio_handler_invoke_helpers::invoke(
2279 function, this_handler->handler_);
2280 #if defined(BOOST_ASIO_NO_DEPRECATED)
2281 return asio_handler_invoke_is_no_longer_used();
2282 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2285 template <typename Function, typename AsyncReadStream,
2286 typename DynamicBuffer_v2, typename ReadHandler>
2287 inline asio_handler_invoke_is_deprecated
2288 asio_handler_invoke(const Function& function,
2289 read_until_delim_op_v2<AsyncReadStream,
2290 DynamicBuffer_v2, ReadHandler>* this_handler)
2292 boost_asio_handler_invoke_helpers::invoke(
2293 function, this_handler->handler_);
2294 #if defined(BOOST_ASIO_NO_DEPRECATED)
2295 return asio_handler_invoke_is_no_longer_used();
2296 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2299 template <typename AsyncReadStream>
2300 class initiate_async_read_until_delim_v2
2303 typedef typename AsyncReadStream::executor_type executor_type;
2305 explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)
2310 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2312 return stream_.get_executor();
2315 template <typename ReadHandler, typename DynamicBuffer_v2>
2316 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2317 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) const
2319 // If you get an error on the following line it means that your handler
2320 // does not meet the documented type requirements for a ReadHandler.
2321 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2323 non_const_lvalue<ReadHandler> handler2(handler);
2324 read_until_delim_op_v2<AsyncReadStream,
2325 typename decay<DynamicBuffer_v2>::type,
2326 typename decay<ReadHandler>::type>(
2327 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2328 delim, handler2.value)(boost::system::error_code(), 0, 1);
2332 AsyncReadStream& stream_;
2334 } // namespace detail
2336 #if !defined(GENERATING_DOCUMENTATION)
2338 template <template <typename, typename> class Associator,
2339 typename AsyncReadStream, typename DynamicBuffer_v2,
2340 typename ReadHandler, typename DefaultCandidate>
2341 struct associator<Associator,
2342 detail::read_until_delim_op_v2<AsyncReadStream,
2343 DynamicBuffer_v2, ReadHandler>,
2345 : Associator<ReadHandler, DefaultCandidate>
2347 static typename Associator<ReadHandler, DefaultCandidate>::type get(
2348 const detail::read_until_delim_op_v2<AsyncReadStream,
2349 DynamicBuffer_v2, ReadHandler>& h,
2350 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
2352 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
2356 #endif // !defined(GENERATING_DOCUMENTATION)
2358 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2359 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2360 std::size_t)) ReadToken>
2361 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2362 void (boost::system::error_code, std::size_t))
2363 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
2364 char delim, BOOST_ASIO_MOVE_ARG(ReadToken) token,
2365 typename constraint<
2366 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2369 return async_initiate<ReadToken,
2370 void (boost::system::error_code, std::size_t)>(
2371 detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),
2372 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);
2377 template <typename AsyncReadStream,
2378 typename DynamicBuffer_v2, typename ReadHandler>
2379 class read_until_delim_string_op_v2
2380 : public base_from_cancellation_state<ReadHandler>
2383 template <typename BufferSequence>
2384 read_until_delim_string_op_v2(AsyncReadStream& stream,
2385 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2386 const std::string& delim, ReadHandler& handler)
2387 : base_from_cancellation_state<ReadHandler>(
2388 handler, enable_partial_cancellation()),
2390 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2393 search_position_(0),
2395 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2399 #if defined(BOOST_ASIO_HAS_MOVE)
2400 read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
2401 : base_from_cancellation_state<ReadHandler>(other),
2402 stream_(other.stream_),
2403 buffers_(other.buffers_),
2404 delim_(other.delim_),
2405 start_(other.start_),
2406 search_position_(other.search_position_),
2407 bytes_to_read_(other.bytes_to_read_),
2408 handler_(other.handler_)
2412 read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
2413 : base_from_cancellation_state<ReadHandler>(
2414 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
2415 ReadHandler>)(other)),
2416 stream_(other.stream_),
2417 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2418 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
2419 start_(other.start_),
2420 search_position_(other.search_position_),
2421 bytes_to_read_(other.bytes_to_read_),
2422 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2425 #endif // defined(BOOST_ASIO_HAS_MOVE)
2427 void operator()(boost::system::error_code ec,
2428 std::size_t bytes_transferred, int start = 0)
2430 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2432 switch (start_ = start)
2438 // Determine the range of the data to be searched.
2439 typedef typename DynamicBuffer_v2::const_buffers_type
2441 typedef buffers_iterator<buffers_type> iterator;
2442 buffers_type data_buffers =
2443 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2444 0, buffers_.size());
2445 iterator begin = iterator::begin(data_buffers);
2446 iterator start_pos = begin + search_position_;
2447 iterator end = iterator::end(data_buffers);
2449 // Look for a match.
2450 std::pair<iterator, bool> result = detail::partial_search(
2451 start_pos, end, delim_.begin(), delim_.end());
2452 if (result.first != end && result.second)
2454 // Full match. We're done.
2455 search_position_ = result.first - begin + delim_.length();
2459 // No match yet. Check if buffer is full.
2460 else if (buffers_.size() == buffers_.max_size())
2462 search_position_ = not_found;
2466 // Need to read some more data.
2469 if (result.first != end)
2471 // Partial match. Next search needs to start from beginning of
2473 search_position_ = result.first - begin;
2477 // Next search can start with the new data.
2478 search_position_ = end - begin;
2481 bytes_to_read_ = std::min<std::size_t>(
2482 std::max<std::size_t>(512,
2483 buffers_.capacity() - buffers_.size()),
2484 std::min<std::size_t>(65536,
2485 buffers_.max_size() - buffers_.size()));
2489 // Check if we're done.
2490 if (!start && bytes_to_read_ == 0)
2493 // Start a new asynchronous read operation to obtain more data.
2494 pos = buffers_.size();
2495 buffers_.grow(bytes_to_read_);
2497 BOOST_ASIO_HANDLER_LOCATION((
2498 __FILE__, __LINE__, "async_read_until"));
2499 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2500 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));
2503 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2504 if (ec || bytes_transferred == 0)
2506 if (this->cancelled() != cancellation_type::none)
2508 ec = error::operation_aborted;
2513 const boost::system::error_code result_ec =
2514 (search_position_ == not_found)
2515 ? error::not_found : ec;
2517 const std::size_t result_n =
2518 (ec || search_position_ == not_found)
2519 ? 0 : search_position_;
2521 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
2526 AsyncReadStream& stream_;
2527 DynamicBuffer_v2 buffers_;
2530 std::size_t search_position_;
2531 std::size_t bytes_to_read_;
2532 ReadHandler handler_;
2535 template <typename AsyncReadStream,
2536 typename DynamicBuffer_v2, typename ReadHandler>
2537 inline asio_handler_allocate_is_deprecated
2538 asio_handler_allocate(std::size_t size,
2539 read_until_delim_string_op_v2<AsyncReadStream,
2540 DynamicBuffer_v2, ReadHandler>* this_handler)
2542 #if defined(BOOST_ASIO_NO_DEPRECATED)
2543 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2544 return asio_handler_allocate_is_no_longer_used();
2545 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2546 return boost_asio_handler_alloc_helpers::allocate(
2547 size, this_handler->handler_);
2548 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2551 template <typename AsyncReadStream,
2552 typename DynamicBuffer_v2, typename ReadHandler>
2553 inline asio_handler_deallocate_is_deprecated
2554 asio_handler_deallocate(void* pointer, std::size_t size,
2555 read_until_delim_string_op_v2<AsyncReadStream,
2556 DynamicBuffer_v2, ReadHandler>* this_handler)
2558 boost_asio_handler_alloc_helpers::deallocate(
2559 pointer, size, this_handler->handler_);
2560 #if defined(BOOST_ASIO_NO_DEPRECATED)
2561 return asio_handler_deallocate_is_no_longer_used();
2562 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2565 template <typename AsyncReadStream,
2566 typename DynamicBuffer_v2, typename ReadHandler>
2567 inline bool asio_handler_is_continuation(
2568 read_until_delim_string_op_v2<AsyncReadStream,
2569 DynamicBuffer_v2, ReadHandler>* this_handler)
2571 return this_handler->start_ == 0 ? true
2572 : boost_asio_handler_cont_helpers::is_continuation(
2573 this_handler->handler_);
2576 template <typename Function, typename AsyncReadStream,
2577 typename DynamicBuffer_v2, typename ReadHandler>
2578 inline asio_handler_invoke_is_deprecated
2579 asio_handler_invoke(Function& function,
2580 read_until_delim_string_op_v2<AsyncReadStream,
2581 DynamicBuffer_v2, ReadHandler>* this_handler)
2583 boost_asio_handler_invoke_helpers::invoke(
2584 function, this_handler->handler_);
2585 #if defined(BOOST_ASIO_NO_DEPRECATED)
2586 return asio_handler_invoke_is_no_longer_used();
2587 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2590 template <typename Function, typename AsyncReadStream,
2591 typename DynamicBuffer_v2, typename ReadHandler>
2592 inline asio_handler_invoke_is_deprecated
2593 asio_handler_invoke(const Function& function,
2594 read_until_delim_string_op_v2<AsyncReadStream,
2595 DynamicBuffer_v2, ReadHandler>* this_handler)
2597 boost_asio_handler_invoke_helpers::invoke(
2598 function, this_handler->handler_);
2599 #if defined(BOOST_ASIO_NO_DEPRECATED)
2600 return asio_handler_invoke_is_no_longer_used();
2601 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2604 template <typename AsyncReadStream>
2605 class initiate_async_read_until_delim_string_v2
2608 typedef typename AsyncReadStream::executor_type executor_type;
2610 explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)
2615 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2617 return stream_.get_executor();
2620 template <typename ReadHandler, typename DynamicBuffer_v2>
2621 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2622 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2623 const std::string& delim) const
2625 // If you get an error on the following line it means that your handler
2626 // does not meet the documented type requirements for a ReadHandler.
2627 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2629 non_const_lvalue<ReadHandler> handler2(handler);
2630 read_until_delim_string_op_v2<AsyncReadStream,
2631 typename decay<DynamicBuffer_v2>::type,
2632 typename decay<ReadHandler>::type>(
2633 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2634 delim, handler2.value)(boost::system::error_code(), 0, 1);
2638 AsyncReadStream& stream_;
2640 } // namespace detail
2642 #if !defined(GENERATING_DOCUMENTATION)
2644 template <template <typename, typename> class Associator,
2645 typename AsyncReadStream, typename DynamicBuffer_v2,
2646 typename ReadHandler, typename DefaultCandidate>
2647 struct associator<Associator,
2648 detail::read_until_delim_string_op_v2<AsyncReadStream,
2649 DynamicBuffer_v2, ReadHandler>,
2651 : Associator<ReadHandler, DefaultCandidate>
2653 static typename Associator<ReadHandler, DefaultCandidate>::type get(
2654 const detail::read_until_delim_string_op_v2<AsyncReadStream,
2655 DynamicBuffer_v2, ReadHandler>& h,
2656 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
2658 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
2662 #endif // !defined(GENERATING_DOCUMENTATION)
2664 template <typename AsyncReadStream,
2665 typename DynamicBuffer_v2,
2666 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2667 std::size_t)) ReadToken>
2668 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2669 void (boost::system::error_code, std::size_t))
2670 async_read_until(AsyncReadStream& s,
2671 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
2672 BOOST_ASIO_MOVE_ARG(ReadToken) token,
2673 typename constraint<
2674 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2677 return async_initiate<ReadToken,
2678 void (boost::system::error_code, std::size_t)>(
2679 detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),
2680 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2681 static_cast<std::string>(delim));
2684 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
2685 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
2689 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2690 typename RegEx, typename ReadHandler>
2691 class read_until_expr_op_v2
2692 : public base_from_cancellation_state<ReadHandler>
2695 template <typename BufferSequence>
2696 read_until_expr_op_v2(AsyncReadStream& stream,
2697 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2698 const boost::regex& expr, ReadHandler& handler)
2699 : base_from_cancellation_state<ReadHandler>(
2700 handler, enable_partial_cancellation()),
2702 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2705 search_position_(0),
2707 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2711 #if defined(BOOST_ASIO_HAS_MOVE)
2712 read_until_expr_op_v2(const read_until_expr_op_v2& other)
2713 : base_from_cancellation_state<ReadHandler>(other),
2714 stream_(other.stream_),
2715 buffers_(other.buffers_),
2717 start_(other.start_),
2718 search_position_(other.search_position_),
2719 bytes_to_read_(other.bytes_to_read_),
2720 handler_(other.handler_)
2724 read_until_expr_op_v2(read_until_expr_op_v2&& other)
2725 : base_from_cancellation_state<ReadHandler>(
2726 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
2727 ReadHandler>)(other)),
2728 stream_(other.stream_),
2729 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2731 start_(other.start_),
2732 search_position_(other.search_position_),
2733 bytes_to_read_(other.bytes_to_read_),
2734 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2737 #endif // defined(BOOST_ASIO_HAS_MOVE)
2739 void operator()(boost::system::error_code ec,
2740 std::size_t bytes_transferred, int start = 0)
2742 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2744 switch (start_ = start)
2750 // Determine the range of the data to be searched.
2751 typedef typename DynamicBuffer_v2::const_buffers_type
2753 typedef buffers_iterator<buffers_type> iterator;
2754 buffers_type data_buffers =
2755 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2756 0, buffers_.size());
2757 iterator begin = iterator::begin(data_buffers);
2758 iterator start_pos = begin + search_position_;
2759 iterator end = iterator::end(data_buffers);
2761 // Look for a match.
2762 boost::match_results<iterator,
2763 typename std::vector<boost::sub_match<iterator> >::allocator_type>
2765 bool match = regex_search(start_pos, end, match_results, expr_,
2766 boost::match_default | boost::match_partial);
2767 if (match && match_results[0].matched)
2769 // Full match. We're done.
2770 search_position_ = match_results[0].second - begin;
2774 // No match yet. Check if buffer is full.
2775 else if (buffers_.size() == buffers_.max_size())
2777 search_position_ = not_found;
2781 // Need to read some more data.
2786 // Partial match. Next search needs to start from beginning of
2788 search_position_ = match_results[0].first - begin;
2792 // Next search can start with the new data.
2793 search_position_ = end - begin;
2796 bytes_to_read_ = std::min<std::size_t>(
2797 std::max<std::size_t>(512,
2798 buffers_.capacity() - buffers_.size()),
2799 std::min<std::size_t>(65536,
2800 buffers_.max_size() - buffers_.size()));
2804 // Check if we're done.
2805 if (!start && bytes_to_read_ == 0)
2808 // Start a new asynchronous read operation to obtain more data.
2809 pos = buffers_.size();
2810 buffers_.grow(bytes_to_read_);
2812 BOOST_ASIO_HANDLER_LOCATION((
2813 __FILE__, __LINE__, "async_read_until"));
2814 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2815 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));
2818 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2819 if (ec || bytes_transferred == 0)
2821 if (this->cancelled() != cancellation_type::none)
2823 ec = error::operation_aborted;
2828 const boost::system::error_code result_ec =
2829 (search_position_ == not_found)
2830 ? error::not_found : ec;
2832 const std::size_t result_n =
2833 (ec || search_position_ == not_found)
2834 ? 0 : search_position_;
2836 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
2841 AsyncReadStream& stream_;
2842 DynamicBuffer_v2 buffers_;
2845 std::size_t search_position_;
2846 std::size_t bytes_to_read_;
2847 ReadHandler handler_;
2850 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2851 typename RegEx, typename ReadHandler>
2852 inline asio_handler_allocate_is_deprecated
2853 asio_handler_allocate(std::size_t size,
2854 read_until_expr_op_v2<AsyncReadStream,
2855 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2857 #if defined(BOOST_ASIO_NO_DEPRECATED)
2858 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2859 return asio_handler_allocate_is_no_longer_used();
2860 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2861 return boost_asio_handler_alloc_helpers::allocate(
2862 size, this_handler->handler_);
2863 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2866 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2867 typename RegEx, typename ReadHandler>
2868 inline asio_handler_deallocate_is_deprecated
2869 asio_handler_deallocate(void* pointer, std::size_t size,
2870 read_until_expr_op_v2<AsyncReadStream,
2871 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2873 boost_asio_handler_alloc_helpers::deallocate(
2874 pointer, size, this_handler->handler_);
2875 #if defined(BOOST_ASIO_NO_DEPRECATED)
2876 return asio_handler_deallocate_is_no_longer_used();
2877 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2880 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2881 typename RegEx, typename ReadHandler>
2882 inline bool asio_handler_is_continuation(
2883 read_until_expr_op_v2<AsyncReadStream,
2884 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2886 return this_handler->start_ == 0 ? true
2887 : boost_asio_handler_cont_helpers::is_continuation(
2888 this_handler->handler_);
2891 template <typename Function, typename AsyncReadStream,
2892 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2893 inline asio_handler_invoke_is_deprecated
2894 asio_handler_invoke(Function& function,
2895 read_until_expr_op_v2<AsyncReadStream,
2896 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2898 boost_asio_handler_invoke_helpers::invoke(
2899 function, this_handler->handler_);
2900 #if defined(BOOST_ASIO_NO_DEPRECATED)
2901 return asio_handler_invoke_is_no_longer_used();
2902 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2905 template <typename Function, typename AsyncReadStream,
2906 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2907 inline asio_handler_invoke_is_deprecated
2908 asio_handler_invoke(const Function& function,
2909 read_until_expr_op_v2<AsyncReadStream,
2910 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2912 boost_asio_handler_invoke_helpers::invoke(
2913 function, this_handler->handler_);
2914 #if defined(BOOST_ASIO_NO_DEPRECATED)
2915 return asio_handler_invoke_is_no_longer_used();
2916 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2919 template <typename AsyncReadStream>
2920 class initiate_async_read_until_expr_v2
2923 typedef typename AsyncReadStream::executor_type executor_type;
2925 explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)
2930 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2932 return stream_.get_executor();
2935 template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>
2936 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2937 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2938 const RegEx& expr) const
2940 // If you get an error on the following line it means that your handler
2941 // does not meet the documented type requirements for a ReadHandler.
2942 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2944 non_const_lvalue<ReadHandler> handler2(handler);
2945 read_until_expr_op_v2<AsyncReadStream,
2946 typename decay<DynamicBuffer_v2>::type,
2947 RegEx, typename decay<ReadHandler>::type>(
2948 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2949 expr, handler2.value)(boost::system::error_code(), 0, 1);
2953 AsyncReadStream& stream_;
2955 } // namespace detail
2957 #if !defined(GENERATING_DOCUMENTATION)
2959 template <template <typename, typename> class Associator,
2960 typename AsyncReadStream, typename DynamicBuffer_v2,
2961 typename RegEx, typename ReadHandler, typename DefaultCandidate>
2962 struct associator<Associator,
2963 detail::read_until_expr_op_v2<AsyncReadStream,
2964 DynamicBuffer_v2, RegEx, ReadHandler>,
2966 : Associator<ReadHandler, DefaultCandidate>
2968 static typename Associator<ReadHandler, DefaultCandidate>::type get(
2969 const detail::read_until_expr_op_v2<AsyncReadStream,
2970 DynamicBuffer_v2, RegEx, ReadHandler>& h,
2971 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
2973 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
2977 #endif // !defined(GENERATING_DOCUMENTATION)
2979 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2980 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2981 std::size_t)) ReadToken>
2982 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
2983 void (boost::system::error_code, std::size_t))
2984 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
2985 const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadToken) token,
2986 typename constraint<
2987 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2990 return async_initiate<ReadToken,
2991 void (boost::system::error_code, std::size_t)>(
2992 detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),
2993 token, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);
2996 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
3000 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3001 typename MatchCondition, typename ReadHandler>
3002 class read_until_match_op_v2
3003 : public base_from_cancellation_state<ReadHandler>
3006 template <typename BufferSequence>
3007 read_until_match_op_v2(AsyncReadStream& stream,
3008 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
3009 MatchCondition match_condition, ReadHandler& handler)
3010 : base_from_cancellation_state<ReadHandler>(
3011 handler, enable_partial_cancellation()),
3013 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
3014 match_condition_(match_condition),
3016 search_position_(0),
3018 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
3022 #if defined(BOOST_ASIO_HAS_MOVE)
3023 read_until_match_op_v2(const read_until_match_op_v2& other)
3024 : base_from_cancellation_state<ReadHandler>(other),
3025 stream_(other.stream_),
3026 buffers_(other.buffers_),
3027 match_condition_(other.match_condition_),
3028 start_(other.start_),
3029 search_position_(other.search_position_),
3030 bytes_to_read_(other.bytes_to_read_),
3031 handler_(other.handler_)
3035 read_until_match_op_v2(read_until_match_op_v2&& other)
3036 : base_from_cancellation_state<ReadHandler>(
3037 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
3038 ReadHandler>)(other)),
3039 stream_(other.stream_),
3040 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
3041 match_condition_(other.match_condition_),
3042 start_(other.start_),
3043 search_position_(other.search_position_),
3044 bytes_to_read_(other.bytes_to_read_),
3045 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
3048 #endif // defined(BOOST_ASIO_HAS_MOVE)
3050 void operator()(boost::system::error_code ec,
3051 std::size_t bytes_transferred, int start = 0)
3053 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
3055 switch (start_ = start)
3061 // Determine the range of the data to be searched.
3062 typedef typename DynamicBuffer_v2::const_buffers_type
3064 typedef buffers_iterator<buffers_type> iterator;
3065 buffers_type data_buffers =
3066 const_cast<const DynamicBuffer_v2&>(buffers_).data(
3067 0, buffers_.size());
3068 iterator begin = iterator::begin(data_buffers);
3069 iterator start_pos = begin + search_position_;
3070 iterator end = iterator::end(data_buffers);
3072 // Look for a match.
3073 std::pair<iterator, bool> result = match_condition_(start_pos, end);
3076 // Full match. We're done.
3077 search_position_ = result.first - begin;
3081 // No match yet. Check if buffer is full.
3082 else if (buffers_.size() == buffers_.max_size())
3084 search_position_ = not_found;
3088 // Need to read some more data.
3091 if (result.first != end)
3093 // Partial match. Next search needs to start from beginning of
3095 search_position_ = result.first - begin;
3099 // Next search can start with the new data.
3100 search_position_ = end - begin;
3103 bytes_to_read_ = std::min<std::size_t>(
3104 std::max<std::size_t>(512,
3105 buffers_.capacity() - buffers_.size()),
3106 std::min<std::size_t>(65536,
3107 buffers_.max_size() - buffers_.size()));
3111 // Check if we're done.
3112 if (!start && bytes_to_read_ == 0)
3115 // Start a new asynchronous read operation to obtain more data.
3116 pos = buffers_.size();
3117 buffers_.grow(bytes_to_read_);
3119 BOOST_ASIO_HANDLER_LOCATION((
3120 __FILE__, __LINE__, "async_read_until"));
3121 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
3122 BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this));
3125 buffers_.shrink(bytes_to_read_ - bytes_transferred);
3126 if (ec || bytes_transferred == 0)
3128 if (this->cancelled() != cancellation_type::none)
3130 ec = error::operation_aborted;
3135 const boost::system::error_code result_ec =
3136 (search_position_ == not_found)
3137 ? error::not_found : ec;
3139 const std::size_t result_n =
3140 (ec || search_position_ == not_found)
3141 ? 0 : search_position_;
3143 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);
3148 AsyncReadStream& stream_;
3149 DynamicBuffer_v2 buffers_;
3150 MatchCondition match_condition_;
3152 std::size_t search_position_;
3153 std::size_t bytes_to_read_;
3154 ReadHandler handler_;
3157 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3158 typename MatchCondition, typename ReadHandler>
3159 inline asio_handler_allocate_is_deprecated
3160 asio_handler_allocate(std::size_t size,
3161 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3162 MatchCondition, ReadHandler>* this_handler)
3164 #if defined(BOOST_ASIO_NO_DEPRECATED)
3165 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
3166 return asio_handler_allocate_is_no_longer_used();
3167 #else // defined(BOOST_ASIO_NO_DEPRECATED)
3168 return boost_asio_handler_alloc_helpers::allocate(
3169 size, this_handler->handler_);
3170 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3173 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3174 typename MatchCondition, typename ReadHandler>
3175 inline asio_handler_deallocate_is_deprecated
3176 asio_handler_deallocate(void* pointer, std::size_t size,
3177 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3178 MatchCondition, ReadHandler>* this_handler)
3180 boost_asio_handler_alloc_helpers::deallocate(
3181 pointer, size, this_handler->handler_);
3182 #if defined(BOOST_ASIO_NO_DEPRECATED)
3183 return asio_handler_deallocate_is_no_longer_used();
3184 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3187 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3188 typename MatchCondition, typename ReadHandler>
3189 inline bool asio_handler_is_continuation(
3190 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3191 MatchCondition, ReadHandler>* this_handler)
3193 return this_handler->start_ == 0 ? true
3194 : boost_asio_handler_cont_helpers::is_continuation(
3195 this_handler->handler_);
3198 template <typename Function, typename AsyncReadStream,
3199 typename DynamicBuffer_v2, typename MatchCondition,
3200 typename ReadHandler>
3201 inline asio_handler_invoke_is_deprecated
3202 asio_handler_invoke(Function& function,
3203 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3204 MatchCondition, ReadHandler>* this_handler)
3206 boost_asio_handler_invoke_helpers::invoke(
3207 function, this_handler->handler_);
3208 #if defined(BOOST_ASIO_NO_DEPRECATED)
3209 return asio_handler_invoke_is_no_longer_used();
3210 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3213 template <typename Function, typename AsyncReadStream,
3214 typename DynamicBuffer_v2, typename MatchCondition,
3215 typename ReadHandler>
3216 inline asio_handler_invoke_is_deprecated
3217 asio_handler_invoke(const Function& function,
3218 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3219 MatchCondition, ReadHandler>* this_handler)
3221 boost_asio_handler_invoke_helpers::invoke(
3222 function, this_handler->handler_);
3223 #if defined(BOOST_ASIO_NO_DEPRECATED)
3224 return asio_handler_invoke_is_no_longer_used();
3225 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3228 template <typename AsyncReadStream>
3229 class initiate_async_read_until_match_v2
3232 typedef typename AsyncReadStream::executor_type executor_type;
3234 explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)
3239 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
3241 return stream_.get_executor();
3244 template <typename ReadHandler,
3245 typename DynamicBuffer_v2, typename MatchCondition>
3246 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3247 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
3248 MatchCondition match_condition) const
3250 // If you get an error on the following line it means that your handler
3251 // does not meet the documented type requirements for a ReadHandler.
3252 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
3254 non_const_lvalue<ReadHandler> handler2(handler);
3255 read_until_match_op_v2<AsyncReadStream,
3256 typename decay<DynamicBuffer_v2>::type,
3257 MatchCondition, typename decay<ReadHandler>::type>(
3258 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
3259 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
3263 AsyncReadStream& stream_;
3265 } // namespace detail
3267 #if !defined(GENERATING_DOCUMENTATION)
3269 template <template <typename, typename> class Associator,
3270 typename AsyncReadStream, typename DynamicBuffer_v2,
3271 typename MatchCondition, typename ReadHandler, typename DefaultCandidate>
3272 struct associator<Associator,
3273 detail::read_until_match_op_v2<AsyncReadStream,
3274 DynamicBuffer_v2, MatchCondition, ReadHandler>,
3276 : Associator<ReadHandler, DefaultCandidate>
3278 static typename Associator<ReadHandler, DefaultCandidate>::type get(
3279 const detail::read_until_match_op_v2<AsyncReadStream,
3280 DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
3281 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
3283 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
3287 #endif // !defined(GENERATING_DOCUMENTATION)
3289 template <typename AsyncReadStream,
3290 typename DynamicBuffer_v2, typename MatchCondition,
3291 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
3292 std::size_t)) ReadToken>
3293 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
3294 void (boost::system::error_code, std::size_t))
3295 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
3296 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadToken) token,
3297 typename constraint<
3298 is_match_condition<MatchCondition>::value
3300 typename constraint<
3301 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
3304 return async_initiate<ReadToken,
3305 void (boost::system::error_code, std::size_t)>(
3306 detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), token,
3307 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);
3310 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
3313 } // namespace boost
3315 #include <boost/asio/detail/pop_options.hpp>
3317 #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP