1 //
2 // impl/read_until.hpp
3 // ~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #ifndef BOOST_ASIO_IMPL_READ_UNTIL_HPP
12 #define BOOST_ASIO_IMPL_READ_UNTIL_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <algorithm>
19 #include <string>
20 #include <vector>
21 #include <utility>
22 #include <boost/asio/associated_allocator.hpp>
23 #include <boost/asio/associated_executor.hpp>
24 #include <boost/asio/buffer.hpp>
25 #include <boost/asio/buffers_iterator.hpp>
26 #include <boost/asio/detail/bind_handler.hpp>
27 #include <boost/asio/detail/handler_alloc_helpers.hpp>
28 #include <boost/asio/detail/handler_cont_helpers.hpp>
29 #include <boost/asio/detail/handler_invoke_helpers.hpp>
30 #include <boost/asio/detail/handler_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>
35
36 #include <boost/asio/detail/push_options.hpp>
37
38 namespace boost {
39 namespace asio {
40
41 namespace detail
42 {
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>
partial_search(Iterator1 first1,Iterator1 last1,Iterator2 first2,Iterator2 last2)50 std::pair<Iterator1, bool> partial_search(
51 Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
52 {
53 for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
54 {
55 Iterator1 test_iter1 = iter1;
56 Iterator2 test_iter2 = first2;
57 for (;; ++test_iter1, ++test_iter2)
58 {
59 if (test_iter2 == last2)
60 return std::make_pair(iter1, true);
61 if (test_iter1 == last1)
62 {
63 if (test_iter2 != first2)
64 return std::make_pair(iter1, false);
65 else
66 break;
67 }
68 if (*test_iter1 != *test_iter2)
69 break;
70 }
71 }
72 return std::make_pair(last1, false);
73 }
74 } // namespace detail
75
76 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
77
78 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,char delim,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)79 inline std::size_t read_until(SyncReadStream& s,
80 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,
81 typename constraint<
82 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
83 >::type,
84 typename constraint<
85 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
86 >::type)
87 {
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;
93 }
94
95 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,char delim,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)96 std::size_t read_until(SyncReadStream& s,
97 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
98 char delim, boost::system::error_code& ec,
99 typename constraint<
100 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
101 >::type,
102 typename constraint<
103 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
104 >::type)
105 {
106 typename decay<DynamicBuffer_v1>::type b(
107 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
108
109 std::size_t search_position = 0;
110 for (;;)
111 {
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);
119
120 // Look for a match.
121 iterator iter = std::find(start_pos, end, delim);
122 if (iter != end)
123 {
124 // Found a match. We're done.
125 ec = boost::system::error_code();
126 return iter - begin + 1;
127 }
128 else
129 {
130 // No match. Next search can start with the new data.
131 search_position = end - begin;
132 }
133
134 // Check if buffer is full.
135 if (b.size() == b.max_size())
136 {
137 ec = error::not_found;
138 return 0;
139 }
140
141 // Need more data.
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));
146 if (ec)
147 return 0;
148 }
149 }
150
151 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,BOOST_ASIO_STRING_VIEW_PARAM delim,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)152 inline std::size_t read_until(SyncReadStream& s,
153 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
154 BOOST_ASIO_STRING_VIEW_PARAM delim,
155 typename constraint<
156 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
157 >::type,
158 typename constraint<
159 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
160 >::type)
161 {
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;
167 }
168
169 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,BOOST_ASIO_STRING_VIEW_PARAM delim,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)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,
173 typename constraint<
174 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
175 >::type,
176 typename constraint<
177 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
178 >::type)
179 {
180 typename decay<DynamicBuffer_v1>::type b(
181 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
182
183 std::size_t search_position = 0;
184 for (;;)
185 {
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);
193
194 // Look for a match.
195 std::pair<iterator, bool> result = detail::partial_search(
196 start_pos, end, delim.begin(), delim.end());
197 if (result.first != end)
198 {
199 if (result.second)
200 {
201 // Full match. We're done.
202 ec = boost::system::error_code();
203 return result.first - begin + delim.length();
204 }
205 else
206 {
207 // Partial match. Next search needs to start from beginning of match.
208 search_position = result.first - begin;
209 }
210 }
211 else
212 {
213 // No match. Next search can start with the new data.
214 search_position = end - begin;
215 }
216
217 // Check if buffer is full.
218 if (b.size() == b.max_size())
219 {
220 ec = error::not_found;
221 return 0;
222 }
223
224 // Need more data.
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));
229 if (ec)
230 return 0;
231 }
232 }
233
234 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
235 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
236
237 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,const boost::regex & expr,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)238 inline std::size_t read_until(SyncReadStream& s,
239 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
240 const boost::regex& expr,
241 typename constraint<
242 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
243 >::type,
244 typename constraint<
245 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
246 >::type)
247 {
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;
253 }
254
255 template <typename SyncReadStream, typename DynamicBuffer_v1>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,const boost::regex & expr,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)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,
259 typename constraint<
260 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
261 >::type,
262 typename constraint<
263 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
264 >::type)
265 {
266 typename decay<DynamicBuffer_v1>::type b(
267 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
268
269 std::size_t search_position = 0;
270 for (;;)
271 {
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);
279
280 // Look for a match.
281 boost::match_results<iterator,
282 typename std::vector<boost::sub_match<iterator> >::allocator_type>
283 match_results;
284 if (regex_search(start_pos, end, match_results, expr,
285 boost::match_default | boost::match_partial))
286 {
287 if (match_results[0].matched)
288 {
289 // Full match. We're done.
290 ec = boost::system::error_code();
291 return match_results[0].second - begin;
292 }
293 else
294 {
295 // Partial match. Next search needs to start from beginning of match.
296 search_position = match_results[0].first - begin;
297 }
298 }
299 else
300 {
301 // No match. Next search can start with the new data.
302 search_position = end - begin;
303 }
304
305 // Check if buffer is full.
306 if (b.size() == b.max_size())
307 {
308 ec = error::not_found;
309 return 0;
310 }
311
312 // Need more data.
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));
317 if (ec)
318 return 0;
319 }
320 }
321
322 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
323
324 template <typename SyncReadStream,
325 typename DynamicBuffer_v1, typename MatchCondition>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,MatchCondition match_condition,typename constraint<is_match_condition<MatchCondition>::value>::type,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)326 inline std::size_t read_until(SyncReadStream& s,
327 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
328 MatchCondition match_condition,
329 typename constraint<
330 is_match_condition<MatchCondition>::value
331 >::type,
332 typename constraint<
333 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
334 >::type,
335 typename constraint<
336 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
337 >::type)
338 {
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;
345 }
346
347 template <typename SyncReadStream,
348 typename DynamicBuffer_v1, typename MatchCondition>
read_until(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,MatchCondition match_condition,boost::system::error_code & ec,typename constraint<is_match_condition<MatchCondition>::value>::type,typename constraint<is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value>::type,typename constraint<!is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value>::type)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,
352 typename constraint<
353 is_match_condition<MatchCondition>::value
354 >::type,
355 typename constraint<
356 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
357 >::type,
358 typename constraint<
359 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
360 >::type)
361 {
362 typename decay<DynamicBuffer_v1>::type b(
363 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
364
365 std::size_t search_position = 0;
366 for (;;)
367 {
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);
375
376 // Look for a match.
377 std::pair<iterator, bool> result = match_condition(start_pos, end);
378 if (result.second)
379 {
380 // Full match. We're done.
381 ec = boost::system::error_code();
382 return result.first - begin;
383 }
384 else if (result.first != end)
385 {
386 // Partial match. Next search needs to start from beginning of match.
387 search_position = result.first - begin;
388 }
389 else
390 {
391 // No match. Next search can start with the new data.
392 search_position = end - begin;
393 }
394
395 // Check if buffer is full.
396 if (b.size() == b.max_size())
397 {
398 ec = error::not_found;
399 return 0;
400 }
401
402 // Need more data.
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));
407 if (ec)
408 return 0;
409 }
410 }
411
412 #if !defined(BOOST_ASIO_NO_IOSTREAM)
413
414 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,char delim)415 inline std::size_t read_until(SyncReadStream& s,
416 boost::asio::basic_streambuf<Allocator>& b, char delim)
417 {
418 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
419 }
420
421 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,char delim,boost::system::error_code & ec)422 inline std::size_t read_until(SyncReadStream& s,
423 boost::asio::basic_streambuf<Allocator>& b, char delim,
424 boost::system::error_code& ec)
425 {
426 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
427 }
428
429 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,BOOST_ASIO_STRING_VIEW_PARAM delim)430 inline std::size_t read_until(SyncReadStream& s,
431 boost::asio::basic_streambuf<Allocator>& b,
432 BOOST_ASIO_STRING_VIEW_PARAM delim)
433 {
434 return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
435 }
436
437 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,BOOST_ASIO_STRING_VIEW_PARAM delim,boost::system::error_code & ec)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)
441 {
442 return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
443 }
444
445 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
446
447 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,const boost::regex & expr)448 inline std::size_t read_until(SyncReadStream& s,
449 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
450 {
451 return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
452 }
453
454 template <typename SyncReadStream, typename Allocator>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,const boost::regex & expr,boost::system::error_code & ec)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)
458 {
459 return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
460 }
461
462 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
463
464 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,MatchCondition match_condition,typename constraint<is_match_condition<MatchCondition>::value>::type)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)
468 {
469 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
470 }
471
472 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
read_until(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,MatchCondition match_condition,boost::system::error_code & ec,typename constraint<is_match_condition<MatchCondition>::value>::type)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)
477 {
478 return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
479 }
480
481 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
482 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
483 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
484
485 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,char delim,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)486 inline std::size_t read_until(SyncReadStream& s,
487 DynamicBuffer_v2 buffers, char delim,
488 typename constraint<
489 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
490 >::type)
491 {
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;
497 }
498
499 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,char delim,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)500 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
501 char delim, boost::system::error_code& ec,
502 typename constraint<
503 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
504 >::type)
505 {
506 DynamicBuffer_v2& b = buffers;
507
508 std::size_t search_position = 0;
509 for (;;)
510 {
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);
519
520 // Look for a match.
521 iterator iter = std::find(start_pos, end, delim);
522 if (iter != end)
523 {
524 // Found a match. We're done.
525 ec = boost::system::error_code();
526 return iter - begin + 1;
527 }
528 else
529 {
530 // No match. Next search can start with the new data.
531 search_position = end - begin;
532 }
533
534 // Check if buffer is full.
535 if (b.size() == b.max_size())
536 {
537 ec = error::not_found;
538 return 0;
539 }
540
541 // Need more data.
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);
549 if (ec)
550 return 0;
551 }
552 }
553
554 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,BOOST_ASIO_STRING_VIEW_PARAM delim,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)555 inline std::size_t read_until(SyncReadStream& s,
556 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
557 typename constraint<
558 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
559 >::type)
560 {
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;
566 }
567
568 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,BOOST_ASIO_STRING_VIEW_PARAM delim,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)569 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
570 BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec,
571 typename constraint<
572 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
573 >::type)
574 {
575 DynamicBuffer_v2& b = buffers;
576
577 std::size_t search_position = 0;
578 for (;;)
579 {
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);
588
589 // Look for a match.
590 std::pair<iterator, bool> result = detail::partial_search(
591 start_pos, end, delim.begin(), delim.end());
592 if (result.first != end)
593 {
594 if (result.second)
595 {
596 // Full match. We're done.
597 ec = boost::system::error_code();
598 return result.first - begin + delim.length();
599 }
600 else
601 {
602 // Partial match. Next search needs to start from beginning of match.
603 search_position = result.first - begin;
604 }
605 }
606 else
607 {
608 // No match. Next search can start with the new data.
609 search_position = end - begin;
610 }
611
612 // Check if buffer is full.
613 if (b.size() == b.max_size())
614 {
615 ec = error::not_found;
616 return 0;
617 }
618
619 // Need more data.
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);
627 if (ec)
628 return 0;
629 }
630 }
631
632 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
633 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
634
635 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,const boost::regex & expr,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)636 inline std::size_t read_until(SyncReadStream& s,
637 DynamicBuffer_v2 buffers, const boost::regex& expr,
638 typename constraint<
639 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
640 >::type)
641 {
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;
647 }
648
649 template <typename SyncReadStream, typename DynamicBuffer_v2>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,const boost::regex & expr,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)650 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
651 const boost::regex& expr, boost::system::error_code& ec,
652 typename constraint<
653 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
654 >::type)
655 {
656 DynamicBuffer_v2& b = buffers;
657
658 std::size_t search_position = 0;
659 for (;;)
660 {
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);
669
670 // Look for a match.
671 boost::match_results<iterator,
672 typename std::vector<boost::sub_match<iterator> >::allocator_type>
673 match_results;
674 if (regex_search(start_pos, end, match_results, expr,
675 boost::match_default | boost::match_partial))
676 {
677 if (match_results[0].matched)
678 {
679 // Full match. We're done.
680 ec = boost::system::error_code();
681 return match_results[0].second - begin;
682 }
683 else
684 {
685 // Partial match. Next search needs to start from beginning of match.
686 search_position = match_results[0].first - begin;
687 }
688 }
689 else
690 {
691 // No match. Next search can start with the new data.
692 search_position = end - begin;
693 }
694
695 // Check if buffer is full.
696 if (b.size() == b.max_size())
697 {
698 ec = error::not_found;
699 return 0;
700 }
701
702 // Need more data.
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);
710 if (ec)
711 return 0;
712 }
713 }
714
715 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
716
717 template <typename SyncReadStream,
718 typename DynamicBuffer_v2, typename MatchCondition>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,MatchCondition match_condition,typename constraint<is_match_condition<MatchCondition>::value>::type,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)719 inline std::size_t read_until(SyncReadStream& s,
720 DynamicBuffer_v2 buffers, MatchCondition match_condition,
721 typename constraint<
722 is_match_condition<MatchCondition>::value
723 >::type,
724 typename constraint<
725 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
726 >::type)
727 {
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;
734 }
735
736 template <typename SyncReadStream,
737 typename DynamicBuffer_v2, typename MatchCondition>
read_until(SyncReadStream & s,DynamicBuffer_v2 buffers,MatchCondition match_condition,boost::system::error_code & ec,typename constraint<is_match_condition<MatchCondition>::value>::type,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)738 std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,
739 MatchCondition match_condition, boost::system::error_code& ec,
740 typename constraint<
741 is_match_condition<MatchCondition>::value
742 >::type,
743 typename constraint<
744 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
745 >::type)
746 {
747 DynamicBuffer_v2& b = buffers;
748
749 std::size_t search_position = 0;
750 for (;;)
751 {
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);
760
761 // Look for a match.
762 std::pair<iterator, bool> result = match_condition(start_pos, end);
763 if (result.second)
764 {
765 // Full match. We're done.
766 ec = boost::system::error_code();
767 return result.first - begin;
768 }
769 else if (result.first != end)
770 {
771 // Partial match. Next search needs to start from beginning of match.
772 search_position = result.first - begin;
773 }
774 else
775 {
776 // No match. Next search can start with the new data.
777 search_position = end - begin;
778 }
779
780 // Check if buffer is full.
781 if (b.size() == b.max_size())
782 {
783 ec = error::not_found;
784 return 0;
785 }
786
787 // Need more data.
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);
795 if (ec)
796 return 0;
797 }
798 }
799
800 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
801
802 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
803
804 namespace detail
805 {
806 template <typename AsyncReadStream,
807 typename DynamicBuffer_v1, typename ReadHandler>
808 class read_until_delim_op_v1
809 {
810 public:
811 template <typename BufferSequence>
read_until_delim_op_v1(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,char delim,ReadHandler & handler)812 read_until_delim_op_v1(AsyncReadStream& stream,
813 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
814 char delim, ReadHandler& handler)
815 : stream_(stream),
816 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
817 delim_(delim),
818 start_(0),
819 search_position_(0),
820 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
821 {
822 }
823
824 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_op_v1(const read_until_delim_op_v1 & other)825 read_until_delim_op_v1(const read_until_delim_op_v1& other)
826 : stream_(other.stream_),
827 buffers_(other.buffers_),
828 delim_(other.delim_),
829 start_(other.start_),
830 search_position_(other.search_position_),
831 handler_(other.handler_)
832 {
833 }
834
read_until_delim_op_v1(read_until_delim_op_v1 && other)835 read_until_delim_op_v1(read_until_delim_op_v1&& other)
836 : stream_(other.stream_),
837 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
838 delim_(other.delim_),
839 start_(other.start_),
840 search_position_(other.search_position_),
841 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
842 {
843 }
844 #endif // defined(BOOST_ASIO_HAS_MOVE)
845
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)846 void operator()(const boost::system::error_code& ec,
847 std::size_t bytes_transferred, int start = 0)
848 {
849 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
850 std::size_t bytes_to_read;
851 switch (start_ = start)
852 {
853 case 1:
854 for (;;)
855 {
856 {
857 // Determine the range of the data to be searched.
858 typedef typename DynamicBuffer_v1::const_buffers_type
859 buffers_type;
860 typedef buffers_iterator<buffers_type> iterator;
861 buffers_type data_buffers = buffers_.data();
862 iterator begin = iterator::begin(data_buffers);
863 iterator start_pos = begin + search_position_;
864 iterator end = iterator::end(data_buffers);
865
866 // Look for a match.
867 iterator iter = std::find(start_pos, end, delim_);
868 if (iter != end)
869 {
870 // Found a match. We're done.
871 search_position_ = iter - begin + 1;
872 bytes_to_read = 0;
873 }
874
875 // No match yet. Check if buffer is full.
876 else if (buffers_.size() == buffers_.max_size())
877 {
878 search_position_ = not_found;
879 bytes_to_read = 0;
880 }
881
882 // Need to read some more data.
883 else
884 {
885 // Next search can start with the new data.
886 search_position_ = end - begin;
887 bytes_to_read = std::min<std::size_t>(
888 std::max<std::size_t>(512,
889 buffers_.capacity() - buffers_.size()),
890 std::min<std::size_t>(65536,
891 buffers_.max_size() - buffers_.size()));
892 }
893 }
894
895 // Check if we're done.
896 if (!start && bytes_to_read == 0)
897 break;
898
899 // Start a new asynchronous read operation to obtain more data.
900 {
901 BOOST_ASIO_HANDLER_LOCATION((
902 __FILE__, __LINE__, "async_read_until"));
903 stream_.async_read_some(buffers_.prepare(bytes_to_read),
904 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));
905 }
906 return; default:
907 buffers_.commit(bytes_transferred);
908 if (ec || bytes_transferred == 0)
909 break;
910 }
911
912 const boost::system::error_code result_ec =
913 (search_position_ == not_found)
914 ? error::not_found : ec;
915
916 const std::size_t result_n =
917 (ec || search_position_ == not_found)
918 ? 0 : search_position_;
919
920 handler_(result_ec, result_n);
921 }
922 }
923
924 //private:
925 AsyncReadStream& stream_;
926 DynamicBuffer_v1 buffers_;
927 char delim_;
928 int start_;
929 std::size_t search_position_;
930 ReadHandler handler_;
931 };
932
933 template <typename AsyncReadStream,
934 typename DynamicBuffer_v1, typename ReadHandler>
935 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_delim_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)936 asio_handler_allocate(std::size_t size,
937 read_until_delim_op_v1<AsyncReadStream,
938 DynamicBuffer_v1, ReadHandler>* this_handler)
939 {
940 #if defined(BOOST_ASIO_NO_DEPRECATED)
941 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
942 return asio_handler_allocate_is_no_longer_used();
943 #else // defined(BOOST_ASIO_NO_DEPRECATED)
944 return boost_asio_handler_alloc_helpers::allocate(
945 size, this_handler->handler_);
946 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
947 }
948
949 template <typename AsyncReadStream,
950 typename DynamicBuffer_v1, typename ReadHandler>
951 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_delim_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)952 asio_handler_deallocate(void* pointer, std::size_t size,
953 read_until_delim_op_v1<AsyncReadStream,
954 DynamicBuffer_v1, ReadHandler>* this_handler)
955 {
956 boost_asio_handler_alloc_helpers::deallocate(
957 pointer, size, this_handler->handler_);
958 #if defined(BOOST_ASIO_NO_DEPRECATED)
959 return asio_handler_deallocate_is_no_longer_used();
960 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
961 }
962
963 template <typename AsyncReadStream,
964 typename DynamicBuffer_v1, typename ReadHandler>
asio_handler_is_continuation(read_until_delim_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)965 inline bool asio_handler_is_continuation(
966 read_until_delim_op_v1<AsyncReadStream,
967 DynamicBuffer_v1, ReadHandler>* this_handler)
968 {
969 return this_handler->start_ == 0 ? true
970 : boost_asio_handler_cont_helpers::is_continuation(
971 this_handler->handler_);
972 }
973
974 template <typename Function, typename AsyncReadStream,
975 typename DynamicBuffer_v1, typename ReadHandler>
976 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_delim_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)977 asio_handler_invoke(Function& function,
978 read_until_delim_op_v1<AsyncReadStream,
979 DynamicBuffer_v1, ReadHandler>* this_handler)
980 {
981 boost_asio_handler_invoke_helpers::invoke(
982 function, this_handler->handler_);
983 #if defined(BOOST_ASIO_NO_DEPRECATED)
984 return asio_handler_invoke_is_no_longer_used();
985 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
986 }
987
988 template <typename Function, typename AsyncReadStream,
989 typename DynamicBuffer_v1, typename ReadHandler>
990 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_delim_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)991 asio_handler_invoke(const Function& function,
992 read_until_delim_op_v1<AsyncReadStream,
993 DynamicBuffer_v1, ReadHandler>* this_handler)
994 {
995 boost_asio_handler_invoke_helpers::invoke(
996 function, this_handler->handler_);
997 #if defined(BOOST_ASIO_NO_DEPRECATED)
998 return asio_handler_invoke_is_no_longer_used();
999 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1000 }
1001
1002 template <typename AsyncReadStream>
1003 class initiate_async_read_until_delim_v1
1004 {
1005 public:
1006 typedef typename AsyncReadStream::executor_type executor_type;
1007
initiate_async_read_until_delim_v1(AsyncReadStream & stream)1008 explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)
1009 : stream_(stream)
1010 {
1011 }
1012
get_executor() const1013 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1014 {
1015 return stream_.get_executor();
1016 }
1017
1018 template <typename ReadHandler, typename DynamicBuffer_v1>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,char delim) const1019 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1020 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1021 char delim) const
1022 {
1023 // If you get an error on the following line it means that your handler
1024 // does not meet the documented type requirements for a ReadHandler.
1025 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1026
1027 non_const_lvalue<ReadHandler> handler2(handler);
1028 read_until_delim_op_v1<AsyncReadStream,
1029 typename decay<DynamicBuffer_v1>::type,
1030 typename decay<ReadHandler>::type>(
1031 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1032 delim, handler2.value)(boost::system::error_code(), 0, 1);
1033 }
1034
1035 private:
1036 AsyncReadStream& stream_;
1037 };
1038 } // namespace detail
1039
1040 #if !defined(GENERATING_DOCUMENTATION)
1041
1042 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1043 typename ReadHandler, typename Allocator>
1044 struct associated_allocator<
1045 detail::read_until_delim_op_v1<AsyncReadStream,
1046 DynamicBuffer_v1, ReadHandler>,
1047 Allocator>
1048 {
1049 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1050
getboost::asio::associated_allocator1051 static type get(
1052 const detail::read_until_delim_op_v1<AsyncReadStream,
1053 DynamicBuffer_v1, ReadHandler>& h,
1054 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1055 {
1056 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1057 }
1058 };
1059
1060 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1061 typename ReadHandler, typename Executor>
1062 struct associated_executor<
1063 detail::read_until_delim_op_v1<AsyncReadStream,
1064 DynamicBuffer_v1, ReadHandler>,
1065 Executor>
1066 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
1067 {
1068 typedef typename associated_executor<ReadHandler, Executor>::type type;
1069
getboost::asio::associated_executor1070 static type get(
1071 const detail::read_until_delim_op_v1<AsyncReadStream,
1072 DynamicBuffer_v1, ReadHandler>& h,
1073 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1074 {
1075 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1076 }
1077 };
1078
1079 #endif // !defined(GENERATING_DOCUMENTATION)
1080
1081 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1082 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1083 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1084 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1085 void (boost::system::error_code, std::size_t))
1086 async_read_until(AsyncReadStream& s,
1087 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1088 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1089 typename constraint<
1090 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1091 >::type,
1092 typename constraint<
1093 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1094 >::type)
1095 {
1096 return async_initiate<ReadHandler,
1097 void (boost::system::error_code, std::size_t)>(
1098 detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),
1099 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);
1100 }
1101
1102 namespace detail
1103 {
1104 template <typename AsyncReadStream,
1105 typename DynamicBuffer_v1, typename ReadHandler>
1106 class read_until_delim_string_op_v1
1107 {
1108 public:
1109 template <typename BufferSequence>
read_until_delim_string_op_v1(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,const std::string & delim,ReadHandler & handler)1110 read_until_delim_string_op_v1(AsyncReadStream& stream,
1111 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1112 const std::string& delim, ReadHandler& handler)
1113 : stream_(stream),
1114 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1115 delim_(delim),
1116 start_(0),
1117 search_position_(0),
1118 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1119 {
1120 }
1121
1122 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_string_op_v1(const read_until_delim_string_op_v1 & other)1123 read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)
1124 : stream_(other.stream_),
1125 buffers_(other.buffers_),
1126 delim_(other.delim_),
1127 start_(other.start_),
1128 search_position_(other.search_position_),
1129 handler_(other.handler_)
1130 {
1131 }
1132
read_until_delim_string_op_v1(read_until_delim_string_op_v1 && other)1133 read_until_delim_string_op_v1(read_until_delim_string_op_v1&& 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_))
1140 {
1141 }
1142 #endif // defined(BOOST_ASIO_HAS_MOVE)
1143
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)1144 void operator()(const boost::system::error_code& ec,
1145 std::size_t bytes_transferred, int start = 0)
1146 {
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)
1150 {
1151 case 1:
1152 for (;;)
1153 {
1154 {
1155 // Determine the range of the data to be searched.
1156 typedef typename DynamicBuffer_v1::const_buffers_type
1157 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);
1163
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)
1168 {
1169 // Full match. We're done.
1170 search_position_ = result.first - begin + delim_.length();
1171 bytes_to_read = 0;
1172 }
1173
1174 // No match yet. Check if buffer is full.
1175 else if (buffers_.size() == buffers_.max_size())
1176 {
1177 search_position_ = not_found;
1178 bytes_to_read = 0;
1179 }
1180
1181 // Need to read some more data.
1182 else
1183 {
1184 if (result.first != end)
1185 {
1186 // Partial match. Next search needs to start from beginning of
1187 // match.
1188 search_position_ = result.first - begin;
1189 }
1190 else
1191 {
1192 // Next search can start with the new data.
1193 search_position_ = end - begin;
1194 }
1195
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()));
1201 }
1202 }
1203
1204 // Check if we're done.
1205 if (!start && bytes_to_read == 0)
1206 break;
1207
1208 // Start a new asynchronous read operation to obtain more data.
1209 {
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));
1214 }
1215 return; default:
1216 buffers_.commit(bytes_transferred);
1217 if (ec || bytes_transferred == 0)
1218 break;
1219 }
1220
1221 const boost::system::error_code result_ec =
1222 (search_position_ == not_found)
1223 ? error::not_found : ec;
1224
1225 const std::size_t result_n =
1226 (ec || search_position_ == not_found)
1227 ? 0 : search_position_;
1228
1229 handler_(result_ec, result_n);
1230 }
1231 }
1232
1233 //private:
1234 AsyncReadStream& stream_;
1235 DynamicBuffer_v1 buffers_;
1236 std::string delim_;
1237 int start_;
1238 std::size_t search_position_;
1239 ReadHandler handler_;
1240 };
1241
1242 template <typename AsyncReadStream,
1243 typename DynamicBuffer_v1, typename ReadHandler>
1244 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_delim_string_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)1245 asio_handler_allocate(std::size_t size,
1246 read_until_delim_string_op_v1<AsyncReadStream,
1247 DynamicBuffer_v1, ReadHandler>* this_handler)
1248 {
1249 #if defined(BOOST_ASIO_NO_DEPRECATED)
1250 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1251 return asio_handler_allocate_is_no_longer_used();
1252 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1253 return boost_asio_handler_alloc_helpers::allocate(
1254 size, this_handler->handler_);
1255 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1256 }
1257
1258 template <typename AsyncReadStream,
1259 typename DynamicBuffer_v1, typename ReadHandler>
1260 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_delim_string_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)1261 asio_handler_deallocate(void* pointer, std::size_t size,
1262 read_until_delim_string_op_v1<AsyncReadStream,
1263 DynamicBuffer_v1, ReadHandler>* this_handler)
1264 {
1265 boost_asio_handler_alloc_helpers::deallocate(
1266 pointer, size, this_handler->handler_);
1267 #if defined(BOOST_ASIO_NO_DEPRECATED)
1268 return asio_handler_deallocate_is_no_longer_used();
1269 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1270 }
1271
1272 template <typename AsyncReadStream,
1273 typename DynamicBuffer_v1, typename ReadHandler>
asio_handler_is_continuation(read_until_delim_string_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)1274 inline bool asio_handler_is_continuation(
1275 read_until_delim_string_op_v1<AsyncReadStream,
1276 DynamicBuffer_v1, ReadHandler>* this_handler)
1277 {
1278 return this_handler->start_ == 0 ? true
1279 : boost_asio_handler_cont_helpers::is_continuation(
1280 this_handler->handler_);
1281 }
1282
1283 template <typename Function, typename AsyncReadStream,
1284 typename DynamicBuffer_v1, typename ReadHandler>
1285 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_delim_string_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)1286 asio_handler_invoke(Function& function,
1287 read_until_delim_string_op_v1<AsyncReadStream,
1288 DynamicBuffer_v1, ReadHandler>* this_handler)
1289 {
1290 boost_asio_handler_invoke_helpers::invoke(
1291 function, this_handler->handler_);
1292 #if defined(BOOST_ASIO_NO_DEPRECATED)
1293 return asio_handler_invoke_is_no_longer_used();
1294 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1295 }
1296
1297 template <typename Function, typename AsyncReadStream,
1298 typename DynamicBuffer_v1, typename ReadHandler>
1299 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_delim_string_op_v1<AsyncReadStream,DynamicBuffer_v1,ReadHandler> * this_handler)1300 asio_handler_invoke(const Function& function,
1301 read_until_delim_string_op_v1<AsyncReadStream,
1302 DynamicBuffer_v1, ReadHandler>* this_handler)
1303 {
1304 boost_asio_handler_invoke_helpers::invoke(
1305 function, this_handler->handler_);
1306 #if defined(BOOST_ASIO_NO_DEPRECATED)
1307 return asio_handler_invoke_is_no_longer_used();
1308 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1309 }
1310
1311 template <typename AsyncReadStream>
1312 class initiate_async_read_until_delim_string_v1
1313 {
1314 public:
1315 typedef typename AsyncReadStream::executor_type executor_type;
1316
initiate_async_read_until_delim_string_v1(AsyncReadStream & stream)1317 explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)
1318 : stream_(stream)
1319 {
1320 }
1321
get_executor() const1322 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1323 {
1324 return stream_.get_executor();
1325 }
1326
1327 template <typename ReadHandler, typename DynamicBuffer_v1>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,const std::string & delim) const1328 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1329 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1330 const std::string& delim) const
1331 {
1332 // If you get an error on the following line it means that your handler
1333 // does not meet the documented type requirements for a ReadHandler.
1334 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1335
1336 non_const_lvalue<ReadHandler> handler2(handler);
1337 read_until_delim_string_op_v1<AsyncReadStream,
1338 typename decay<DynamicBuffer_v1>::type,
1339 typename decay<ReadHandler>::type>(
1340 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1341 delim, handler2.value)(boost::system::error_code(), 0, 1);
1342 }
1343
1344 private:
1345 AsyncReadStream& stream_;
1346 };
1347 } // namespace detail
1348
1349 #if !defined(GENERATING_DOCUMENTATION)
1350
1351 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1352 typename ReadHandler, typename Allocator>
1353 struct associated_allocator<
1354 detail::read_until_delim_string_op_v1<AsyncReadStream,
1355 DynamicBuffer_v1, ReadHandler>,
1356 Allocator>
1357 {
1358 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1359
getboost::asio::associated_allocator1360 static type get(
1361 const detail::read_until_delim_string_op_v1<AsyncReadStream,
1362 DynamicBuffer_v1, ReadHandler>& h,
1363 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1364 {
1365 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1366 }
1367 };
1368
1369 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1370 typename ReadHandler, typename Executor>
1371 struct associated_executor<
1372 detail::read_until_delim_string_op_v1<AsyncReadStream,
1373 DynamicBuffer_v1, ReadHandler>,
1374 Executor>
1375 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
1376 {
1377 typedef typename associated_executor<ReadHandler, Executor>::type type;
1378
getboost::asio::associated_executor1379 static type get(
1380 const detail::read_until_delim_string_op_v1<AsyncReadStream,
1381 DynamicBuffer_v1, ReadHandler>& h,
1382 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1383 {
1384 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1385 }
1386 };
1387
1388 #endif // !defined(GENERATING_DOCUMENTATION)
1389
1390 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1391 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1392 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1393 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1394 void (boost::system::error_code, std::size_t))
1395 async_read_until(AsyncReadStream& s,
1396 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1397 BOOST_ASIO_STRING_VIEW_PARAM delim,
1398 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1399 typename constraint<
1400 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1401 >::type,
1402 typename constraint<
1403 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1404 >::type)
1405 {
1406 return async_initiate<ReadHandler,
1407 void (boost::system::error_code, std::size_t)>(
1408 detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),
1409 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1410 static_cast<std::string>(delim));
1411 }
1412
1413 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
1414 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
1415
1416 namespace detail
1417 {
1418 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1419 typename RegEx, typename ReadHandler>
1420 class read_until_expr_op_v1
1421 {
1422 public:
1423 template <typename BufferSequence>
read_until_expr_op_v1(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,const boost::regex & expr,ReadHandler & handler)1424 read_until_expr_op_v1(AsyncReadStream& stream,
1425 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1426 const boost::regex& expr, ReadHandler& handler)
1427 : stream_(stream),
1428 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1429 expr_(expr),
1430 start_(0),
1431 search_position_(0),
1432 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1433 {
1434 }
1435
1436 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_expr_op_v1(const read_until_expr_op_v1 & other)1437 read_until_expr_op_v1(const read_until_expr_op_v1& other)
1438 : stream_(other.stream_),
1439 buffers_(other.buffers_),
1440 expr_(other.expr_),
1441 start_(other.start_),
1442 search_position_(other.search_position_),
1443 handler_(other.handler_)
1444 {
1445 }
1446
read_until_expr_op_v1(read_until_expr_op_v1 && other)1447 read_until_expr_op_v1(read_until_expr_op_v1&& other)
1448 : stream_(other.stream_),
1449 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1450 expr_(other.expr_),
1451 start_(other.start_),
1452 search_position_(other.search_position_),
1453 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1454 {
1455 }
1456 #endif // defined(BOOST_ASIO_HAS_MOVE)
1457
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)1458 void operator()(const boost::system::error_code& ec,
1459 std::size_t bytes_transferred, int start = 0)
1460 {
1461 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1462 std::size_t bytes_to_read;
1463 switch (start_ = start)
1464 {
1465 case 1:
1466 for (;;)
1467 {
1468 {
1469 // Determine the range of the data to be searched.
1470 typedef typename DynamicBuffer_v1::const_buffers_type
1471 buffers_type;
1472 typedef buffers_iterator<buffers_type> iterator;
1473 buffers_type data_buffers = buffers_.data();
1474 iterator begin = iterator::begin(data_buffers);
1475 iterator start_pos = begin + search_position_;
1476 iterator end = iterator::end(data_buffers);
1477
1478 // Look for a match.
1479 boost::match_results<iterator,
1480 typename std::vector<boost::sub_match<iterator> >::allocator_type>
1481 match_results;
1482 bool match = regex_search(start_pos, end, match_results, expr_,
1483 boost::match_default | boost::match_partial);
1484 if (match && match_results[0].matched)
1485 {
1486 // Full match. We're done.
1487 search_position_ = match_results[0].second - begin;
1488 bytes_to_read = 0;
1489 }
1490
1491 // No match yet. Check if buffer is full.
1492 else if (buffers_.size() == buffers_.max_size())
1493 {
1494 search_position_ = not_found;
1495 bytes_to_read = 0;
1496 }
1497
1498 // Need to read some more data.
1499 else
1500 {
1501 if (match)
1502 {
1503 // Partial match. Next search needs to start from beginning of
1504 // match.
1505 search_position_ = match_results[0].first - begin;
1506 }
1507 else
1508 {
1509 // Next search can start with the new data.
1510 search_position_ = end - begin;
1511 }
1512
1513 bytes_to_read = std::min<std::size_t>(
1514 std::max<std::size_t>(512,
1515 buffers_.capacity() - buffers_.size()),
1516 std::min<std::size_t>(65536,
1517 buffers_.max_size() - buffers_.size()));
1518 }
1519 }
1520
1521 // Check if we're done.
1522 if (!start && bytes_to_read == 0)
1523 break;
1524
1525 // Start a new asynchronous read operation to obtain more data.
1526 {
1527 BOOST_ASIO_HANDLER_LOCATION((
1528 __FILE__, __LINE__, "async_read_until"));
1529 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1530 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));
1531 }
1532 return; default:
1533 buffers_.commit(bytes_transferred);
1534 if (ec || bytes_transferred == 0)
1535 break;
1536 }
1537
1538 const boost::system::error_code result_ec =
1539 (search_position_ == not_found)
1540 ? error::not_found : ec;
1541
1542 const std::size_t result_n =
1543 (ec || search_position_ == not_found)
1544 ? 0 : search_position_;
1545
1546 handler_(result_ec, result_n);
1547 }
1548 }
1549
1550 //private:
1551 AsyncReadStream& stream_;
1552 DynamicBuffer_v1 buffers_;
1553 RegEx expr_;
1554 int start_;
1555 std::size_t search_position_;
1556 ReadHandler handler_;
1557 };
1558
1559 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1560 typename RegEx, typename ReadHandler>
1561 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_expr_op_v1<AsyncReadStream,DynamicBuffer_v1,RegEx,ReadHandler> * this_handler)1562 asio_handler_allocate(std::size_t size,
1563 read_until_expr_op_v1<AsyncReadStream,
1564 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1565 {
1566 #if defined(BOOST_ASIO_NO_DEPRECATED)
1567 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1568 return asio_handler_allocate_is_no_longer_used();
1569 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1570 return boost_asio_handler_alloc_helpers::allocate(
1571 size, this_handler->handler_);
1572 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1573 }
1574
1575 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1576 typename RegEx, typename ReadHandler>
1577 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_expr_op_v1<AsyncReadStream,DynamicBuffer_v1,RegEx,ReadHandler> * this_handler)1578 asio_handler_deallocate(void* pointer, std::size_t size,
1579 read_until_expr_op_v1<AsyncReadStream,
1580 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1581 {
1582 boost_asio_handler_alloc_helpers::deallocate(
1583 pointer, size, this_handler->handler_);
1584 #if defined(BOOST_ASIO_NO_DEPRECATED)
1585 return asio_handler_deallocate_is_no_longer_used();
1586 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1587 }
1588
1589 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1590 typename RegEx, typename ReadHandler>
asio_handler_is_continuation(read_until_expr_op_v1<AsyncReadStream,DynamicBuffer_v1,RegEx,ReadHandler> * this_handler)1591 inline bool asio_handler_is_continuation(
1592 read_until_expr_op_v1<AsyncReadStream,
1593 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1594 {
1595 return this_handler->start_ == 0 ? true
1596 : boost_asio_handler_cont_helpers::is_continuation(
1597 this_handler->handler_);
1598 }
1599
1600 template <typename Function, typename AsyncReadStream,
1601 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1602 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_expr_op_v1<AsyncReadStream,DynamicBuffer_v1,RegEx,ReadHandler> * this_handler)1603 asio_handler_invoke(Function& function,
1604 read_until_expr_op_v1<AsyncReadStream,
1605 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1606 {
1607 boost_asio_handler_invoke_helpers::invoke(
1608 function, this_handler->handler_);
1609 #if defined(BOOST_ASIO_NO_DEPRECATED)
1610 return asio_handler_invoke_is_no_longer_used();
1611 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1612 }
1613
1614 template <typename Function, typename AsyncReadStream,
1615 typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>
1616 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_expr_op_v1<AsyncReadStream,DynamicBuffer_v1,RegEx,ReadHandler> * this_handler)1617 asio_handler_invoke(const Function& function,
1618 read_until_expr_op_v1<AsyncReadStream,
1619 DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)
1620 {
1621 boost_asio_handler_invoke_helpers::invoke(
1622 function, this_handler->handler_);
1623 #if defined(BOOST_ASIO_NO_DEPRECATED)
1624 return asio_handler_invoke_is_no_longer_used();
1625 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1626 }
1627
1628 template <typename AsyncReadStream>
1629 class initiate_async_read_until_expr_v1
1630 {
1631 public:
1632 typedef typename AsyncReadStream::executor_type executor_type;
1633
initiate_async_read_until_expr_v1(AsyncReadStream & stream)1634 explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)
1635 : stream_(stream)
1636 {
1637 }
1638
get_executor() const1639 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1640 {
1641 return stream_.get_executor();
1642 }
1643
1644 template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,const RegEx & expr) const1645 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1646 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) const
1647 {
1648 // If you get an error on the following line it means that your handler
1649 // does not meet the documented type requirements for a ReadHandler.
1650 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1651
1652 non_const_lvalue<ReadHandler> handler2(handler);
1653 read_until_expr_op_v1<AsyncReadStream,
1654 typename decay<DynamicBuffer_v1>::type,
1655 RegEx, typename decay<ReadHandler>::type>(
1656 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1657 expr, handler2.value)(boost::system::error_code(), 0, 1);
1658 }
1659
1660 private:
1661 AsyncReadStream& stream_;
1662 };
1663 } // namespace detail
1664
1665 #if !defined(GENERATING_DOCUMENTATION)
1666
1667 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1668 typename RegEx, typename ReadHandler, typename Allocator>
1669 struct associated_allocator<
1670 detail::read_until_expr_op_v1<AsyncReadStream,
1671 DynamicBuffer_v1, RegEx, ReadHandler>,
1672 Allocator>
1673 {
1674 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1675
getboost::asio::associated_allocator1676 static type get(
1677 const detail::read_until_expr_op_v1<AsyncReadStream,
1678 DynamicBuffer_v1, RegEx, ReadHandler>& h,
1679 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1680 {
1681 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1682 }
1683 };
1684
1685 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1686 typename RegEx, typename ReadHandler, typename Executor>
1687 struct associated_executor<
1688 detail::read_until_expr_op_v1<AsyncReadStream,
1689 DynamicBuffer_v1, RegEx, ReadHandler>,
1690 Executor>
1691 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
1692 {
1693 typedef typename associated_executor<ReadHandler, Executor>::type type;
1694
getboost::asio::associated_executor1695 static type get(
1696 const detail::read_until_expr_op_v1<AsyncReadStream,
1697 DynamicBuffer_v1, RegEx, ReadHandler>& h,
1698 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1699 {
1700 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1701 }
1702 };
1703
1704 #endif // !defined(GENERATING_DOCUMENTATION)
1705
1706 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1707 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1708 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1709 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1710 void (boost::system::error_code, std::size_t))
1711 async_read_until(AsyncReadStream& s,
1712 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1713 const boost::regex& expr,
1714 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1715 typename constraint<
1716 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
1717 >::type,
1718 typename constraint<
1719 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
1720 >::type)
1721 {
1722 return async_initiate<ReadHandler,
1723 void (boost::system::error_code, std::size_t)>(
1724 detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),
1725 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);
1726 }
1727
1728 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
1729
1730 namespace detail
1731 {
1732 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1733 typename MatchCondition, typename ReadHandler>
1734 class read_until_match_op_v1
1735 {
1736 public:
1737 template <typename BufferSequence>
read_until_match_op_v1(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,MatchCondition match_condition,ReadHandler & handler)1738 read_until_match_op_v1(AsyncReadStream& stream,
1739 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
1740 MatchCondition match_condition, ReadHandler& handler)
1741 : stream_(stream),
1742 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
1743 match_condition_(match_condition),
1744 start_(0),
1745 search_position_(0),
1746 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
1747 {
1748 }
1749
1750 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_match_op_v1(const read_until_match_op_v1 & other)1751 read_until_match_op_v1(const read_until_match_op_v1& other)
1752 : stream_(other.stream_),
1753 buffers_(other.buffers_),
1754 match_condition_(other.match_condition_),
1755 start_(other.start_),
1756 search_position_(other.search_position_),
1757 handler_(other.handler_)
1758 {
1759 }
1760
read_until_match_op_v1(read_until_match_op_v1 && other)1761 read_until_match_op_v1(read_until_match_op_v1&& other)
1762 : stream_(other.stream_),
1763 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
1764 match_condition_(other.match_condition_),
1765 start_(other.start_),
1766 search_position_(other.search_position_),
1767 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
1768 {
1769 }
1770 #endif // defined(BOOST_ASIO_HAS_MOVE)
1771
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)1772 void operator()(const boost::system::error_code& ec,
1773 std::size_t bytes_transferred, int start = 0)
1774 {
1775 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
1776 std::size_t bytes_to_read;
1777 switch (start_ = start)
1778 {
1779 case 1:
1780 for (;;)
1781 {
1782 {
1783 // Determine the range of the data to be searched.
1784 typedef typename DynamicBuffer_v1::const_buffers_type
1785 buffers_type;
1786 typedef buffers_iterator<buffers_type> iterator;
1787 buffers_type data_buffers = buffers_.data();
1788 iterator begin = iterator::begin(data_buffers);
1789 iterator start_pos = begin + search_position_;
1790 iterator end = iterator::end(data_buffers);
1791
1792 // Look for a match.
1793 std::pair<iterator, bool> result = match_condition_(start_pos, end);
1794 if (result.second)
1795 {
1796 // Full match. We're done.
1797 search_position_ = result.first - begin;
1798 bytes_to_read = 0;
1799 }
1800
1801 // No match yet. Check if buffer is full.
1802 else if (buffers_.size() == buffers_.max_size())
1803 {
1804 search_position_ = not_found;
1805 bytes_to_read = 0;
1806 }
1807
1808 // Need to read some more data.
1809 else
1810 {
1811 if (result.first != end)
1812 {
1813 // Partial match. Next search needs to start from beginning of
1814 // match.
1815 search_position_ = result.first - begin;
1816 }
1817 else
1818 {
1819 // Next search can start with the new data.
1820 search_position_ = end - begin;
1821 }
1822
1823 bytes_to_read = std::min<std::size_t>(
1824 std::max<std::size_t>(512,
1825 buffers_.capacity() - buffers_.size()),
1826 std::min<std::size_t>(65536,
1827 buffers_.max_size() - buffers_.size()));
1828 }
1829 }
1830
1831 // Check if we're done.
1832 if (!start && bytes_to_read == 0)
1833 break;
1834
1835 // Start a new asynchronous read operation to obtain more data.
1836 {
1837 BOOST_ASIO_HANDLER_LOCATION((
1838 __FILE__, __LINE__, "async_read_until"));
1839 stream_.async_read_some(buffers_.prepare(bytes_to_read),
1840 BOOST_ASIO_MOVE_CAST(read_until_match_op_v1)(*this));
1841 }
1842 return; default:
1843 buffers_.commit(bytes_transferred);
1844 if (ec || bytes_transferred == 0)
1845 break;
1846 }
1847
1848 const boost::system::error_code result_ec =
1849 (search_position_ == not_found)
1850 ? error::not_found : ec;
1851
1852 const std::size_t result_n =
1853 (ec || search_position_ == not_found)
1854 ? 0 : search_position_;
1855
1856 handler_(result_ec, result_n);
1857 }
1858 }
1859
1860 //private:
1861 AsyncReadStream& stream_;
1862 DynamicBuffer_v1 buffers_;
1863 MatchCondition match_condition_;
1864 int start_;
1865 std::size_t search_position_;
1866 ReadHandler handler_;
1867 };
1868
1869 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1870 typename MatchCondition, typename ReadHandler>
1871 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_match_op_v1<AsyncReadStream,DynamicBuffer_v1,MatchCondition,ReadHandler> * this_handler)1872 asio_handler_allocate(std::size_t size,
1873 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1874 MatchCondition, ReadHandler>* this_handler)
1875 {
1876 #if defined(BOOST_ASIO_NO_DEPRECATED)
1877 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1878 return asio_handler_allocate_is_no_longer_used();
1879 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1880 return boost_asio_handler_alloc_helpers::allocate(
1881 size, this_handler->handler_);
1882 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1883 }
1884
1885 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1886 typename MatchCondition, typename ReadHandler>
1887 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_match_op_v1<AsyncReadStream,DynamicBuffer_v1,MatchCondition,ReadHandler> * this_handler)1888 asio_handler_deallocate(void* pointer, std::size_t size,
1889 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1890 MatchCondition, ReadHandler>* this_handler)
1891 {
1892 boost_asio_handler_alloc_helpers::deallocate(
1893 pointer, size, this_handler->handler_);
1894 #if defined(BOOST_ASIO_NO_DEPRECATED)
1895 return asio_handler_deallocate_is_no_longer_used();
1896 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1897 }
1898
1899 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1900 typename MatchCondition, typename ReadHandler>
asio_handler_is_continuation(read_until_match_op_v1<AsyncReadStream,DynamicBuffer_v1,MatchCondition,ReadHandler> * this_handler)1901 inline bool asio_handler_is_continuation(
1902 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1903 MatchCondition, ReadHandler>* this_handler)
1904 {
1905 return this_handler->start_ == 0 ? true
1906 : boost_asio_handler_cont_helpers::is_continuation(
1907 this_handler->handler_);
1908 }
1909
1910 template <typename Function, typename AsyncReadStream,
1911 typename DynamicBuffer_v1, typename MatchCondition,
1912 typename ReadHandler>
1913 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_match_op_v1<AsyncReadStream,DynamicBuffer_v1,MatchCondition,ReadHandler> * this_handler)1914 asio_handler_invoke(Function& function,
1915 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1916 MatchCondition, ReadHandler>* this_handler)
1917 {
1918 boost_asio_handler_invoke_helpers::invoke(
1919 function, this_handler->handler_);
1920 #if defined(BOOST_ASIO_NO_DEPRECATED)
1921 return asio_handler_invoke_is_no_longer_used();
1922 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1923 }
1924
1925 template <typename Function, typename AsyncReadStream,
1926 typename DynamicBuffer_v1, typename MatchCondition,
1927 typename ReadHandler>
1928 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_match_op_v1<AsyncReadStream,DynamicBuffer_v1,MatchCondition,ReadHandler> * this_handler)1929 asio_handler_invoke(const Function& function,
1930 read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,
1931 MatchCondition, ReadHandler>* this_handler)
1932 {
1933 boost_asio_handler_invoke_helpers::invoke(
1934 function, this_handler->handler_);
1935 #if defined(BOOST_ASIO_NO_DEPRECATED)
1936 return asio_handler_invoke_is_no_longer_used();
1937 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1938 }
1939
1940 template <typename AsyncReadStream>
1941 class initiate_async_read_until_match_v1
1942 {
1943 public:
1944 typedef typename AsyncReadStream::executor_type executor_type;
1945
initiate_async_read_until_match_v1(AsyncReadStream & stream)1946 explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)
1947 : stream_(stream)
1948 {
1949 }
1950
get_executor() const1951 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1952 {
1953 return stream_.get_executor();
1954 }
1955
1956 template <typename ReadHandler,
1957 typename DynamicBuffer_v1, typename MatchCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,MatchCondition match_condition) const1958 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1959 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
1960 MatchCondition match_condition) const
1961 {
1962 // If you get an error on the following line it means that your handler
1963 // does not meet the documented type requirements for a ReadHandler.
1964 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1965
1966 non_const_lvalue<ReadHandler> handler2(handler);
1967 read_until_match_op_v1<AsyncReadStream,
1968 typename decay<DynamicBuffer_v1>::type,
1969 MatchCondition, typename decay<ReadHandler>::type>(
1970 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
1971 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
1972 }
1973
1974 private:
1975 AsyncReadStream& stream_;
1976 };
1977 } // namespace detail
1978
1979 #if !defined(GENERATING_DOCUMENTATION)
1980
1981 template <typename AsyncReadStream, typename DynamicBuffer_v1,
1982 typename MatchCondition, typename ReadHandler, typename Allocator>
1983 struct associated_allocator<
1984 detail::read_until_match_op_v1<AsyncReadStream,
1985 DynamicBuffer_v1, MatchCondition, ReadHandler>,
1986 Allocator>
1987 {
1988 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1989
getboost::asio::associated_allocator1990 static type get(
1991 const detail::read_until_match_op_v1<AsyncReadStream,
1992 DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
1993 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1994 {
1995 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1996 }
1997 };
1998
1999 template <typename AsyncReadStream, typename DynamicBuffer_v1,
2000 typename MatchCondition, typename ReadHandler, typename Executor>
2001 struct associated_executor<
2002 detail::read_until_match_op_v1<AsyncReadStream,
2003 DynamicBuffer_v1, MatchCondition, ReadHandler>,
2004 Executor>
2005 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
2006 {
2007 typedef typename associated_executor<ReadHandler, Executor>::type type;
2008
getboost::asio::associated_executor2009 static type get(
2010 const detail::read_until_match_op_v1<AsyncReadStream,
2011 DynamicBuffer_v1, MatchCondition, ReadHandler>& h,
2012 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2013 {
2014 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2015 }
2016 };
2017
2018 #endif // !defined(GENERATING_DOCUMENTATION)
2019
2020 template <typename AsyncReadStream,
2021 typename DynamicBuffer_v1, typename MatchCondition,
2022 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2023 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2024 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2025 void (boost::system::error_code, std::size_t))
2026 async_read_until(AsyncReadStream& s,
2027 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
2028 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2029 typename constraint<
2030 is_match_condition<MatchCondition>::value
2031 >::type,
2032 typename constraint<
2033 is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
2034 >::type,
2035 typename constraint<
2036 !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
2037 >::type)
2038 {
2039 return async_initiate<ReadHandler,
2040 void (boost::system::error_code, std::size_t)>(
2041 detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), handler,
2042 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);
2043 }
2044
2045 #if !defined(BOOST_ASIO_NO_IOSTREAM)
2046
2047 template <typename AsyncReadStream, typename Allocator,
2048 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2049 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2050 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2051 void (boost::system::error_code, std::size_t))
2052 async_read_until(AsyncReadStream& s,
2053 boost::asio::basic_streambuf<Allocator>& b,
2054 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
2055 {
2056 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2057 delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
2058 }
2059
2060 template <typename AsyncReadStream, typename Allocator,
2061 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2062 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2063 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2064 void (boost::system::error_code, std::size_t))
2065 async_read_until(AsyncReadStream& s,
2066 boost::asio::basic_streambuf<Allocator>& b,
2067 BOOST_ASIO_STRING_VIEW_PARAM delim,
2068 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
2069 {
2070 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2071 delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
2072 }
2073
2074 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
2075
2076 template <typename AsyncReadStream, typename Allocator,
2077 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2078 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2079 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2080 void (boost::system::error_code, std::size_t))
2081 async_read_until(AsyncReadStream& s,
2082 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
2083 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
2084 {
2085 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2086 expr, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
2087 }
2088
2089 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
2090
2091 template <typename AsyncReadStream, typename Allocator, typename MatchCondition,
2092 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2093 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2094 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2095 void (boost::system::error_code, std::size_t))
2096 async_read_until(AsyncReadStream& s,
2097 boost::asio::basic_streambuf<Allocator>& b,
2098 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2099 typename constraint<is_match_condition<MatchCondition>::value>::type)
2100 {
2101 return async_read_until(s, basic_streambuf_ref<Allocator>(b),
2102 match_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
2103 }
2104
2105 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
2106 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
2107 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
2108
2109 namespace detail
2110 {
2111 template <typename AsyncReadStream,
2112 typename DynamicBuffer_v2, typename ReadHandler>
2113 class read_until_delim_op_v2
2114 {
2115 public:
2116 template <typename BufferSequence>
read_until_delim_op_v2(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,char delim,ReadHandler & handler)2117 read_until_delim_op_v2(AsyncReadStream& stream,
2118 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2119 char delim, ReadHandler& handler)
2120 : stream_(stream),
2121 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2122 delim_(delim),
2123 start_(0),
2124 search_position_(0),
2125 bytes_to_read_(0),
2126 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2127 {
2128 }
2129
2130 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_op_v2(const read_until_delim_op_v2 & other)2131 read_until_delim_op_v2(const read_until_delim_op_v2& other)
2132 : stream_(other.stream_),
2133 buffers_(other.buffers_),
2134 delim_(other.delim_),
2135 start_(other.start_),
2136 search_position_(other.search_position_),
2137 bytes_to_read_(other.bytes_to_read_),
2138 handler_(other.handler_)
2139 {
2140 }
2141
read_until_delim_op_v2(read_until_delim_op_v2 && other)2142 read_until_delim_op_v2(read_until_delim_op_v2&& other)
2143 : stream_(other.stream_),
2144 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2145 delim_(other.delim_),
2146 start_(other.start_),
2147 search_position_(other.search_position_),
2148 bytes_to_read_(other.bytes_to_read_),
2149 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2150 {
2151 }
2152 #endif // defined(BOOST_ASIO_HAS_MOVE)
2153
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)2154 void operator()(const boost::system::error_code& ec,
2155 std::size_t bytes_transferred, int start = 0)
2156 {
2157 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2158 std::size_t pos;
2159 switch (start_ = start)
2160 {
2161 case 1:
2162 for (;;)
2163 {
2164 {
2165 // Determine the range of the data to be searched.
2166 typedef typename DynamicBuffer_v2::const_buffers_type
2167 buffers_type;
2168 typedef buffers_iterator<buffers_type> iterator;
2169 buffers_type data_buffers =
2170 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2171 0, buffers_.size());
2172 iterator begin = iterator::begin(data_buffers);
2173 iterator start_pos = begin + search_position_;
2174 iterator end = iterator::end(data_buffers);
2175
2176 // Look for a match.
2177 iterator iter = std::find(start_pos, end, delim_);
2178 if (iter != end)
2179 {
2180 // Found a match. We're done.
2181 search_position_ = iter - begin + 1;
2182 bytes_to_read_ = 0;
2183 }
2184
2185 // No match yet. Check if buffer is full.
2186 else if (buffers_.size() == buffers_.max_size())
2187 {
2188 search_position_ = not_found;
2189 bytes_to_read_ = 0;
2190 }
2191
2192 // Need to read some more data.
2193 else
2194 {
2195 // Next search can start with the new data.
2196 search_position_ = end - begin;
2197 bytes_to_read_ = std::min<std::size_t>(
2198 std::max<std::size_t>(512,
2199 buffers_.capacity() - buffers_.size()),
2200 std::min<std::size_t>(65536,
2201 buffers_.max_size() - buffers_.size()));
2202 }
2203 }
2204
2205 // Check if we're done.
2206 if (!start && bytes_to_read_ == 0)
2207 break;
2208
2209 // Start a new asynchronous read operation to obtain more data.
2210 pos = buffers_.size();
2211 buffers_.grow(bytes_to_read_);
2212 {
2213 BOOST_ASIO_HANDLER_LOCATION((
2214 __FILE__, __LINE__, "async_read_until"));
2215 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2216 BOOST_ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));
2217 }
2218 return; default:
2219 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2220 if (ec || bytes_transferred == 0)
2221 break;
2222 }
2223
2224 const boost::system::error_code result_ec =
2225 (search_position_ == not_found)
2226 ? error::not_found : ec;
2227
2228 const std::size_t result_n =
2229 (ec || search_position_ == not_found)
2230 ? 0 : search_position_;
2231
2232 handler_(result_ec, result_n);
2233 }
2234 }
2235
2236 //private:
2237 AsyncReadStream& stream_;
2238 DynamicBuffer_v2 buffers_;
2239 char delim_;
2240 int start_;
2241 std::size_t search_position_;
2242 std::size_t bytes_to_read_;
2243 ReadHandler handler_;
2244 };
2245
2246 template <typename AsyncReadStream,
2247 typename DynamicBuffer_v2, typename ReadHandler>
2248 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_delim_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2249 asio_handler_allocate(std::size_t size,
2250 read_until_delim_op_v2<AsyncReadStream,
2251 DynamicBuffer_v2, ReadHandler>* this_handler)
2252 {
2253 #if defined(BOOST_ASIO_NO_DEPRECATED)
2254 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2255 return asio_handler_allocate_is_no_longer_used();
2256 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2257 return boost_asio_handler_alloc_helpers::allocate(
2258 size, this_handler->handler_);
2259 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2260 }
2261
2262 template <typename AsyncReadStream,
2263 typename DynamicBuffer_v2, typename ReadHandler>
2264 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_delim_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2265 asio_handler_deallocate(void* pointer, std::size_t size,
2266 read_until_delim_op_v2<AsyncReadStream,
2267 DynamicBuffer_v2, ReadHandler>* this_handler)
2268 {
2269 boost_asio_handler_alloc_helpers::deallocate(
2270 pointer, size, this_handler->handler_);
2271 #if defined(BOOST_ASIO_NO_DEPRECATED)
2272 return asio_handler_deallocate_is_no_longer_used();
2273 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2274 }
2275
2276 template <typename AsyncReadStream,
2277 typename DynamicBuffer_v2, typename ReadHandler>
asio_handler_is_continuation(read_until_delim_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2278 inline bool asio_handler_is_continuation(
2279 read_until_delim_op_v2<AsyncReadStream,
2280 DynamicBuffer_v2, ReadHandler>* this_handler)
2281 {
2282 return this_handler->start_ == 0 ? true
2283 : boost_asio_handler_cont_helpers::is_continuation(
2284 this_handler->handler_);
2285 }
2286
2287 template <typename Function, typename AsyncReadStream,
2288 typename DynamicBuffer_v2, typename ReadHandler>
2289 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_delim_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2290 asio_handler_invoke(Function& function,
2291 read_until_delim_op_v2<AsyncReadStream,
2292 DynamicBuffer_v2, ReadHandler>* this_handler)
2293 {
2294 boost_asio_handler_invoke_helpers::invoke(
2295 function, this_handler->handler_);
2296 #if defined(BOOST_ASIO_NO_DEPRECATED)
2297 return asio_handler_invoke_is_no_longer_used();
2298 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2299 }
2300
2301 template <typename Function, typename AsyncReadStream,
2302 typename DynamicBuffer_v2, typename ReadHandler>
2303 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_delim_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2304 asio_handler_invoke(const Function& function,
2305 read_until_delim_op_v2<AsyncReadStream,
2306 DynamicBuffer_v2, ReadHandler>* this_handler)
2307 {
2308 boost_asio_handler_invoke_helpers::invoke(
2309 function, this_handler->handler_);
2310 #if defined(BOOST_ASIO_NO_DEPRECATED)
2311 return asio_handler_invoke_is_no_longer_used();
2312 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2313 }
2314
2315 template <typename AsyncReadStream>
2316 class initiate_async_read_until_delim_v2
2317 {
2318 public:
2319 typedef typename AsyncReadStream::executor_type executor_type;
2320
initiate_async_read_until_delim_v2(AsyncReadStream & stream)2321 explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)
2322 : stream_(stream)
2323 {
2324 }
2325
get_executor() const2326 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2327 {
2328 return stream_.get_executor();
2329 }
2330
2331 template <typename ReadHandler, typename DynamicBuffer_v2>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,char delim) const2332 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2333 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) const
2334 {
2335 // If you get an error on the following line it means that your handler
2336 // does not meet the documented type requirements for a ReadHandler.
2337 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2338
2339 non_const_lvalue<ReadHandler> handler2(handler);
2340 read_until_delim_op_v2<AsyncReadStream,
2341 typename decay<DynamicBuffer_v2>::type,
2342 typename decay<ReadHandler>::type>(
2343 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2344 delim, handler2.value)(boost::system::error_code(), 0, 1);
2345 }
2346
2347 private:
2348 AsyncReadStream& stream_;
2349 };
2350 } // namespace detail
2351
2352 #if !defined(GENERATING_DOCUMENTATION)
2353
2354 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2355 typename ReadHandler, typename Allocator>
2356 struct associated_allocator<
2357 detail::read_until_delim_op_v2<AsyncReadStream,
2358 DynamicBuffer_v2, ReadHandler>,
2359 Allocator>
2360 {
2361 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2362
getboost::asio::associated_allocator2363 static type get(
2364 const detail::read_until_delim_op_v2<AsyncReadStream,
2365 DynamicBuffer_v2, ReadHandler>& h,
2366 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
2367 {
2368 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
2369 }
2370 };
2371
2372 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2373 typename ReadHandler, typename Executor>
2374 struct associated_executor<
2375 detail::read_until_delim_op_v2<AsyncReadStream,
2376 DynamicBuffer_v2, ReadHandler>,
2377 Executor>
2378 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
2379 {
2380 typedef typename associated_executor<ReadHandler, Executor>::type type;
2381
getboost::asio::associated_executor2382 static type get(
2383 const detail::read_until_delim_op_v2<AsyncReadStream,
2384 DynamicBuffer_v2, ReadHandler>& h,
2385 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2386 {
2387 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2388 }
2389 };
2390
2391 #endif // !defined(GENERATING_DOCUMENTATION)
2392
2393 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2394 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2395 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2396 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2397 void (boost::system::error_code, std::size_t))
2398 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
2399 char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2400 typename constraint<
2401 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2402 >::type)
2403 {
2404 return async_initiate<ReadHandler,
2405 void (boost::system::error_code, std::size_t)>(
2406 detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),
2407 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);
2408 }
2409
2410 namespace detail
2411 {
2412 template <typename AsyncReadStream,
2413 typename DynamicBuffer_v2, typename ReadHandler>
2414 class read_until_delim_string_op_v2
2415 {
2416 public:
2417 template <typename BufferSequence>
read_until_delim_string_op_v2(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,const std::string & delim,ReadHandler & handler)2418 read_until_delim_string_op_v2(AsyncReadStream& stream,
2419 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2420 const std::string& delim, ReadHandler& handler)
2421 : stream_(stream),
2422 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2423 delim_(delim),
2424 start_(0),
2425 search_position_(0),
2426 bytes_to_read_(0),
2427 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2428 {
2429 }
2430
2431 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_string_op_v2(const read_until_delim_string_op_v2 & other)2432 read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)
2433 : stream_(other.stream_),
2434 buffers_(other.buffers_),
2435 delim_(other.delim_),
2436 start_(other.start_),
2437 search_position_(other.search_position_),
2438 bytes_to_read_(other.bytes_to_read_),
2439 handler_(other.handler_)
2440 {
2441 }
2442
read_until_delim_string_op_v2(read_until_delim_string_op_v2 && other)2443 read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)
2444 : stream_(other.stream_),
2445 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2446 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
2447 start_(other.start_),
2448 search_position_(other.search_position_),
2449 bytes_to_read_(other.bytes_to_read_),
2450 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2451 {
2452 }
2453 #endif // defined(BOOST_ASIO_HAS_MOVE)
2454
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)2455 void operator()(const boost::system::error_code& ec,
2456 std::size_t bytes_transferred, int start = 0)
2457 {
2458 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2459 std::size_t pos;
2460 switch (start_ = start)
2461 {
2462 case 1:
2463 for (;;)
2464 {
2465 {
2466 // Determine the range of the data to be searched.
2467 typedef typename DynamicBuffer_v2::const_buffers_type
2468 buffers_type;
2469 typedef buffers_iterator<buffers_type> iterator;
2470 buffers_type data_buffers =
2471 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2472 0, buffers_.size());
2473 iterator begin = iterator::begin(data_buffers);
2474 iterator start_pos = begin + search_position_;
2475 iterator end = iterator::end(data_buffers);
2476
2477 // Look for a match.
2478 std::pair<iterator, bool> result = detail::partial_search(
2479 start_pos, end, delim_.begin(), delim_.end());
2480 if (result.first != end && result.second)
2481 {
2482 // Full match. We're done.
2483 search_position_ = result.first - begin + delim_.length();
2484 bytes_to_read_ = 0;
2485 }
2486
2487 // No match yet. Check if buffer is full.
2488 else if (buffers_.size() == buffers_.max_size())
2489 {
2490 search_position_ = not_found;
2491 bytes_to_read_ = 0;
2492 }
2493
2494 // Need to read some more data.
2495 else
2496 {
2497 if (result.first != end)
2498 {
2499 // Partial match. Next search needs to start from beginning of
2500 // match.
2501 search_position_ = result.first - begin;
2502 }
2503 else
2504 {
2505 // Next search can start with the new data.
2506 search_position_ = end - begin;
2507 }
2508
2509 bytes_to_read_ = std::min<std::size_t>(
2510 std::max<std::size_t>(512,
2511 buffers_.capacity() - buffers_.size()),
2512 std::min<std::size_t>(65536,
2513 buffers_.max_size() - buffers_.size()));
2514 }
2515 }
2516
2517 // Check if we're done.
2518 if (!start && bytes_to_read_ == 0)
2519 break;
2520
2521 // Start a new asynchronous read operation to obtain more data.
2522 pos = buffers_.size();
2523 buffers_.grow(bytes_to_read_);
2524 {
2525 BOOST_ASIO_HANDLER_LOCATION((
2526 __FILE__, __LINE__, "async_read_until"));
2527 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2528 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));
2529 }
2530 return; default:
2531 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2532 if (ec || bytes_transferred == 0)
2533 break;
2534 }
2535
2536 const boost::system::error_code result_ec =
2537 (search_position_ == not_found)
2538 ? error::not_found : ec;
2539
2540 const std::size_t result_n =
2541 (ec || search_position_ == not_found)
2542 ? 0 : search_position_;
2543
2544 handler_(result_ec, result_n);
2545 }
2546 }
2547
2548 //private:
2549 AsyncReadStream& stream_;
2550 DynamicBuffer_v2 buffers_;
2551 std::string delim_;
2552 int start_;
2553 std::size_t search_position_;
2554 std::size_t bytes_to_read_;
2555 ReadHandler handler_;
2556 };
2557
2558 template <typename AsyncReadStream,
2559 typename DynamicBuffer_v2, typename ReadHandler>
2560 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_delim_string_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2561 asio_handler_allocate(std::size_t size,
2562 read_until_delim_string_op_v2<AsyncReadStream,
2563 DynamicBuffer_v2, ReadHandler>* this_handler)
2564 {
2565 #if defined(BOOST_ASIO_NO_DEPRECATED)
2566 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2567 return asio_handler_allocate_is_no_longer_used();
2568 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2569 return boost_asio_handler_alloc_helpers::allocate(
2570 size, this_handler->handler_);
2571 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2572 }
2573
2574 template <typename AsyncReadStream,
2575 typename DynamicBuffer_v2, typename ReadHandler>
2576 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_delim_string_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2577 asio_handler_deallocate(void* pointer, std::size_t size,
2578 read_until_delim_string_op_v2<AsyncReadStream,
2579 DynamicBuffer_v2, ReadHandler>* this_handler)
2580 {
2581 boost_asio_handler_alloc_helpers::deallocate(
2582 pointer, size, this_handler->handler_);
2583 #if defined(BOOST_ASIO_NO_DEPRECATED)
2584 return asio_handler_deallocate_is_no_longer_used();
2585 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2586 }
2587
2588 template <typename AsyncReadStream,
2589 typename DynamicBuffer_v2, typename ReadHandler>
asio_handler_is_continuation(read_until_delim_string_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2590 inline bool asio_handler_is_continuation(
2591 read_until_delim_string_op_v2<AsyncReadStream,
2592 DynamicBuffer_v2, ReadHandler>* this_handler)
2593 {
2594 return this_handler->start_ == 0 ? true
2595 : boost_asio_handler_cont_helpers::is_continuation(
2596 this_handler->handler_);
2597 }
2598
2599 template <typename Function, typename AsyncReadStream,
2600 typename DynamicBuffer_v2, typename ReadHandler>
2601 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_delim_string_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2602 asio_handler_invoke(Function& function,
2603 read_until_delim_string_op_v2<AsyncReadStream,
2604 DynamicBuffer_v2, ReadHandler>* this_handler)
2605 {
2606 boost_asio_handler_invoke_helpers::invoke(
2607 function, this_handler->handler_);
2608 #if defined(BOOST_ASIO_NO_DEPRECATED)
2609 return asio_handler_invoke_is_no_longer_used();
2610 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2611 }
2612
2613 template <typename Function, typename AsyncReadStream,
2614 typename DynamicBuffer_v2, typename ReadHandler>
2615 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_delim_string_op_v2<AsyncReadStream,DynamicBuffer_v2,ReadHandler> * this_handler)2616 asio_handler_invoke(const Function& function,
2617 read_until_delim_string_op_v2<AsyncReadStream,
2618 DynamicBuffer_v2, ReadHandler>* this_handler)
2619 {
2620 boost_asio_handler_invoke_helpers::invoke(
2621 function, this_handler->handler_);
2622 #if defined(BOOST_ASIO_NO_DEPRECATED)
2623 return asio_handler_invoke_is_no_longer_used();
2624 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2625 }
2626
2627 template <typename AsyncReadStream>
2628 class initiate_async_read_until_delim_string_v2
2629 {
2630 public:
2631 typedef typename AsyncReadStream::executor_type executor_type;
2632
initiate_async_read_until_delim_string_v2(AsyncReadStream & stream)2633 explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)
2634 : stream_(stream)
2635 {
2636 }
2637
get_executor() const2638 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2639 {
2640 return stream_.get_executor();
2641 }
2642
2643 template <typename ReadHandler, typename DynamicBuffer_v2>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,const std::string & delim) const2644 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2645 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2646 const std::string& delim) const
2647 {
2648 // If you get an error on the following line it means that your handler
2649 // does not meet the documented type requirements for a ReadHandler.
2650 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2651
2652 non_const_lvalue<ReadHandler> handler2(handler);
2653 read_until_delim_string_op_v2<AsyncReadStream,
2654 typename decay<DynamicBuffer_v2>::type,
2655 typename decay<ReadHandler>::type>(
2656 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2657 delim, handler2.value)(boost::system::error_code(), 0, 1);
2658 }
2659
2660 private:
2661 AsyncReadStream& stream_;
2662 };
2663 } // namespace detail
2664
2665 #if !defined(GENERATING_DOCUMENTATION)
2666
2667 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2668 typename ReadHandler, typename Allocator>
2669 struct associated_allocator<
2670 detail::read_until_delim_string_op_v2<AsyncReadStream,
2671 DynamicBuffer_v2, ReadHandler>,
2672 Allocator>
2673 {
2674 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2675
getboost::asio::associated_allocator2676 static type get(
2677 const detail::read_until_delim_string_op_v2<AsyncReadStream,
2678 DynamicBuffer_v2, ReadHandler>& h,
2679 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
2680 {
2681 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
2682 }
2683 };
2684
2685 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2686 typename ReadHandler, typename Executor>
2687 struct associated_executor<
2688 detail::read_until_delim_string_op_v2<AsyncReadStream,
2689 DynamicBuffer_v2, ReadHandler>,
2690 Executor>
2691 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
2692 {
2693 typedef typename associated_executor<ReadHandler, Executor>::type type;
2694
getboost::asio::associated_executor2695 static type get(
2696 const detail::read_until_delim_string_op_v2<AsyncReadStream,
2697 DynamicBuffer_v2, ReadHandler>& h,
2698 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
2699 {
2700 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
2701 }
2702 };
2703
2704 #endif // !defined(GENERATING_DOCUMENTATION)
2705
2706 template <typename AsyncReadStream,
2707 typename DynamicBuffer_v2,
2708 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
2709 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))2710 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
2711 void (boost::system::error_code, std::size_t))
2712 async_read_until(AsyncReadStream& s,
2713 DynamicBuffer_v2 buffers, BOOST_ASIO_STRING_VIEW_PARAM delim,
2714 BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2715 typename constraint<
2716 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
2717 >::type)
2718 {
2719 return async_initiate<ReadHandler,
2720 void (boost::system::error_code, std::size_t)>(
2721 detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),
2722 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2723 static_cast<std::string>(delim));
2724 }
2725
2726 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
2727 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
2728
2729 namespace detail
2730 {
2731 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2732 typename RegEx, typename ReadHandler>
2733 class read_until_expr_op_v2
2734 {
2735 public:
2736 template <typename BufferSequence>
read_until_expr_op_v2(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,const boost::regex & expr,ReadHandler & handler)2737 read_until_expr_op_v2(AsyncReadStream& stream,
2738 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
2739 const boost::regex& expr, ReadHandler& handler)
2740 : stream_(stream),
2741 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
2742 expr_(expr),
2743 start_(0),
2744 search_position_(0),
2745 bytes_to_read_(0),
2746 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
2747 {
2748 }
2749
2750 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_expr_op_v2(const read_until_expr_op_v2 & other)2751 read_until_expr_op_v2(const read_until_expr_op_v2& other)
2752 : stream_(other.stream_),
2753 buffers_(other.buffers_),
2754 expr_(other.expr_),
2755 start_(other.start_),
2756 search_position_(other.search_position_),
2757 bytes_to_read_(other.bytes_to_read_),
2758 handler_(other.handler_)
2759 {
2760 }
2761
read_until_expr_op_v2(read_until_expr_op_v2 && other)2762 read_until_expr_op_v2(read_until_expr_op_v2&& other)
2763 : stream_(other.stream_),
2764 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
2765 expr_(other.expr_),
2766 start_(other.start_),
2767 search_position_(other.search_position_),
2768 bytes_to_read_(other.bytes_to_read_),
2769 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
2770 {
2771 }
2772 #endif // defined(BOOST_ASIO_HAS_MOVE)
2773
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)2774 void operator()(const boost::system::error_code& ec,
2775 std::size_t bytes_transferred, int start = 0)
2776 {
2777 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
2778 std::size_t pos;
2779 switch (start_ = start)
2780 {
2781 case 1:
2782 for (;;)
2783 {
2784 {
2785 // Determine the range of the data to be searched.
2786 typedef typename DynamicBuffer_v2::const_buffers_type
2787 buffers_type;
2788 typedef buffers_iterator<buffers_type> iterator;
2789 buffers_type data_buffers =
2790 const_cast<const DynamicBuffer_v2&>(buffers_).data(
2791 0, buffers_.size());
2792 iterator begin = iterator::begin(data_buffers);
2793 iterator start_pos = begin + search_position_;
2794 iterator end = iterator::end(data_buffers);
2795
2796 // Look for a match.
2797 boost::match_results<iterator,
2798 typename std::vector<boost::sub_match<iterator> >::allocator_type>
2799 match_results;
2800 bool match = regex_search(start_pos, end, match_results, expr_,
2801 boost::match_default | boost::match_partial);
2802 if (match && match_results[0].matched)
2803 {
2804 // Full match. We're done.
2805 search_position_ = match_results[0].second - begin;
2806 bytes_to_read_ = 0;
2807 }
2808
2809 // No match yet. Check if buffer is full.
2810 else if (buffers_.size() == buffers_.max_size())
2811 {
2812 search_position_ = not_found;
2813 bytes_to_read_ = 0;
2814 }
2815
2816 // Need to read some more data.
2817 else
2818 {
2819 if (match)
2820 {
2821 // Partial match. Next search needs to start from beginning of
2822 // match.
2823 search_position_ = match_results[0].first - begin;
2824 }
2825 else
2826 {
2827 // Next search can start with the new data.
2828 search_position_ = end - begin;
2829 }
2830
2831 bytes_to_read_ = std::min<std::size_t>(
2832 std::max<std::size_t>(512,
2833 buffers_.capacity() - buffers_.size()),
2834 std::min<std::size_t>(65536,
2835 buffers_.max_size() - buffers_.size()));
2836 }
2837 }
2838
2839 // Check if we're done.
2840 if (!start && bytes_to_read_ == 0)
2841 break;
2842
2843 // Start a new asynchronous read operation to obtain more data.
2844 pos = buffers_.size();
2845 buffers_.grow(bytes_to_read_);
2846 {
2847 BOOST_ASIO_HANDLER_LOCATION((
2848 __FILE__, __LINE__, "async_read_until"));
2849 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
2850 BOOST_ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));
2851 }
2852 return; default:
2853 buffers_.shrink(bytes_to_read_ - bytes_transferred);
2854 if (ec || bytes_transferred == 0)
2855 break;
2856 }
2857
2858 const boost::system::error_code result_ec =
2859 (search_position_ == not_found)
2860 ? error::not_found : ec;
2861
2862 const std::size_t result_n =
2863 (ec || search_position_ == not_found)
2864 ? 0 : search_position_;
2865
2866 handler_(result_ec, result_n);
2867 }
2868 }
2869
2870 //private:
2871 AsyncReadStream& stream_;
2872 DynamicBuffer_v2 buffers_;
2873 RegEx expr_;
2874 int start_;
2875 std::size_t search_position_;
2876 std::size_t bytes_to_read_;
2877 ReadHandler handler_;
2878 };
2879
2880 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2881 typename RegEx, typename ReadHandler>
2882 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_expr_op_v2<AsyncReadStream,DynamicBuffer_v2,RegEx,ReadHandler> * this_handler)2883 asio_handler_allocate(std::size_t size,
2884 read_until_expr_op_v2<AsyncReadStream,
2885 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2886 {
2887 #if defined(BOOST_ASIO_NO_DEPRECATED)
2888 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
2889 return asio_handler_allocate_is_no_longer_used();
2890 #else // defined(BOOST_ASIO_NO_DEPRECATED)
2891 return boost_asio_handler_alloc_helpers::allocate(
2892 size, this_handler->handler_);
2893 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2894 }
2895
2896 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2897 typename RegEx, typename ReadHandler>
2898 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_expr_op_v2<AsyncReadStream,DynamicBuffer_v2,RegEx,ReadHandler> * this_handler)2899 asio_handler_deallocate(void* pointer, std::size_t size,
2900 read_until_expr_op_v2<AsyncReadStream,
2901 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2902 {
2903 boost_asio_handler_alloc_helpers::deallocate(
2904 pointer, size, this_handler->handler_);
2905 #if defined(BOOST_ASIO_NO_DEPRECATED)
2906 return asio_handler_deallocate_is_no_longer_used();
2907 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2908 }
2909
2910 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2911 typename RegEx, typename ReadHandler>
asio_handler_is_continuation(read_until_expr_op_v2<AsyncReadStream,DynamicBuffer_v2,RegEx,ReadHandler> * this_handler)2912 inline bool asio_handler_is_continuation(
2913 read_until_expr_op_v2<AsyncReadStream,
2914 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2915 {
2916 return this_handler->start_ == 0 ? true
2917 : boost_asio_handler_cont_helpers::is_continuation(
2918 this_handler->handler_);
2919 }
2920
2921 template <typename Function, typename AsyncReadStream,
2922 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2923 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_expr_op_v2<AsyncReadStream,DynamicBuffer_v2,RegEx,ReadHandler> * this_handler)2924 asio_handler_invoke(Function& function,
2925 read_until_expr_op_v2<AsyncReadStream,
2926 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2927 {
2928 boost_asio_handler_invoke_helpers::invoke(
2929 function, this_handler->handler_);
2930 #if defined(BOOST_ASIO_NO_DEPRECATED)
2931 return asio_handler_invoke_is_no_longer_used();
2932 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2933 }
2934
2935 template <typename Function, typename AsyncReadStream,
2936 typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>
2937 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_expr_op_v2<AsyncReadStream,DynamicBuffer_v2,RegEx,ReadHandler> * this_handler)2938 asio_handler_invoke(const Function& function,
2939 read_until_expr_op_v2<AsyncReadStream,
2940 DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)
2941 {
2942 boost_asio_handler_invoke_helpers::invoke(
2943 function, this_handler->handler_);
2944 #if defined(BOOST_ASIO_NO_DEPRECATED)
2945 return asio_handler_invoke_is_no_longer_used();
2946 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
2947 }
2948
2949 template <typename AsyncReadStream>
2950 class initiate_async_read_until_expr_v2
2951 {
2952 public:
2953 typedef typename AsyncReadStream::executor_type executor_type;
2954
initiate_async_read_until_expr_v2(AsyncReadStream & stream)2955 explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)
2956 : stream_(stream)
2957 {
2958 }
2959
get_executor() const2960 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
2961 {
2962 return stream_.get_executor();
2963 }
2964
2965 template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,const RegEx & expr) const2966 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
2967 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
2968 const RegEx& expr) const
2969 {
2970 // If you get an error on the following line it means that your handler
2971 // does not meet the documented type requirements for a ReadHandler.
2972 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
2973
2974 non_const_lvalue<ReadHandler> handler2(handler);
2975 read_until_expr_op_v2<AsyncReadStream,
2976 typename decay<DynamicBuffer_v2>::type,
2977 RegEx, typename decay<ReadHandler>::type>(
2978 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
2979 expr, handler2.value)(boost::system::error_code(), 0, 1);
2980 }
2981
2982 private:
2983 AsyncReadStream& stream_;
2984 };
2985 } // namespace detail
2986
2987 #if !defined(GENERATING_DOCUMENTATION)
2988
2989 template <typename AsyncReadStream, typename DynamicBuffer_v2,
2990 typename RegEx, typename ReadHandler, typename Allocator>
2991 struct associated_allocator<
2992 detail::read_until_expr_op_v2<AsyncReadStream,
2993 DynamicBuffer_v2, RegEx, ReadHandler>,
2994 Allocator>
2995 {
2996 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
2997
getboost::asio::associated_allocator2998 static type get(
2999 const detail::read_until_expr_op_v2<AsyncReadStream,
3000 DynamicBuffer_v2, RegEx, ReadHandler>& h,
3001 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
3002 {
3003 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
3004 }
3005 };
3006
3007 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3008 typename RegEx, typename ReadHandler, typename Executor>
3009 struct associated_executor<
3010 detail::read_until_expr_op_v2<AsyncReadStream,
3011 DynamicBuffer_v2, RegEx, ReadHandler>,
3012 Executor>
3013 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
3014 {
3015 typedef typename associated_executor<ReadHandler, Executor>::type type;
3016
getboost::asio::associated_executor3017 static type get(
3018 const detail::read_until_expr_op_v2<AsyncReadStream,
3019 DynamicBuffer_v2, RegEx, ReadHandler>& h,
3020 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
3021 {
3022 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
3023 }
3024 };
3025
3026 #endif // !defined(GENERATING_DOCUMENTATION)
3027
3028 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3029 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
3030 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))3031 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
3032 void (boost::system::error_code, std::size_t))
3033 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
3034 const boost::regex& expr, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3035 typename constraint<
3036 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
3037 >::type)
3038 {
3039 return async_initiate<ReadHandler,
3040 void (boost::system::error_code, std::size_t)>(
3041 detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),
3042 handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);
3043 }
3044
3045 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
3046
3047 namespace detail
3048 {
3049 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3050 typename MatchCondition, typename ReadHandler>
3051 class read_until_match_op_v2
3052 {
3053 public:
3054 template <typename BufferSequence>
read_until_match_op_v2(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,MatchCondition match_condition,ReadHandler & handler)3055 read_until_match_op_v2(AsyncReadStream& stream,
3056 BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
3057 MatchCondition match_condition, ReadHandler& handler)
3058 : stream_(stream),
3059 buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
3060 match_condition_(match_condition),
3061 start_(0),
3062 search_position_(0),
3063 bytes_to_read_(0),
3064 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
3065 {
3066 }
3067
3068 #if defined(BOOST_ASIO_HAS_MOVE)
read_until_match_op_v2(const read_until_match_op_v2 & other)3069 read_until_match_op_v2(const read_until_match_op_v2& other)
3070 : stream_(other.stream_),
3071 buffers_(other.buffers_),
3072 match_condition_(other.match_condition_),
3073 start_(other.start_),
3074 search_position_(other.search_position_),
3075 bytes_to_read_(other.bytes_to_read_),
3076 handler_(other.handler_)
3077 {
3078 }
3079
read_until_match_op_v2(read_until_match_op_v2 && other)3080 read_until_match_op_v2(read_until_match_op_v2&& other)
3081 : stream_(other.stream_),
3082 buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
3083 match_condition_(other.match_condition_),
3084 start_(other.start_),
3085 search_position_(other.search_position_),
3086 bytes_to_read_(other.bytes_to_read_),
3087 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
3088 {
3089 }
3090 #endif // defined(BOOST_ASIO_HAS_MOVE)
3091
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)3092 void operator()(const boost::system::error_code& ec,
3093 std::size_t bytes_transferred, int start = 0)
3094 {
3095 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
3096 std::size_t pos;
3097 switch (start_ = start)
3098 {
3099 case 1:
3100 for (;;)
3101 {
3102 {
3103 // Determine the range of the data to be searched.
3104 typedef typename DynamicBuffer_v2::const_buffers_type
3105 buffers_type;
3106 typedef buffers_iterator<buffers_type> iterator;
3107 buffers_type data_buffers =
3108 const_cast<const DynamicBuffer_v2&>(buffers_).data(
3109 0, buffers_.size());
3110 iterator begin = iterator::begin(data_buffers);
3111 iterator start_pos = begin + search_position_;
3112 iterator end = iterator::end(data_buffers);
3113
3114 // Look for a match.
3115 std::pair<iterator, bool> result = match_condition_(start_pos, end);
3116 if (result.second)
3117 {
3118 // Full match. We're done.
3119 search_position_ = result.first - begin;
3120 bytes_to_read_ = 0;
3121 }
3122
3123 // No match yet. Check if buffer is full.
3124 else if (buffers_.size() == buffers_.max_size())
3125 {
3126 search_position_ = not_found;
3127 bytes_to_read_ = 0;
3128 }
3129
3130 // Need to read some more data.
3131 else
3132 {
3133 if (result.first != end)
3134 {
3135 // Partial match. Next search needs to start from beginning of
3136 // match.
3137 search_position_ = result.first - begin;
3138 }
3139 else
3140 {
3141 // Next search can start with the new data.
3142 search_position_ = end - begin;
3143 }
3144
3145 bytes_to_read_ = std::min<std::size_t>(
3146 std::max<std::size_t>(512,
3147 buffers_.capacity() - buffers_.size()),
3148 std::min<std::size_t>(65536,
3149 buffers_.max_size() - buffers_.size()));
3150 }
3151 }
3152
3153 // Check if we're done.
3154 if (!start && bytes_to_read_ == 0)
3155 break;
3156
3157 // Start a new asynchronous read operation to obtain more data.
3158 pos = buffers_.size();
3159 buffers_.grow(bytes_to_read_);
3160 {
3161 BOOST_ASIO_HANDLER_LOCATION((
3162 __FILE__, __LINE__, "async_read_until"));
3163 stream_.async_read_some(buffers_.data(pos, bytes_to_read_),
3164 BOOST_ASIO_MOVE_CAST(read_until_match_op_v2)(*this));
3165 }
3166 return; default:
3167 buffers_.shrink(bytes_to_read_ - bytes_transferred);
3168 if (ec || bytes_transferred == 0)
3169 break;
3170 }
3171
3172 const boost::system::error_code result_ec =
3173 (search_position_ == not_found)
3174 ? error::not_found : ec;
3175
3176 const std::size_t result_n =
3177 (ec || search_position_ == not_found)
3178 ? 0 : search_position_;
3179
3180 handler_(result_ec, result_n);
3181 }
3182 }
3183
3184 //private:
3185 AsyncReadStream& stream_;
3186 DynamicBuffer_v2 buffers_;
3187 MatchCondition match_condition_;
3188 int start_;
3189 std::size_t search_position_;
3190 std::size_t bytes_to_read_;
3191 ReadHandler handler_;
3192 };
3193
3194 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3195 typename MatchCondition, typename ReadHandler>
3196 inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_until_match_op_v2<AsyncReadStream,DynamicBuffer_v2,MatchCondition,ReadHandler> * this_handler)3197 asio_handler_allocate(std::size_t size,
3198 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3199 MatchCondition, ReadHandler>* this_handler)
3200 {
3201 #if defined(BOOST_ASIO_NO_DEPRECATED)
3202 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
3203 return asio_handler_allocate_is_no_longer_used();
3204 #else // defined(BOOST_ASIO_NO_DEPRECATED)
3205 return boost_asio_handler_alloc_helpers::allocate(
3206 size, this_handler->handler_);
3207 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3208 }
3209
3210 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3211 typename MatchCondition, typename ReadHandler>
3212 inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_until_match_op_v2<AsyncReadStream,DynamicBuffer_v2,MatchCondition,ReadHandler> * this_handler)3213 asio_handler_deallocate(void* pointer, std::size_t size,
3214 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3215 MatchCondition, ReadHandler>* this_handler)
3216 {
3217 boost_asio_handler_alloc_helpers::deallocate(
3218 pointer, size, this_handler->handler_);
3219 #if defined(BOOST_ASIO_NO_DEPRECATED)
3220 return asio_handler_deallocate_is_no_longer_used();
3221 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3222 }
3223
3224 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3225 typename MatchCondition, typename ReadHandler>
asio_handler_is_continuation(read_until_match_op_v2<AsyncReadStream,DynamicBuffer_v2,MatchCondition,ReadHandler> * this_handler)3226 inline bool asio_handler_is_continuation(
3227 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3228 MatchCondition, ReadHandler>* this_handler)
3229 {
3230 return this_handler->start_ == 0 ? true
3231 : boost_asio_handler_cont_helpers::is_continuation(
3232 this_handler->handler_);
3233 }
3234
3235 template <typename Function, typename AsyncReadStream,
3236 typename DynamicBuffer_v2, typename MatchCondition,
3237 typename ReadHandler>
3238 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_until_match_op_v2<AsyncReadStream,DynamicBuffer_v2,MatchCondition,ReadHandler> * this_handler)3239 asio_handler_invoke(Function& function,
3240 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3241 MatchCondition, ReadHandler>* this_handler)
3242 {
3243 boost_asio_handler_invoke_helpers::invoke(
3244 function, this_handler->handler_);
3245 #if defined(BOOST_ASIO_NO_DEPRECATED)
3246 return asio_handler_invoke_is_no_longer_used();
3247 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3248 }
3249
3250 template <typename Function, typename AsyncReadStream,
3251 typename DynamicBuffer_v2, typename MatchCondition,
3252 typename ReadHandler>
3253 inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_until_match_op_v2<AsyncReadStream,DynamicBuffer_v2,MatchCondition,ReadHandler> * this_handler)3254 asio_handler_invoke(const Function& function,
3255 read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,
3256 MatchCondition, ReadHandler>* this_handler)
3257 {
3258 boost_asio_handler_invoke_helpers::invoke(
3259 function, this_handler->handler_);
3260 #if defined(BOOST_ASIO_NO_DEPRECATED)
3261 return asio_handler_invoke_is_no_longer_used();
3262 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
3263 }
3264
3265 template <typename AsyncReadStream>
3266 class initiate_async_read_until_match_v2
3267 {
3268 public:
3269 typedef typename AsyncReadStream::executor_type executor_type;
3270
initiate_async_read_until_match_v2(AsyncReadStream & stream)3271 explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)
3272 : stream_(stream)
3273 {
3274 }
3275
get_executor() const3276 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
3277 {
3278 return stream_.get_executor();
3279 }
3280
3281 template <typename ReadHandler,
3282 typename DynamicBuffer_v2, typename MatchCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,MatchCondition match_condition) const3283 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3284 BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
3285 MatchCondition match_condition) const
3286 {
3287 // If you get an error on the following line it means that your handler
3288 // does not meet the documented type requirements for a ReadHandler.
3289 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
3290
3291 non_const_lvalue<ReadHandler> handler2(handler);
3292 read_until_match_op_v2<AsyncReadStream,
3293 typename decay<DynamicBuffer_v2>::type,
3294 MatchCondition, typename decay<ReadHandler>::type>(
3295 stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
3296 match_condition, handler2.value)(boost::system::error_code(), 0, 1);
3297 }
3298
3299 private:
3300 AsyncReadStream& stream_;
3301 };
3302 } // namespace detail
3303
3304 #if !defined(GENERATING_DOCUMENTATION)
3305
3306 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3307 typename MatchCondition, typename ReadHandler, typename Allocator>
3308 struct associated_allocator<
3309 detail::read_until_match_op_v2<AsyncReadStream,
3310 DynamicBuffer_v2, MatchCondition, ReadHandler>,
3311 Allocator>
3312 {
3313 typedef typename associated_allocator<ReadHandler, Allocator>::type type;
3314
getboost::asio::associated_allocator3315 static type get(
3316 const detail::read_until_match_op_v2<AsyncReadStream,
3317 DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
3318 const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
3319 {
3320 return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
3321 }
3322 };
3323
3324 template <typename AsyncReadStream, typename DynamicBuffer_v2,
3325 typename MatchCondition, typename ReadHandler, typename Executor>
3326 struct associated_executor<
3327 detail::read_until_match_op_v2<AsyncReadStream,
3328 DynamicBuffer_v2, MatchCondition, ReadHandler>,
3329 Executor>
3330 : detail::associated_executor_forwarding_base<ReadHandler, Executor>
3331 {
3332 typedef typename associated_executor<ReadHandler, Executor>::type type;
3333
getboost::asio::associated_executor3334 static type get(
3335 const detail::read_until_match_op_v2<AsyncReadStream,
3336 DynamicBuffer_v2, MatchCondition, ReadHandler>& h,
3337 const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
3338 {
3339 return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
3340 }
3341 };
3342
3343 #endif // !defined(GENERATING_DOCUMENTATION)
3344
3345 template <typename AsyncReadStream,
3346 typename DynamicBuffer_v2, typename MatchCondition,
3347 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
3348 std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))3349 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
3350 void (boost::system::error_code, std::size_t))
3351 async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,
3352 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
3353 typename constraint<
3354 is_match_condition<MatchCondition>::value
3355 >::type,
3356 typename constraint<
3357 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
3358 >::type)
3359 {
3360 return async_initiate<ReadHandler,
3361 void (boost::system::error_code, std::size_t)>(
3362 detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), handler,
3363 BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);
3364 }
3365
3366 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
3367
3368 } // namespace asio
3369 } // namespace boost
3370
3371 #include <boost/asio/detail/pop_options.hpp>
3372
3373 #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP
3374