1 //
2 // read_until.cpp
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 // Disable autolinking for unit tests.
12 #if !defined(BOOST_ALL_NO_LIB)
13 #define BOOST_ALL_NO_LIB 1
14 #endif // !defined(BOOST_ALL_NO_LIB)
15 
16 // Test that header file is self-contained.
17 #include <boost/asio/read_until.hpp>
18 
19 #include <cstring>
20 #include "archetypes/async_result.hpp"
21 #include <boost/asio/io_context.hpp>
22 #include <boost/asio/post.hpp>
23 #include <boost/asio/streambuf.hpp>
24 #include "unit_test.hpp"
25 
26 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
27 # include <boost/bind/bind.hpp>
28 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
29 # include <functional>
30 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
31 
32 class test_stream
33 {
34 public:
35   typedef boost::asio::io_context::executor_type executor_type;
36 
test_stream(boost::asio::io_context & io_context)37   test_stream(boost::asio::io_context& io_context)
38     : io_context_(io_context),
39       length_(0),
40       position_(0),
41       next_read_length_(0)
42   {
43   }
44 
get_executor()45   executor_type get_executor() BOOST_ASIO_NOEXCEPT
46   {
47     return io_context_.get_executor();
48   }
49 
reset(const void * data,size_t length)50   void reset(const void* data, size_t length)
51   {
52     using namespace std; // For memcpy.
53 
54     BOOST_ASIO_CHECK(length <= max_length);
55 
56     memcpy(data_, data, length);
57     length_ = length;
58     position_ = 0;
59     next_read_length_ = length;
60   }
61 
next_read_length(size_t length)62   void next_read_length(size_t length)
63   {
64     next_read_length_ = length;
65   }
66 
67   template <typename Mutable_Buffers>
read_some(const Mutable_Buffers & buffers)68   size_t read_some(const Mutable_Buffers& buffers)
69   {
70     size_t n = boost::asio::buffer_copy(buffers,
71         boost::asio::buffer(data_, length_) + position_,
72         next_read_length_);
73     position_ += n;
74     return n;
75   }
76 
77   template <typename Mutable_Buffers>
read_some(const Mutable_Buffers & buffers,boost::system::error_code & ec)78   size_t read_some(const Mutable_Buffers& buffers,
79       boost::system::error_code& ec)
80   {
81     ec = boost::system::error_code();
82     return read_some(buffers);
83   }
84 
85   template <typename Mutable_Buffers, typename Handler>
async_read_some(const Mutable_Buffers & buffers,Handler handler)86   void async_read_some(const Mutable_Buffers& buffers, Handler handler)
87   {
88     size_t bytes_transferred = read_some(buffers);
89     boost::asio::post(get_executor(),
90         boost::asio::detail::bind_handler(
91           BOOST_ASIO_MOVE_CAST(Handler)(handler),
92           boost::system::error_code(), bytes_transferred));
93   }
94 
95 private:
96   boost::asio::io_context& io_context_;
97   enum { max_length = 8192 };
98   char data_[max_length];
99   size_t length_;
100   size_t position_;
101   size_t next_read_length_;
102 };
103 
104 static const char read_data[]
105   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
106 
test_dynamic_string_read_until_char()107 void test_dynamic_string_read_until_char()
108 {
109   boost::asio::io_context ioc;
110   test_stream s(ioc);
111   std::string data1, data2;
112   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
113     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
114   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
115     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
116   boost::system::error_code ec;
117 
118   s.reset(read_data, sizeof(read_data));
119   sb1.consume(sb1.size());
120   std::size_t length = boost::asio::read_until(s, sb1, 'Z');
121   BOOST_ASIO_CHECK(length == 26);
122 
123   s.reset(read_data, sizeof(read_data));
124   s.next_read_length(1);
125   sb1.consume(sb1.size());
126   length = boost::asio::read_until(s, sb1, 'Z');
127   BOOST_ASIO_CHECK(length == 26);
128 
129   s.reset(read_data, sizeof(read_data));
130   s.next_read_length(10);
131   sb1.consume(sb1.size());
132   length = boost::asio::read_until(s, sb1, 'Z');
133   BOOST_ASIO_CHECK(length == 26);
134 
135   s.reset(read_data, sizeof(read_data));
136   sb1.consume(sb1.size());
137   length = boost::asio::read_until(s, sb1, 'Z', ec);
138   BOOST_ASIO_CHECK(!ec);
139   BOOST_ASIO_CHECK(length == 26);
140 
141   s.reset(read_data, sizeof(read_data));
142   s.next_read_length(1);
143   sb1.consume(sb1.size());
144   length = boost::asio::read_until(s, sb1, 'Z', ec);
145   BOOST_ASIO_CHECK(!ec);
146   BOOST_ASIO_CHECK(length == 26);
147 
148   s.reset(read_data, sizeof(read_data));
149   s.next_read_length(10);
150   sb1.consume(sb1.size());
151   length = boost::asio::read_until(s, sb1, 'Z', ec);
152   BOOST_ASIO_CHECK(!ec);
153   BOOST_ASIO_CHECK(length == 26);
154 
155   s.reset(read_data, sizeof(read_data));
156   sb2.consume(sb2.size());
157   length = boost::asio::read_until(s, sb2, 'Z', ec);
158   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
159   BOOST_ASIO_CHECK(length == 0);
160 
161   s.reset(read_data, sizeof(read_data));
162   s.next_read_length(1);
163   sb2.consume(sb2.size());
164   length = boost::asio::read_until(s, sb2, 'Z', ec);
165   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
166   BOOST_ASIO_CHECK(length == 0);
167 
168   s.reset(read_data, sizeof(read_data));
169   s.next_read_length(10);
170   sb2.consume(sb2.size());
171   length = boost::asio::read_until(s, sb2, 'Z', ec);
172   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
173   BOOST_ASIO_CHECK(length == 0);
174 
175   s.reset(read_data, sizeof(read_data));
176   sb2.consume(sb2.size());
177   length = boost::asio::read_until(s, sb2, 'Y', ec);
178   BOOST_ASIO_CHECK(!ec);
179   BOOST_ASIO_CHECK(length == 25);
180 
181   s.reset(read_data, sizeof(read_data));
182   s.next_read_length(1);
183   sb2.consume(sb2.size());
184   length = boost::asio::read_until(s, sb2, 'Y', ec);
185   BOOST_ASIO_CHECK(!ec);
186   BOOST_ASIO_CHECK(length == 25);
187 
188   s.reset(read_data, sizeof(read_data));
189   s.next_read_length(10);
190   sb2.consume(sb2.size());
191   length = boost::asio::read_until(s, sb2, 'Y', ec);
192   BOOST_ASIO_CHECK(!ec);
193   BOOST_ASIO_CHECK(length == 25);
194 }
195 
test_streambuf_read_until_char()196 void test_streambuf_read_until_char()
197 {
198 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
199   boost::asio::io_context ioc;
200   test_stream s(ioc);
201   boost::asio::streambuf sb1;
202   boost::asio::streambuf sb2(25);
203   boost::system::error_code ec;
204 
205   s.reset(read_data, sizeof(read_data));
206   sb1.consume(sb1.size());
207   std::size_t length = boost::asio::read_until(s, sb1, 'Z');
208   BOOST_ASIO_CHECK(length == 26);
209 
210   s.reset(read_data, sizeof(read_data));
211   s.next_read_length(1);
212   sb1.consume(sb1.size());
213   length = boost::asio::read_until(s, sb1, 'Z');
214   BOOST_ASIO_CHECK(length == 26);
215 
216   s.reset(read_data, sizeof(read_data));
217   s.next_read_length(10);
218   sb1.consume(sb1.size());
219   length = boost::asio::read_until(s, sb1, 'Z');
220   BOOST_ASIO_CHECK(length == 26);
221 
222   s.reset(read_data, sizeof(read_data));
223   sb1.consume(sb1.size());
224   length = boost::asio::read_until(s, sb1, 'Z', ec);
225   BOOST_ASIO_CHECK(!ec);
226   BOOST_ASIO_CHECK(length == 26);
227 
228   s.reset(read_data, sizeof(read_data));
229   s.next_read_length(1);
230   sb1.consume(sb1.size());
231   length = boost::asio::read_until(s, sb1, 'Z', ec);
232   BOOST_ASIO_CHECK(!ec);
233   BOOST_ASIO_CHECK(length == 26);
234 
235   s.reset(read_data, sizeof(read_data));
236   s.next_read_length(10);
237   sb1.consume(sb1.size());
238   length = boost::asio::read_until(s, sb1, 'Z', ec);
239   BOOST_ASIO_CHECK(!ec);
240   BOOST_ASIO_CHECK(length == 26);
241 
242   s.reset(read_data, sizeof(read_data));
243   sb2.consume(sb2.size());
244   length = boost::asio::read_until(s, sb2, 'Z', ec);
245   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
246   BOOST_ASIO_CHECK(length == 0);
247 
248   s.reset(read_data, sizeof(read_data));
249   s.next_read_length(1);
250   sb2.consume(sb2.size());
251   length = boost::asio::read_until(s, sb2, 'Z', ec);
252   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
253   BOOST_ASIO_CHECK(length == 0);
254 
255   s.reset(read_data, sizeof(read_data));
256   s.next_read_length(10);
257   sb2.consume(sb2.size());
258   length = boost::asio::read_until(s, sb2, 'Z', ec);
259   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
260   BOOST_ASIO_CHECK(length == 0);
261 
262   s.reset(read_data, sizeof(read_data));
263   sb2.consume(sb2.size());
264   length = boost::asio::read_until(s, sb2, 'Y', ec);
265   BOOST_ASIO_CHECK(!ec);
266   BOOST_ASIO_CHECK(length == 25);
267 
268   s.reset(read_data, sizeof(read_data));
269   s.next_read_length(1);
270   sb2.consume(sb2.size());
271   length = boost::asio::read_until(s, sb2, 'Y', ec);
272   BOOST_ASIO_CHECK(!ec);
273   BOOST_ASIO_CHECK(length == 25);
274 
275   s.reset(read_data, sizeof(read_data));
276   s.next_read_length(10);
277   sb2.consume(sb2.size());
278   length = boost::asio::read_until(s, sb2, 'Y', ec);
279   BOOST_ASIO_CHECK(!ec);
280   BOOST_ASIO_CHECK(length == 25);
281 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
282 }
283 
test_dynamic_string_read_until_string()284 void test_dynamic_string_read_until_string()
285 {
286   boost::asio::io_context ioc;
287   test_stream s(ioc);
288   std::string data1, data2;
289   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
290     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
291   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
292     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
293   boost::system::error_code ec;
294 
295   s.reset(read_data, sizeof(read_data));
296   sb1.consume(sb1.size());
297   std::size_t length = boost::asio::read_until(s, sb1, "XYZ");
298   BOOST_ASIO_CHECK(length == 26);
299 
300   s.reset(read_data, sizeof(read_data));
301   s.next_read_length(1);
302   sb1.consume(sb1.size());
303   length = boost::asio::read_until(s, sb1, "XYZ");
304   BOOST_ASIO_CHECK(length == 26);
305 
306   s.reset(read_data, sizeof(read_data));
307   s.next_read_length(10);
308   sb1.consume(sb1.size());
309   length = boost::asio::read_until(s, sb1, "XYZ");
310   BOOST_ASIO_CHECK(length == 26);
311 
312   s.reset(read_data, sizeof(read_data));
313   sb1.consume(sb1.size());
314   length = boost::asio::read_until(s, sb1, "XYZ", ec);
315   BOOST_ASIO_CHECK(!ec);
316   BOOST_ASIO_CHECK(length == 26);
317 
318   s.reset(read_data, sizeof(read_data));
319   s.next_read_length(1);
320   sb1.consume(sb1.size());
321   length = boost::asio::read_until(s, sb1, "XYZ", ec);
322   BOOST_ASIO_CHECK(!ec);
323   BOOST_ASIO_CHECK(length == 26);
324 
325   s.reset(read_data, sizeof(read_data));
326   s.next_read_length(10);
327   sb1.consume(sb1.size());
328   length = boost::asio::read_until(s, sb1, "XYZ", ec);
329   BOOST_ASIO_CHECK(!ec);
330   BOOST_ASIO_CHECK(length == 26);
331 
332   s.reset(read_data, sizeof(read_data));
333   sb2.consume(sb2.size());
334   length = boost::asio::read_until(s, sb2, "XYZ", ec);
335   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
336   BOOST_ASIO_CHECK(length == 0);
337 
338   s.reset(read_data, sizeof(read_data));
339   s.next_read_length(1);
340   sb2.consume(sb2.size());
341   length = boost::asio::read_until(s, sb2, "XYZ", ec);
342   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
343   BOOST_ASIO_CHECK(length == 0);
344 
345   s.reset(read_data, sizeof(read_data));
346   s.next_read_length(10);
347   sb2.consume(sb2.size());
348   length = boost::asio::read_until(s, sb2, "XYZ", ec);
349   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
350   BOOST_ASIO_CHECK(length == 0);
351 
352   s.reset(read_data, sizeof(read_data));
353   sb2.consume(sb2.size());
354   length = boost::asio::read_until(s, sb2, "WXY", ec);
355   BOOST_ASIO_CHECK(!ec);
356   BOOST_ASIO_CHECK(length == 25);
357 
358   s.reset(read_data, sizeof(read_data));
359   s.next_read_length(1);
360   sb2.consume(sb2.size());
361   length = boost::asio::read_until(s, sb2, "WXY", ec);
362   BOOST_ASIO_CHECK(!ec);
363   BOOST_ASIO_CHECK(length == 25);
364 
365   s.reset(read_data, sizeof(read_data));
366   s.next_read_length(10);
367   sb2.consume(sb2.size());
368   length = boost::asio::read_until(s, sb2, "WXY", ec);
369   BOOST_ASIO_CHECK(!ec);
370   BOOST_ASIO_CHECK(length == 25);
371 }
372 
test_streambuf_read_until_string()373 void test_streambuf_read_until_string()
374 {
375 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
376   boost::asio::io_context ioc;
377   test_stream s(ioc);
378   boost::asio::streambuf sb1;
379   boost::asio::streambuf sb2(25);
380   boost::system::error_code ec;
381 
382   s.reset(read_data, sizeof(read_data));
383   sb1.consume(sb1.size());
384   std::size_t length = boost::asio::read_until(s, sb1, "XYZ");
385   BOOST_ASIO_CHECK(length == 26);
386 
387   s.reset(read_data, sizeof(read_data));
388   s.next_read_length(1);
389   sb1.consume(sb1.size());
390   length = boost::asio::read_until(s, sb1, "XYZ");
391   BOOST_ASIO_CHECK(length == 26);
392 
393   s.reset(read_data, sizeof(read_data));
394   s.next_read_length(10);
395   sb1.consume(sb1.size());
396   length = boost::asio::read_until(s, sb1, "XYZ");
397   BOOST_ASIO_CHECK(length == 26);
398 
399   s.reset(read_data, sizeof(read_data));
400   sb1.consume(sb1.size());
401   length = boost::asio::read_until(s, sb1, "XYZ", ec);
402   BOOST_ASIO_CHECK(!ec);
403   BOOST_ASIO_CHECK(length == 26);
404 
405   s.reset(read_data, sizeof(read_data));
406   s.next_read_length(1);
407   sb1.consume(sb1.size());
408   length = boost::asio::read_until(s, sb1, "XYZ", ec);
409   BOOST_ASIO_CHECK(!ec);
410   BOOST_ASIO_CHECK(length == 26);
411 
412   s.reset(read_data, sizeof(read_data));
413   s.next_read_length(10);
414   sb1.consume(sb1.size());
415   length = boost::asio::read_until(s, sb1, "XYZ", ec);
416   BOOST_ASIO_CHECK(!ec);
417   BOOST_ASIO_CHECK(length == 26);
418 
419   s.reset(read_data, sizeof(read_data));
420   sb2.consume(sb2.size());
421   length = boost::asio::read_until(s, sb2, "XYZ", ec);
422   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
423   BOOST_ASIO_CHECK(length == 0);
424 
425   s.reset(read_data, sizeof(read_data));
426   s.next_read_length(1);
427   sb2.consume(sb2.size());
428   length = boost::asio::read_until(s, sb2, "XYZ", ec);
429   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
430   BOOST_ASIO_CHECK(length == 0);
431 
432   s.reset(read_data, sizeof(read_data));
433   s.next_read_length(10);
434   sb2.consume(sb2.size());
435   length = boost::asio::read_until(s, sb2, "XYZ", ec);
436   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
437   BOOST_ASIO_CHECK(length == 0);
438 
439   s.reset(read_data, sizeof(read_data));
440   sb2.consume(sb2.size());
441   length = boost::asio::read_until(s, sb2, "WXY", ec);
442   BOOST_ASIO_CHECK(!ec);
443   BOOST_ASIO_CHECK(length == 25);
444 
445   s.reset(read_data, sizeof(read_data));
446   s.next_read_length(1);
447   sb2.consume(sb2.size());
448   length = boost::asio::read_until(s, sb2, "WXY", ec);
449   BOOST_ASIO_CHECK(!ec);
450   BOOST_ASIO_CHECK(length == 25);
451 
452   s.reset(read_data, sizeof(read_data));
453   s.next_read_length(10);
454   sb2.consume(sb2.size());
455   length = boost::asio::read_until(s, sb2, "WXY", ec);
456   BOOST_ASIO_CHECK(!ec);
457   BOOST_ASIO_CHECK(length == 25);
458 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
459 }
460 
461 class match_char
462 {
463 public:
match_char(char c)464   explicit match_char(char c) : c_(c) {}
465 
466   template <typename Iterator>
operator ()(Iterator begin,Iterator end) const467   std::pair<Iterator, bool> operator()(
468       Iterator begin, Iterator end) const
469   {
470     Iterator i = begin;
471     while (i != end)
472       if (c_ == *i++)
473         return std::make_pair(i, true);
474     return std::make_pair(i, false);
475   }
476 
477 private:
478   char c_;
479 };
480 
481 namespace boost {
482 namespace asio {
483   template <> struct is_match_condition<match_char>
484   {
485     enum { value = true };
486   };
487 } // namespace asio
488 } // namespace boost
489 
test_dynamic_string_read_until_match_condition()490 void test_dynamic_string_read_until_match_condition()
491 {
492   boost::asio::io_context ioc;
493   test_stream s(ioc);
494   std::string data1, data2;
495   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
496     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
497   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
498     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
499   boost::system::error_code ec;
500 
501   s.reset(read_data, sizeof(read_data));
502   sb1.consume(sb1.size());
503   std::size_t length = boost::asio::read_until(s, sb1, match_char('Z'));
504   BOOST_ASIO_CHECK(length == 26);
505 
506   s.reset(read_data, sizeof(read_data));
507   s.next_read_length(1);
508   sb1.consume(sb1.size());
509   length = boost::asio::read_until(s, sb1, match_char('Z'));
510   BOOST_ASIO_CHECK(length == 26);
511 
512   s.reset(read_data, sizeof(read_data));
513   s.next_read_length(10);
514   sb1.consume(sb1.size());
515   length = boost::asio::read_until(s, sb1, match_char('Z'));
516   BOOST_ASIO_CHECK(length == 26);
517 
518   s.reset(read_data, sizeof(read_data));
519   sb1.consume(sb1.size());
520   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
521   BOOST_ASIO_CHECK(!ec);
522   BOOST_ASIO_CHECK(length == 26);
523 
524   s.reset(read_data, sizeof(read_data));
525   s.next_read_length(1);
526   sb1.consume(sb1.size());
527   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
528   BOOST_ASIO_CHECK(!ec);
529   BOOST_ASIO_CHECK(length == 26);
530 
531   s.reset(read_data, sizeof(read_data));
532   s.next_read_length(10);
533   sb1.consume(sb1.size());
534   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
535   BOOST_ASIO_CHECK(!ec);
536   BOOST_ASIO_CHECK(length == 26);
537 
538   s.reset(read_data, sizeof(read_data));
539   sb2.consume(sb2.size());
540   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
541   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
542   BOOST_ASIO_CHECK(length == 0);
543 
544   s.reset(read_data, sizeof(read_data));
545   s.next_read_length(1);
546   sb2.consume(sb2.size());
547   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
548   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
549   BOOST_ASIO_CHECK(length == 0);
550 
551   s.reset(read_data, sizeof(read_data));
552   s.next_read_length(10);
553   sb2.consume(sb2.size());
554   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
555   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
556   BOOST_ASIO_CHECK(length == 0);
557 
558   s.reset(read_data, sizeof(read_data));
559   sb2.consume(sb2.size());
560   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
561   BOOST_ASIO_CHECK(!ec);
562   BOOST_ASIO_CHECK(length == 25);
563 
564   s.reset(read_data, sizeof(read_data));
565   s.next_read_length(1);
566   sb2.consume(sb2.size());
567   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
568   BOOST_ASIO_CHECK(!ec);
569   BOOST_ASIO_CHECK(length == 25);
570 
571   s.reset(read_data, sizeof(read_data));
572   s.next_read_length(10);
573   sb2.consume(sb2.size());
574   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
575   BOOST_ASIO_CHECK(!ec);
576   BOOST_ASIO_CHECK(length == 25);
577 }
578 
test_streambuf_read_until_match_condition()579 void test_streambuf_read_until_match_condition()
580 {
581 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
582   boost::asio::io_context ioc;
583   test_stream s(ioc);
584   boost::asio::streambuf sb1;
585   boost::asio::streambuf sb2(25);
586   boost::system::error_code ec;
587 
588   s.reset(read_data, sizeof(read_data));
589   sb1.consume(sb1.size());
590   std::size_t length = boost::asio::read_until(s, sb1, match_char('Z'));
591   BOOST_ASIO_CHECK(length == 26);
592 
593   s.reset(read_data, sizeof(read_data));
594   s.next_read_length(1);
595   sb1.consume(sb1.size());
596   length = boost::asio::read_until(s, sb1, match_char('Z'));
597   BOOST_ASIO_CHECK(length == 26);
598 
599   s.reset(read_data, sizeof(read_data));
600   s.next_read_length(10);
601   sb1.consume(sb1.size());
602   length = boost::asio::read_until(s, sb1, match_char('Z'));
603   BOOST_ASIO_CHECK(length == 26);
604 
605   s.reset(read_data, sizeof(read_data));
606   sb1.consume(sb1.size());
607   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
608   BOOST_ASIO_CHECK(!ec);
609   BOOST_ASIO_CHECK(length == 26);
610 
611   s.reset(read_data, sizeof(read_data));
612   s.next_read_length(1);
613   sb1.consume(sb1.size());
614   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
615   BOOST_ASIO_CHECK(!ec);
616   BOOST_ASIO_CHECK(length == 26);
617 
618   s.reset(read_data, sizeof(read_data));
619   s.next_read_length(10);
620   sb1.consume(sb1.size());
621   length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
622   BOOST_ASIO_CHECK(!ec);
623   BOOST_ASIO_CHECK(length == 26);
624 
625   s.reset(read_data, sizeof(read_data));
626   sb2.consume(sb2.size());
627   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
628   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
629   BOOST_ASIO_CHECK(length == 0);
630 
631   s.reset(read_data, sizeof(read_data));
632   s.next_read_length(1);
633   sb2.consume(sb2.size());
634   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
635   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
636   BOOST_ASIO_CHECK(length == 0);
637 
638   s.reset(read_data, sizeof(read_data));
639   s.next_read_length(10);
640   sb2.consume(sb2.size());
641   length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
642   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
643   BOOST_ASIO_CHECK(length == 0);
644 
645   s.reset(read_data, sizeof(read_data));
646   sb2.consume(sb2.size());
647   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
648   BOOST_ASIO_CHECK(!ec);
649   BOOST_ASIO_CHECK(length == 25);
650 
651   s.reset(read_data, sizeof(read_data));
652   s.next_read_length(1);
653   sb2.consume(sb2.size());
654   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
655   BOOST_ASIO_CHECK(!ec);
656   BOOST_ASIO_CHECK(length == 25);
657 
658   s.reset(read_data, sizeof(read_data));
659   s.next_read_length(10);
660   sb2.consume(sb2.size());
661   length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
662   BOOST_ASIO_CHECK(!ec);
663   BOOST_ASIO_CHECK(length == 25);
664 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
665 }
666 
async_read_handler(const boost::system::error_code & err,boost::system::error_code * err_out,std::size_t bytes_transferred,std::size_t * bytes_out,bool * called)667 void async_read_handler(
668     const boost::system::error_code& err, boost::system::error_code* err_out,
669     std::size_t bytes_transferred, std::size_t* bytes_out, bool* called)
670 {
671   *err_out = err;
672   *bytes_out = bytes_transferred;
673   *called = true;
674 }
675 
test_dynamic_string_async_read_until_char()676 void test_dynamic_string_async_read_until_char()
677 {
678 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
679   namespace bindns = boost;
680 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
681   namespace bindns = std;
682 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
683   using bindns::placeholders::_1;
684   using bindns::placeholders::_2;
685 
686   boost::asio::io_context ioc;
687   test_stream s(ioc);
688   std::string data1, data2;
689   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
690     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
691   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
692     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
693   boost::system::error_code ec;
694   std::size_t length;
695   bool called;
696 
697   s.reset(read_data, sizeof(read_data));
698   ec = boost::system::error_code();
699   length = 0;
700   called = false;
701   sb1.consume(sb1.size());
702   boost::asio::async_read_until(s, sb1, 'Z',
703       bindns::bind(async_read_handler, _1, &ec,
704         _2, &length, &called));
705   ioc.restart();
706   ioc.run();
707   BOOST_ASIO_CHECK(called);
708   BOOST_ASIO_CHECK(!ec);
709   BOOST_ASIO_CHECK(length == 26);
710 
711   s.reset(read_data, sizeof(read_data));
712   s.next_read_length(1);
713   ec = boost::system::error_code();
714   length = 0;
715   called = false;
716   sb1.consume(sb1.size());
717   boost::asio::async_read_until(s, sb1, 'Z',
718       bindns::bind(async_read_handler, _1, &ec,
719         _2, &length, &called));
720   ioc.restart();
721   ioc.run();
722   BOOST_ASIO_CHECK(called);
723   BOOST_ASIO_CHECK(!ec);
724   BOOST_ASIO_CHECK(length == 26);
725 
726   s.reset(read_data, sizeof(read_data));
727   s.next_read_length(10);
728   ec = boost::system::error_code();
729   length = 0;
730   called = false;
731   sb1.consume(sb1.size());
732   boost::asio::async_read_until(s, sb1, 'Z',
733       bindns::bind(async_read_handler, _1, &ec,
734         _2, &length, &called));
735   ioc.restart();
736   ioc.run();
737   BOOST_ASIO_CHECK(called);
738   BOOST_ASIO_CHECK(!ec);
739   BOOST_ASIO_CHECK(length == 26);
740 
741   s.reset(read_data, sizeof(read_data));
742   ec = boost::system::error_code();
743   length = 0;
744   called = false;
745   sb2.consume(sb2.size());
746   boost::asio::async_read_until(s, sb2, 'Z',
747       bindns::bind(async_read_handler, _1, &ec,
748         _2, &length, &called));
749   ioc.restart();
750   ioc.run();
751   BOOST_ASIO_CHECK(called);
752   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
753   BOOST_ASIO_CHECK(length == 0);
754 
755   s.reset(read_data, sizeof(read_data));
756   s.next_read_length(1);
757   ec = boost::system::error_code();
758   length = 0;
759   called = false;
760   sb2.consume(sb2.size());
761   boost::asio::async_read_until(s, sb2, 'Z',
762       bindns::bind(async_read_handler, _1, &ec,
763         _2, &length, &called));
764   ioc.restart();
765   ioc.run();
766   BOOST_ASIO_CHECK(called);
767   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
768   BOOST_ASIO_CHECK(length == 0);
769 
770   s.reset(read_data, sizeof(read_data));
771   s.next_read_length(10);
772   ec = boost::system::error_code();
773   length = 0;
774   called = false;
775   sb2.consume(sb2.size());
776   boost::asio::async_read_until(s, sb2, 'Z',
777       bindns::bind(async_read_handler, _1, &ec,
778         _2, &length, &called));
779   ioc.restart();
780   ioc.run();
781   BOOST_ASIO_CHECK(called);
782   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
783   BOOST_ASIO_CHECK(length == 0);
784 
785   s.reset(read_data, sizeof(read_data));
786   ec = boost::system::error_code();
787   length = 0;
788   called = false;
789   sb2.consume(sb2.size());
790   boost::asio::async_read_until(s, sb2, 'Y',
791       bindns::bind(async_read_handler, _1, &ec,
792         _2, &length, &called));
793   ioc.restart();
794   ioc.run();
795   BOOST_ASIO_CHECK(called);
796   BOOST_ASIO_CHECK(!ec);
797   BOOST_ASIO_CHECK(length == 25);
798 
799   s.reset(read_data, sizeof(read_data));
800   s.next_read_length(1);
801   ec = boost::system::error_code();
802   length = 0;
803   called = false;
804   sb2.consume(sb2.size());
805   boost::asio::async_read_until(s, sb2, 'Y',
806       bindns::bind(async_read_handler, _1, &ec,
807         _2, &length, &called));
808   ioc.restart();
809   ioc.run();
810   BOOST_ASIO_CHECK(called);
811   BOOST_ASIO_CHECK(!ec);
812   BOOST_ASIO_CHECK(length == 25);
813 
814   s.reset(read_data, sizeof(read_data));
815   s.next_read_length(10);
816   ec = boost::system::error_code();
817   length = 0;
818   called = false;
819   sb2.consume(sb2.size());
820   boost::asio::async_read_until(s, sb2, 'Y',
821       bindns::bind(async_read_handler, _1, &ec,
822         _2, &length, &called));
823   ioc.restart();
824   ioc.run();
825   BOOST_ASIO_CHECK(called);
826   BOOST_ASIO_CHECK(!ec);
827   BOOST_ASIO_CHECK(length == 25);
828 
829   s.reset(read_data, sizeof(read_data));
830   sb2.consume(sb2.size());
831   int i = boost::asio::async_read_until(s, sb2, 'Y',
832       archetypes::lazy_handler());
833   BOOST_ASIO_CHECK(i == 42);
834   ioc.restart();
835   ioc.run();
836 }
837 
test_streambuf_async_read_until_char()838 void test_streambuf_async_read_until_char()
839 {
840 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
841 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
842   namespace bindns = boost;
843 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
844   namespace bindns = std;
845 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
846   using bindns::placeholders::_1;
847   using bindns::placeholders::_2;
848 
849   boost::asio::io_context ioc;
850   test_stream s(ioc);
851   boost::asio::streambuf sb1;
852   boost::asio::streambuf sb2(25);
853   boost::system::error_code ec;
854   std::size_t length;
855   bool called;
856 
857   s.reset(read_data, sizeof(read_data));
858   ec = boost::system::error_code();
859   length = 0;
860   called = false;
861   sb1.consume(sb1.size());
862   boost::asio::async_read_until(s, sb1, 'Z',
863       bindns::bind(async_read_handler, _1, &ec,
864         _2, &length, &called));
865   ioc.restart();
866   ioc.run();
867   BOOST_ASIO_CHECK(called);
868   BOOST_ASIO_CHECK(!ec);
869   BOOST_ASIO_CHECK(length == 26);
870 
871   s.reset(read_data, sizeof(read_data));
872   s.next_read_length(1);
873   ec = boost::system::error_code();
874   length = 0;
875   called = false;
876   sb1.consume(sb1.size());
877   boost::asio::async_read_until(s, sb1, 'Z',
878       bindns::bind(async_read_handler, _1, &ec,
879         _2, &length, &called));
880   ioc.restart();
881   ioc.run();
882   BOOST_ASIO_CHECK(called);
883   BOOST_ASIO_CHECK(!ec);
884   BOOST_ASIO_CHECK(length == 26);
885 
886   s.reset(read_data, sizeof(read_data));
887   s.next_read_length(10);
888   ec = boost::system::error_code();
889   length = 0;
890   called = false;
891   sb1.consume(sb1.size());
892   boost::asio::async_read_until(s, sb1, 'Z',
893       bindns::bind(async_read_handler, _1, &ec,
894         _2, &length, &called));
895   ioc.restart();
896   ioc.run();
897   BOOST_ASIO_CHECK(called);
898   BOOST_ASIO_CHECK(!ec);
899   BOOST_ASIO_CHECK(length == 26);
900 
901   s.reset(read_data, sizeof(read_data));
902   ec = boost::system::error_code();
903   length = 0;
904   called = false;
905   sb2.consume(sb2.size());
906   boost::asio::async_read_until(s, sb2, 'Z',
907       bindns::bind(async_read_handler, _1, &ec,
908         _2, &length, &called));
909   ioc.restart();
910   ioc.run();
911   BOOST_ASIO_CHECK(called);
912   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
913   BOOST_ASIO_CHECK(length == 0);
914 
915   s.reset(read_data, sizeof(read_data));
916   s.next_read_length(1);
917   ec = boost::system::error_code();
918   length = 0;
919   called = false;
920   sb2.consume(sb2.size());
921   boost::asio::async_read_until(s, sb2, 'Z',
922       bindns::bind(async_read_handler, _1, &ec,
923         _2, &length, &called));
924   ioc.restart();
925   ioc.run();
926   BOOST_ASIO_CHECK(called);
927   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
928   BOOST_ASIO_CHECK(length == 0);
929 
930   s.reset(read_data, sizeof(read_data));
931   s.next_read_length(10);
932   ec = boost::system::error_code();
933   length = 0;
934   called = false;
935   sb2.consume(sb2.size());
936   boost::asio::async_read_until(s, sb2, 'Z',
937       bindns::bind(async_read_handler, _1, &ec,
938         _2, &length, &called));
939   ioc.restart();
940   ioc.run();
941   BOOST_ASIO_CHECK(called);
942   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
943   BOOST_ASIO_CHECK(length == 0);
944 
945   s.reset(read_data, sizeof(read_data));
946   ec = boost::system::error_code();
947   length = 0;
948   called = false;
949   sb2.consume(sb2.size());
950   boost::asio::async_read_until(s, sb2, 'Y',
951       bindns::bind(async_read_handler, _1, &ec,
952         _2, &length, &called));
953   ioc.restart();
954   ioc.run();
955   BOOST_ASIO_CHECK(called);
956   BOOST_ASIO_CHECK(!ec);
957   BOOST_ASIO_CHECK(length == 25);
958 
959   s.reset(read_data, sizeof(read_data));
960   s.next_read_length(1);
961   ec = boost::system::error_code();
962   length = 0;
963   called = false;
964   sb2.consume(sb2.size());
965   boost::asio::async_read_until(s, sb2, 'Y',
966       bindns::bind(async_read_handler, _1, &ec,
967         _2, &length, &called));
968   ioc.restart();
969   ioc.run();
970   BOOST_ASIO_CHECK(called);
971   BOOST_ASIO_CHECK(!ec);
972   BOOST_ASIO_CHECK(length == 25);
973 
974   s.reset(read_data, sizeof(read_data));
975   s.next_read_length(10);
976   ec = boost::system::error_code();
977   length = 0;
978   called = false;
979   sb2.consume(sb2.size());
980   boost::asio::async_read_until(s, sb2, 'Y',
981       bindns::bind(async_read_handler, _1, &ec,
982         _2, &length, &called));
983   ioc.restart();
984   ioc.run();
985   BOOST_ASIO_CHECK(called);
986   BOOST_ASIO_CHECK(!ec);
987   BOOST_ASIO_CHECK(length == 25);
988 
989   s.reset(read_data, sizeof(read_data));
990   sb2.consume(sb2.size());
991   int i = boost::asio::async_read_until(s, sb2, 'Y',
992       archetypes::lazy_handler());
993   BOOST_ASIO_CHECK(i == 42);
994   ioc.restart();
995   ioc.run();
996 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
997 }
998 
test_dynamic_string_async_read_until_string()999 void test_dynamic_string_async_read_until_string()
1000 {
1001 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
1002   namespace bindns = boost;
1003 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
1004   namespace bindns = std;
1005 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
1006   using bindns::placeholders::_1;
1007   using bindns::placeholders::_2;
1008 
1009   boost::asio::io_context ioc;
1010   test_stream s(ioc);
1011   std::string data1, data2;
1012   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
1013     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
1014   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
1015     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
1016   boost::system::error_code ec;
1017   std::size_t length;
1018   bool called;
1019 
1020   s.reset(read_data, sizeof(read_data));
1021   ec = boost::system::error_code();
1022   length = 0;
1023   called = false;
1024   sb1.consume(sb1.size());
1025   boost::asio::async_read_until(s, sb1, "XYZ",
1026       bindns::bind(async_read_handler, _1, &ec,
1027         _2, &length, &called));
1028   ioc.restart();
1029   ioc.run();
1030   BOOST_ASIO_CHECK(called);
1031   BOOST_ASIO_CHECK(!ec);
1032   BOOST_ASIO_CHECK(length == 26);
1033 
1034   s.reset(read_data, sizeof(read_data));
1035   s.next_read_length(1);
1036   ec = boost::system::error_code();
1037   length = 0;
1038   called = false;
1039   sb1.consume(sb1.size());
1040   boost::asio::async_read_until(s, sb1, "XYZ",
1041       bindns::bind(async_read_handler, _1, &ec,
1042         _2, &length, &called));
1043   ioc.restart();
1044   ioc.run();
1045   BOOST_ASIO_CHECK(called);
1046   BOOST_ASIO_CHECK(!ec);
1047   BOOST_ASIO_CHECK(length == 26);
1048 
1049   s.reset(read_data, sizeof(read_data));
1050   s.next_read_length(10);
1051   ec = boost::system::error_code();
1052   length = 0;
1053   called = false;
1054   sb1.consume(sb1.size());
1055   boost::asio::async_read_until(s, sb1, "XYZ",
1056       bindns::bind(async_read_handler, _1, &ec,
1057         _2, &length, &called));
1058   ioc.restart();
1059   ioc.run();
1060   BOOST_ASIO_CHECK(called);
1061   BOOST_ASIO_CHECK(!ec);
1062   BOOST_ASIO_CHECK(length == 26);
1063 
1064   s.reset(read_data, sizeof(read_data));
1065   ec = boost::system::error_code();
1066   length = 0;
1067   called = false;
1068   sb2.consume(sb2.size());
1069   boost::asio::async_read_until(s, sb2, "XYZ",
1070       bindns::bind(async_read_handler, _1, &ec,
1071         _2, &length, &called));
1072   ioc.restart();
1073   ioc.run();
1074   BOOST_ASIO_CHECK(called);
1075   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1076   BOOST_ASIO_CHECK(length == 0);
1077 
1078   s.reset(read_data, sizeof(read_data));
1079   s.next_read_length(1);
1080   ec = boost::system::error_code();
1081   length = 0;
1082   called = false;
1083   sb2.consume(sb2.size());
1084   boost::asio::async_read_until(s, sb2, "XYZ",
1085       bindns::bind(async_read_handler, _1, &ec,
1086         _2, &length, &called));
1087   ioc.restart();
1088   ioc.run();
1089   BOOST_ASIO_CHECK(called);
1090   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1091   BOOST_ASIO_CHECK(length == 0);
1092 
1093   s.reset(read_data, sizeof(read_data));
1094   s.next_read_length(10);
1095   ec = boost::system::error_code();
1096   length = 0;
1097   called = false;
1098   sb2.consume(sb2.size());
1099   boost::asio::async_read_until(s, sb2, "XYZ",
1100       bindns::bind(async_read_handler, _1, &ec,
1101         _2, &length, &called));
1102   ioc.restart();
1103   ioc.run();
1104   BOOST_ASIO_CHECK(called);
1105   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1106   BOOST_ASIO_CHECK(length == 0);
1107 
1108   s.reset(read_data, sizeof(read_data));
1109   ec = boost::system::error_code();
1110   length = 0;
1111   called = false;
1112   sb2.consume(sb2.size());
1113   boost::asio::async_read_until(s, sb2, "WXY",
1114       bindns::bind(async_read_handler, _1, &ec,
1115         _2, &length, &called));
1116   ioc.restart();
1117   ioc.run();
1118   BOOST_ASIO_CHECK(called);
1119   BOOST_ASIO_CHECK(!ec);
1120   BOOST_ASIO_CHECK(length == 25);
1121 
1122   s.reset(read_data, sizeof(read_data));
1123   s.next_read_length(1);
1124   ec = boost::system::error_code();
1125   length = 0;
1126   called = false;
1127   sb2.consume(sb2.size());
1128   boost::asio::async_read_until(s, sb2, "WXY",
1129       bindns::bind(async_read_handler, _1, &ec,
1130         _2, &length, &called));
1131   ioc.restart();
1132   ioc.run();
1133   BOOST_ASIO_CHECK(called);
1134   BOOST_ASIO_CHECK(!ec);
1135   BOOST_ASIO_CHECK(length == 25);
1136 
1137   s.reset(read_data, sizeof(read_data));
1138   s.next_read_length(10);
1139   ec = boost::system::error_code();
1140   length = 0;
1141   called = false;
1142   sb2.consume(sb2.size());
1143   boost::asio::async_read_until(s, sb2, "WXY",
1144       bindns::bind(async_read_handler, _1, &ec,
1145         _2, &length, &called));
1146   ioc.restart();
1147   ioc.run();
1148   BOOST_ASIO_CHECK(called);
1149   BOOST_ASIO_CHECK(!ec);
1150   BOOST_ASIO_CHECK(length == 25);
1151 
1152   s.reset(read_data, sizeof(read_data));
1153   sb2.consume(sb2.size());
1154   int i = boost::asio::async_read_until(s, sb2, "WXY",
1155       archetypes::lazy_handler());
1156   BOOST_ASIO_CHECK(i == 42);
1157   ioc.restart();
1158   ioc.run();
1159 }
1160 
test_streambuf_async_read_until_string()1161 void test_streambuf_async_read_until_string()
1162 {
1163 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1164 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
1165   namespace bindns = boost;
1166 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
1167   namespace bindns = std;
1168 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
1169   using bindns::placeholders::_1;
1170   using bindns::placeholders::_2;
1171 
1172   boost::asio::io_context ioc;
1173   test_stream s(ioc);
1174   boost::asio::streambuf sb1;
1175   boost::asio::streambuf sb2(25);
1176   boost::system::error_code ec;
1177   std::size_t length;
1178   bool called;
1179 
1180   s.reset(read_data, sizeof(read_data));
1181   ec = boost::system::error_code();
1182   length = 0;
1183   called = false;
1184   sb1.consume(sb1.size());
1185   boost::asio::async_read_until(s, sb1, "XYZ",
1186       bindns::bind(async_read_handler, _1, &ec,
1187         _2, &length, &called));
1188   ioc.restart();
1189   ioc.run();
1190   BOOST_ASIO_CHECK(called);
1191   BOOST_ASIO_CHECK(!ec);
1192   BOOST_ASIO_CHECK(length == 26);
1193 
1194   s.reset(read_data, sizeof(read_data));
1195   s.next_read_length(1);
1196   ec = boost::system::error_code();
1197   length = 0;
1198   called = false;
1199   sb1.consume(sb1.size());
1200   boost::asio::async_read_until(s, sb1, "XYZ",
1201       bindns::bind(async_read_handler, _1, &ec,
1202         _2, &length, &called));
1203   ioc.restart();
1204   ioc.run();
1205   BOOST_ASIO_CHECK(called);
1206   BOOST_ASIO_CHECK(!ec);
1207   BOOST_ASIO_CHECK(length == 26);
1208 
1209   s.reset(read_data, sizeof(read_data));
1210   s.next_read_length(10);
1211   ec = boost::system::error_code();
1212   length = 0;
1213   called = false;
1214   sb1.consume(sb1.size());
1215   boost::asio::async_read_until(s, sb1, "XYZ",
1216       bindns::bind(async_read_handler, _1, &ec,
1217         _2, &length, &called));
1218   ioc.restart();
1219   ioc.run();
1220   BOOST_ASIO_CHECK(called);
1221   BOOST_ASIO_CHECK(!ec);
1222   BOOST_ASIO_CHECK(length == 26);
1223 
1224   s.reset(read_data, sizeof(read_data));
1225   ec = boost::system::error_code();
1226   length = 0;
1227   called = false;
1228   sb2.consume(sb2.size());
1229   boost::asio::async_read_until(s, sb2, "XYZ",
1230       bindns::bind(async_read_handler, _1, &ec,
1231         _2, &length, &called));
1232   ioc.restart();
1233   ioc.run();
1234   BOOST_ASIO_CHECK(called);
1235   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1236   BOOST_ASIO_CHECK(length == 0);
1237 
1238   s.reset(read_data, sizeof(read_data));
1239   s.next_read_length(1);
1240   ec = boost::system::error_code();
1241   length = 0;
1242   called = false;
1243   sb2.consume(sb2.size());
1244   boost::asio::async_read_until(s, sb2, "XYZ",
1245       bindns::bind(async_read_handler, _1, &ec,
1246         _2, &length, &called));
1247   ioc.restart();
1248   ioc.run();
1249   BOOST_ASIO_CHECK(called);
1250   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1251   BOOST_ASIO_CHECK(length == 0);
1252 
1253   s.reset(read_data, sizeof(read_data));
1254   s.next_read_length(10);
1255   ec = boost::system::error_code();
1256   length = 0;
1257   called = false;
1258   sb2.consume(sb2.size());
1259   boost::asio::async_read_until(s, sb2, "XYZ",
1260       bindns::bind(async_read_handler, _1, &ec,
1261         _2, &length, &called));
1262   ioc.restart();
1263   ioc.run();
1264   BOOST_ASIO_CHECK(called);
1265   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1266   BOOST_ASIO_CHECK(length == 0);
1267 
1268   s.reset(read_data, sizeof(read_data));
1269   ec = boost::system::error_code();
1270   length = 0;
1271   called = false;
1272   sb2.consume(sb2.size());
1273   boost::asio::async_read_until(s, sb2, "WXY",
1274       bindns::bind(async_read_handler, _1, &ec,
1275         _2, &length, &called));
1276   ioc.restart();
1277   ioc.run();
1278   BOOST_ASIO_CHECK(called);
1279   BOOST_ASIO_CHECK(!ec);
1280   BOOST_ASIO_CHECK(length == 25);
1281 
1282   s.reset(read_data, sizeof(read_data));
1283   s.next_read_length(1);
1284   ec = boost::system::error_code();
1285   length = 0;
1286   called = false;
1287   sb2.consume(sb2.size());
1288   boost::asio::async_read_until(s, sb2, "WXY",
1289       bindns::bind(async_read_handler, _1, &ec,
1290         _2, &length, &called));
1291   ioc.restart();
1292   ioc.run();
1293   BOOST_ASIO_CHECK(called);
1294   BOOST_ASIO_CHECK(!ec);
1295   BOOST_ASIO_CHECK(length == 25);
1296 
1297   s.reset(read_data, sizeof(read_data));
1298   s.next_read_length(10);
1299   ec = boost::system::error_code();
1300   length = 0;
1301   called = false;
1302   sb2.consume(sb2.size());
1303   boost::asio::async_read_until(s, sb2, "WXY",
1304       bindns::bind(async_read_handler, _1, &ec,
1305         _2, &length, &called));
1306   ioc.restart();
1307   ioc.run();
1308   BOOST_ASIO_CHECK(called);
1309   BOOST_ASIO_CHECK(!ec);
1310   BOOST_ASIO_CHECK(length == 25);
1311 
1312   s.reset(read_data, sizeof(read_data));
1313   sb2.consume(sb2.size());
1314   int i = boost::asio::async_read_until(s, sb2, "WXY",
1315       archetypes::lazy_handler());
1316   BOOST_ASIO_CHECK(i == 42);
1317   ioc.restart();
1318   ioc.run();
1319 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1320 }
1321 
test_dynamic_string_async_read_until_match_condition()1322 void test_dynamic_string_async_read_until_match_condition()
1323 {
1324 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
1325   namespace bindns = boost;
1326 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
1327   namespace bindns = std;
1328 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
1329   using bindns::placeholders::_1;
1330   using bindns::placeholders::_2;
1331 
1332   boost::asio::io_context ioc;
1333   test_stream s(ioc);
1334   std::string data1, data2;
1335   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
1336     std::string::allocator_type> sb1 = boost::asio::dynamic_buffer(data1);
1337   boost::asio::dynamic_string_buffer<char, std::string::traits_type,
1338     std::string::allocator_type> sb2 = boost::asio::dynamic_buffer(data2, 25);
1339   boost::system::error_code ec;
1340   std::size_t length;
1341   bool called;
1342 
1343   s.reset(read_data, sizeof(read_data));
1344   ec = boost::system::error_code();
1345   length = 0;
1346   called = false;
1347   sb1.consume(sb1.size());
1348   boost::asio::async_read_until(s, sb1, match_char('Z'),
1349       bindns::bind(async_read_handler, _1, &ec,
1350         _2, &length, &called));
1351   ioc.restart();
1352   ioc.run();
1353   BOOST_ASIO_CHECK(called);
1354   BOOST_ASIO_CHECK(!ec);
1355   BOOST_ASIO_CHECK(length == 26);
1356 
1357   s.reset(read_data, sizeof(read_data));
1358   s.next_read_length(1);
1359   ec = boost::system::error_code();
1360   length = 0;
1361   called = false;
1362   sb1.consume(sb1.size());
1363   boost::asio::async_read_until(s, sb1, match_char('Z'),
1364       bindns::bind(async_read_handler, _1, &ec,
1365         _2, &length, &called));
1366   ioc.restart();
1367   ioc.run();
1368   BOOST_ASIO_CHECK(called);
1369   BOOST_ASIO_CHECK(!ec);
1370   BOOST_ASIO_CHECK(length == 26);
1371 
1372   s.reset(read_data, sizeof(read_data));
1373   s.next_read_length(10);
1374   ec = boost::system::error_code();
1375   length = 0;
1376   called = false;
1377   sb1.consume(sb1.size());
1378   boost::asio::async_read_until(s, sb1, match_char('Z'),
1379       bindns::bind(async_read_handler, _1, &ec,
1380         _2, &length, &called));
1381   ioc.restart();
1382   ioc.run();
1383   BOOST_ASIO_CHECK(called);
1384   BOOST_ASIO_CHECK(!ec);
1385   BOOST_ASIO_CHECK(length == 26);
1386 
1387   s.reset(read_data, sizeof(read_data));
1388   ec = boost::system::error_code();
1389   length = 0;
1390   called = false;
1391   sb2.consume(sb2.size());
1392   boost::asio::async_read_until(s, sb2, match_char('Z'),
1393       bindns::bind(async_read_handler, _1, &ec,
1394         _2, &length, &called));
1395   ioc.restart();
1396   ioc.run();
1397   BOOST_ASIO_CHECK(called);
1398   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1399   BOOST_ASIO_CHECK(length == 0);
1400 
1401   s.reset(read_data, sizeof(read_data));
1402   s.next_read_length(1);
1403   ec = boost::system::error_code();
1404   length = 0;
1405   called = false;
1406   sb2.consume(sb2.size());
1407   boost::asio::async_read_until(s, sb2, match_char('Z'),
1408       bindns::bind(async_read_handler, _1, &ec,
1409         _2, &length, &called));
1410   ioc.restart();
1411   ioc.run();
1412   BOOST_ASIO_CHECK(called);
1413   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1414   BOOST_ASIO_CHECK(length == 0);
1415 
1416   s.reset(read_data, sizeof(read_data));
1417   s.next_read_length(10);
1418   ec = boost::system::error_code();
1419   length = 0;
1420   called = false;
1421   sb2.consume(sb2.size());
1422   boost::asio::async_read_until(s, sb2, match_char('Z'),
1423       bindns::bind(async_read_handler, _1, &ec,
1424         _2, &length, &called));
1425   ioc.restart();
1426   ioc.run();
1427   BOOST_ASIO_CHECK(called);
1428   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1429   BOOST_ASIO_CHECK(length == 0);
1430 
1431   s.reset(read_data, sizeof(read_data));
1432   ec = boost::system::error_code();
1433   length = 0;
1434   called = false;
1435   sb2.consume(sb2.size());
1436   boost::asio::async_read_until(s, sb2, match_char('Y'),
1437       bindns::bind(async_read_handler, _1, &ec,
1438         _2, &length, &called));
1439   ioc.restart();
1440   ioc.run();
1441   BOOST_ASIO_CHECK(called);
1442   BOOST_ASIO_CHECK(!ec);
1443   BOOST_ASIO_CHECK(length == 25);
1444 
1445   s.reset(read_data, sizeof(read_data));
1446   s.next_read_length(1);
1447   ec = boost::system::error_code();
1448   length = 0;
1449   called = false;
1450   sb2.consume(sb2.size());
1451   boost::asio::async_read_until(s, sb2, match_char('Y'),
1452       bindns::bind(async_read_handler, _1, &ec,
1453         _2, &length, &called));
1454   ioc.restart();
1455   ioc.run();
1456   BOOST_ASIO_CHECK(called);
1457   BOOST_ASIO_CHECK(!ec);
1458   BOOST_ASIO_CHECK(length == 25);
1459 
1460   s.reset(read_data, sizeof(read_data));
1461   s.next_read_length(10);
1462   ec = boost::system::error_code();
1463   length = 0;
1464   called = false;
1465   sb2.consume(sb2.size());
1466   boost::asio::async_read_until(s, sb2, match_char('Y'),
1467       bindns::bind(async_read_handler, _1, &ec,
1468         _2, &length, &called));
1469   ioc.restart();
1470   ioc.run();
1471   BOOST_ASIO_CHECK(called);
1472   BOOST_ASIO_CHECK(!ec);
1473   BOOST_ASIO_CHECK(length == 25);
1474 
1475   s.reset(read_data, sizeof(read_data));
1476   sb2.consume(sb2.size());
1477   int i = boost::asio::async_read_until(s, sb2, match_char('Y'),
1478       archetypes::lazy_handler());
1479   BOOST_ASIO_CHECK(i == 42);
1480   ioc.restart();
1481   ioc.run();
1482 }
1483 
test_streambuf_async_read_until_match_condition()1484 void test_streambuf_async_read_until_match_condition()
1485 {
1486 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1487 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
1488   namespace bindns = boost;
1489 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
1490   namespace bindns = std;
1491 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
1492   using bindns::placeholders::_1;
1493   using bindns::placeholders::_2;
1494 
1495   boost::asio::io_context ioc;
1496   test_stream s(ioc);
1497   boost::asio::streambuf sb1;
1498   boost::asio::streambuf sb2(25);
1499   boost::system::error_code ec;
1500   std::size_t length;
1501   bool called;
1502 
1503   s.reset(read_data, sizeof(read_data));
1504   ec = boost::system::error_code();
1505   length = 0;
1506   called = false;
1507   sb1.consume(sb1.size());
1508   boost::asio::async_read_until(s, sb1, match_char('Z'),
1509       bindns::bind(async_read_handler, _1, &ec,
1510         _2, &length, &called));
1511   ioc.restart();
1512   ioc.run();
1513   BOOST_ASIO_CHECK(called);
1514   BOOST_ASIO_CHECK(!ec);
1515   BOOST_ASIO_CHECK(length == 26);
1516 
1517   s.reset(read_data, sizeof(read_data));
1518   s.next_read_length(1);
1519   ec = boost::system::error_code();
1520   length = 0;
1521   called = false;
1522   sb1.consume(sb1.size());
1523   boost::asio::async_read_until(s, sb1, match_char('Z'),
1524       bindns::bind(async_read_handler, _1, &ec,
1525         _2, &length, &called));
1526   ioc.restart();
1527   ioc.run();
1528   BOOST_ASIO_CHECK(called);
1529   BOOST_ASIO_CHECK(!ec);
1530   BOOST_ASIO_CHECK(length == 26);
1531 
1532   s.reset(read_data, sizeof(read_data));
1533   s.next_read_length(10);
1534   ec = boost::system::error_code();
1535   length = 0;
1536   called = false;
1537   sb1.consume(sb1.size());
1538   boost::asio::async_read_until(s, sb1, match_char('Z'),
1539       bindns::bind(async_read_handler, _1, &ec,
1540         _2, &length, &called));
1541   ioc.restart();
1542   ioc.run();
1543   BOOST_ASIO_CHECK(called);
1544   BOOST_ASIO_CHECK(!ec);
1545   BOOST_ASIO_CHECK(length == 26);
1546 
1547   s.reset(read_data, sizeof(read_data));
1548   ec = boost::system::error_code();
1549   length = 0;
1550   called = false;
1551   sb2.consume(sb2.size());
1552   boost::asio::async_read_until(s, sb2, match_char('Z'),
1553       bindns::bind(async_read_handler, _1, &ec,
1554         _2, &length, &called));
1555   ioc.restart();
1556   ioc.run();
1557   BOOST_ASIO_CHECK(called);
1558   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1559   BOOST_ASIO_CHECK(length == 0);
1560 
1561   s.reset(read_data, sizeof(read_data));
1562   s.next_read_length(1);
1563   ec = boost::system::error_code();
1564   length = 0;
1565   called = false;
1566   sb2.consume(sb2.size());
1567   boost::asio::async_read_until(s, sb2, match_char('Z'),
1568       bindns::bind(async_read_handler, _1, &ec,
1569         _2, &length, &called));
1570   ioc.restart();
1571   ioc.run();
1572   BOOST_ASIO_CHECK(called);
1573   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1574   BOOST_ASIO_CHECK(length == 0);
1575 
1576   s.reset(read_data, sizeof(read_data));
1577   s.next_read_length(10);
1578   ec = boost::system::error_code();
1579   length = 0;
1580   called = false;
1581   sb2.consume(sb2.size());
1582   boost::asio::async_read_until(s, sb2, match_char('Z'),
1583       bindns::bind(async_read_handler, _1, &ec,
1584         _2, &length, &called));
1585   ioc.restart();
1586   ioc.run();
1587   BOOST_ASIO_CHECK(called);
1588   BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
1589   BOOST_ASIO_CHECK(length == 0);
1590 
1591   s.reset(read_data, sizeof(read_data));
1592   ec = boost::system::error_code();
1593   length = 0;
1594   called = false;
1595   sb2.consume(sb2.size());
1596   boost::asio::async_read_until(s, sb2, match_char('Y'),
1597       bindns::bind(async_read_handler, _1, &ec,
1598         _2, &length, &called));
1599   ioc.restart();
1600   ioc.run();
1601   BOOST_ASIO_CHECK(called);
1602   BOOST_ASIO_CHECK(!ec);
1603   BOOST_ASIO_CHECK(length == 25);
1604 
1605   s.reset(read_data, sizeof(read_data));
1606   s.next_read_length(1);
1607   ec = boost::system::error_code();
1608   length = 0;
1609   called = false;
1610   sb2.consume(sb2.size());
1611   boost::asio::async_read_until(s, sb2, match_char('Y'),
1612       bindns::bind(async_read_handler, _1, &ec,
1613         _2, &length, &called));
1614   ioc.restart();
1615   ioc.run();
1616   BOOST_ASIO_CHECK(called);
1617   BOOST_ASIO_CHECK(!ec);
1618   BOOST_ASIO_CHECK(length == 25);
1619 
1620   s.reset(read_data, sizeof(read_data));
1621   s.next_read_length(10);
1622   ec = boost::system::error_code();
1623   length = 0;
1624   called = false;
1625   sb2.consume(sb2.size());
1626   boost::asio::async_read_until(s, sb2, match_char('Y'),
1627       bindns::bind(async_read_handler, _1, &ec,
1628         _2, &length, &called));
1629   ioc.restart();
1630   ioc.run();
1631   BOOST_ASIO_CHECK(called);
1632   BOOST_ASIO_CHECK(!ec);
1633   BOOST_ASIO_CHECK(length == 25);
1634 
1635   s.reset(read_data, sizeof(read_data));
1636   sb2.consume(sb2.size());
1637   int i = boost::asio::async_read_until(s, sb2, match_char('Y'),
1638       archetypes::lazy_handler());
1639   BOOST_ASIO_CHECK(i == 42);
1640   ioc.restart();
1641   ioc.run();
1642 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
1643 }
1644 
1645 BOOST_ASIO_TEST_SUITE
1646 (
1647   "read_until",
1648   BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_char)
1649   BOOST_ASIO_TEST_CASE(test_streambuf_read_until_char)
1650   BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_string)
1651   BOOST_ASIO_TEST_CASE(test_streambuf_read_until_string)
1652   BOOST_ASIO_TEST_CASE(test_dynamic_string_read_until_match_condition)
1653   BOOST_ASIO_TEST_CASE(test_streambuf_read_until_match_condition)
1654   BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_char)
1655   BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_char)
1656   BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_string)
1657   BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_string)
1658   BOOST_ASIO_TEST_CASE(test_dynamic_string_async_read_until_match_condition)
1659   BOOST_ASIO_TEST_CASE(test_streambuf_async_read_until_match_condition)
1660 )
1661