• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // impl/read.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_HPP
12 #define BOOST_ASIO_IMPL_READ_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 <boost/asio/associated_allocator.hpp>
20 #include <boost/asio/associated_executor.hpp>
21 #include <boost/asio/buffer.hpp>
22 #include <boost/asio/completion_condition.hpp>
23 #include <boost/asio/detail/array_fwd.hpp>
24 #include <boost/asio/detail/base_from_completion_cond.hpp>
25 #include <boost/asio/detail/bind_handler.hpp>
26 #include <boost/asio/detail/consuming_buffers.hpp>
27 #include <boost/asio/detail/dependent_type.hpp>
28 #include <boost/asio/detail/handler_alloc_helpers.hpp>
29 #include <boost/asio/detail/handler_cont_helpers.hpp>
30 #include <boost/asio/detail/handler_invoke_helpers.hpp>
31 #include <boost/asio/detail/handler_tracking.hpp>
32 #include <boost/asio/detail/handler_type_requirements.hpp>
33 #include <boost/asio/detail/non_const_lvalue.hpp>
34 #include <boost/asio/detail/throw_error.hpp>
35 #include <boost/asio/error.hpp>
36 
37 #include <boost/asio/detail/push_options.hpp>
38 
39 namespace boost {
40 namespace asio {
41 
42 namespace detail
43 {
44   template <typename SyncReadStream, typename MutableBufferSequence,
45       typename MutableBufferIterator, typename CompletionCondition>
read_buffer_sequence(SyncReadStream & s,const MutableBufferSequence & buffers,const MutableBufferIterator &,CompletionCondition completion_condition,boost::system::error_code & ec)46   std::size_t read_buffer_sequence(SyncReadStream& s,
47       const MutableBufferSequence& buffers, const MutableBufferIterator&,
48       CompletionCondition completion_condition, boost::system::error_code& ec)
49   {
50     ec = boost::system::error_code();
51     boost::asio::detail::consuming_buffers<mutable_buffer,
52         MutableBufferSequence, MutableBufferIterator> tmp(buffers);
53     while (!tmp.empty())
54     {
55       if (std::size_t max_size = detail::adapt_completion_condition_result(
56             completion_condition(ec, tmp.total_consumed())))
57         tmp.consume(s.read_some(tmp.prepare(max_size), ec));
58       else
59         break;
60     }
61     return tmp.total_consumed();
62   }
63 } // namespace detail
64 
65 template <typename SyncReadStream, typename MutableBufferSequence,
66     typename CompletionCondition>
read(SyncReadStream & s,const MutableBufferSequence & buffers,CompletionCondition completion_condition,boost::system::error_code & ec,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)67 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
68     CompletionCondition completion_condition, boost::system::error_code& ec,
69     typename constraint<
70       is_mutable_buffer_sequence<MutableBufferSequence>::value
71     >::type)
72 {
73   return detail::read_buffer_sequence(s, buffers,
74       boost::asio::buffer_sequence_begin(buffers),
75       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
76 }
77 
78 template <typename SyncReadStream, typename MutableBufferSequence>
read(SyncReadStream & s,const MutableBufferSequence & buffers,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)79 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
80     typename constraint<
81       is_mutable_buffer_sequence<MutableBufferSequence>::value
82     >::type)
83 {
84   boost::system::error_code ec;
85   std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
86   boost::asio::detail::throw_error(ec, "read");
87   return bytes_transferred;
88 }
89 
90 template <typename SyncReadStream, typename MutableBufferSequence>
read(SyncReadStream & s,const MutableBufferSequence & buffers,boost::system::error_code & ec,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)91 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
92     boost::system::error_code& ec,
93     typename constraint<
94       is_mutable_buffer_sequence<MutableBufferSequence>::value
95     >::type)
96 {
97   return read(s, buffers, transfer_all(), ec);
98 }
99 
100 template <typename SyncReadStream, typename MutableBufferSequence,
101     typename CompletionCondition>
read(SyncReadStream & s,const MutableBufferSequence & buffers,CompletionCondition completion_condition,typename constraint<is_mutable_buffer_sequence<MutableBufferSequence>::value>::type)102 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
103     CompletionCondition completion_condition,
104     typename constraint<
105       is_mutable_buffer_sequence<MutableBufferSequence>::value
106     >::type)
107 {
108   boost::system::error_code ec;
109   std::size_t bytes_transferred = read(s, buffers,
110       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
111   boost::asio::detail::throw_error(ec, "read");
112   return bytes_transferred;
113 }
114 
115 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
116 
117 template <typename SyncReadStream, typename DynamicBuffer_v1,
118     typename CompletionCondition>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,CompletionCondition completion_condition,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)119 std::size_t read(SyncReadStream& s,
120     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
121     CompletionCondition completion_condition, boost::system::error_code& ec,
122     typename constraint<
123       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
124     >::type,
125     typename constraint<
126       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
127     >::type)
128 {
129   typename decay<DynamicBuffer_v1>::type b(
130       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
131 
132   ec = boost::system::error_code();
133   std::size_t total_transferred = 0;
134   std::size_t max_size = detail::adapt_completion_condition_result(
135         completion_condition(ec, total_transferred));
136   std::size_t bytes_available = std::min<std::size_t>(
137         std::max<std::size_t>(512, b.capacity() - b.size()),
138         std::min<std::size_t>(max_size, b.max_size() - b.size()));
139   while (bytes_available > 0)
140   {
141     std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
142     b.commit(bytes_transferred);
143     total_transferred += bytes_transferred;
144     max_size = detail::adapt_completion_condition_result(
145           completion_condition(ec, total_transferred));
146     bytes_available = std::min<std::size_t>(
147           std::max<std::size_t>(512, b.capacity() - b.size()),
148           std::min<std::size_t>(max_size, b.max_size() - b.size()));
149   }
150   return total_transferred;
151 }
152 
153 template <typename SyncReadStream, typename DynamicBuffer_v1>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,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)154 inline std::size_t read(SyncReadStream& s,
155     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
156     typename constraint<
157       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
158     >::type,
159     typename constraint<
160       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
161     >::type)
162 {
163   boost::system::error_code ec;
164   std::size_t bytes_transferred = read(s,
165       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);
166   boost::asio::detail::throw_error(ec, "read");
167   return bytes_transferred;
168 }
169 
170 template <typename SyncReadStream, typename DynamicBuffer_v1>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,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)171 inline std::size_t read(SyncReadStream& s,
172     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
173     boost::system::error_code& ec,
174     typename constraint<
175       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
176     >::type,
177     typename constraint<
178       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
179     >::type)
180 {
181   return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
182       transfer_all(), ec);
183 }
184 
185 template <typename SyncReadStream, typename DynamicBuffer_v1,
186     typename CompletionCondition>
read(SyncReadStream & s,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,CompletionCondition completion_condition,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)187 inline std::size_t read(SyncReadStream& s,
188     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
189     CompletionCondition completion_condition,
190     typename constraint<
191       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
192     >::type,
193     typename constraint<
194       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
195     >::type)
196 {
197   boost::system::error_code ec;
198   std::size_t bytes_transferred = read(s,
199       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
200       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
201   boost::asio::detail::throw_error(ec, "read");
202   return bytes_transferred;
203 }
204 
205 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
206 #if !defined(BOOST_ASIO_NO_IOSTREAM)
207 
208 template <typename SyncReadStream, typename Allocator,
209     typename CompletionCondition>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,CompletionCondition completion_condition,boost::system::error_code & ec)210 inline std::size_t read(SyncReadStream& s,
211     boost::asio::basic_streambuf<Allocator>& b,
212     CompletionCondition completion_condition, boost::system::error_code& ec)
213 {
214   return read(s, basic_streambuf_ref<Allocator>(b),
215       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
216 }
217 
218 template <typename SyncReadStream, typename Allocator>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b)219 inline std::size_t read(SyncReadStream& s,
220     boost::asio::basic_streambuf<Allocator>& b)
221 {
222   return read(s, basic_streambuf_ref<Allocator>(b));
223 }
224 
225 template <typename SyncReadStream, typename Allocator>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,boost::system::error_code & ec)226 inline std::size_t read(SyncReadStream& s,
227     boost::asio::basic_streambuf<Allocator>& b,
228     boost::system::error_code& ec)
229 {
230   return read(s, basic_streambuf_ref<Allocator>(b), ec);
231 }
232 
233 template <typename SyncReadStream, typename Allocator,
234     typename CompletionCondition>
read(SyncReadStream & s,boost::asio::basic_streambuf<Allocator> & b,CompletionCondition completion_condition)235 inline std::size_t read(SyncReadStream& s,
236     boost::asio::basic_streambuf<Allocator>& b,
237     CompletionCondition completion_condition)
238 {
239   return read(s, basic_streambuf_ref<Allocator>(b),
240       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
241 }
242 
243 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
244 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
245 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
246 
247 template <typename SyncReadStream, typename DynamicBuffer_v2,
248     typename CompletionCondition>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,CompletionCondition completion_condition,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)249 std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
250     CompletionCondition completion_condition, boost::system::error_code& ec,
251     typename constraint<
252       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
253     >::type)
254 {
255   DynamicBuffer_v2& b = buffers;
256 
257   ec = boost::system::error_code();
258   std::size_t total_transferred = 0;
259   std::size_t max_size = detail::adapt_completion_condition_result(
260         completion_condition(ec, total_transferred));
261   std::size_t bytes_available = std::min<std::size_t>(
262         std::max<std::size_t>(512, b.capacity() - b.size()),
263         std::min<std::size_t>(max_size, b.max_size() - b.size()));
264   while (bytes_available > 0)
265   {
266     std::size_t pos = b.size();
267     b.grow(bytes_available);
268     std::size_t bytes_transferred = s.read_some(
269         b.data(pos, bytes_available), ec);
270     b.shrink(bytes_available - bytes_transferred);
271     total_transferred += bytes_transferred;
272     max_size = detail::adapt_completion_condition_result(
273           completion_condition(ec, total_transferred));
274     bytes_available = std::min<std::size_t>(
275           std::max<std::size_t>(512, b.capacity() - b.size()),
276           std::min<std::size_t>(max_size, b.max_size() - b.size()));
277   }
278   return total_transferred;
279 }
280 
281 template <typename SyncReadStream, typename DynamicBuffer_v2>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)282 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
283     typename constraint<
284       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
285     >::type)
286 {
287   boost::system::error_code ec;
288   std::size_t bytes_transferred = read(s,
289       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);
290   boost::asio::detail::throw_error(ec, "read");
291   return bytes_transferred;
292 }
293 
294 template <typename SyncReadStream, typename DynamicBuffer_v2>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,boost::system::error_code & ec,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)295 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
296     boost::system::error_code& ec,
297     typename constraint<
298       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
299     >::type)
300 {
301   return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
302       transfer_all(), ec);
303 }
304 
305 template <typename SyncReadStream, typename DynamicBuffer_v2,
306     typename CompletionCondition>
read(SyncReadStream & s,DynamicBuffer_v2 buffers,CompletionCondition completion_condition,typename constraint<is_dynamic_buffer_v2<DynamicBuffer_v2>::value>::type)307 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
308     CompletionCondition completion_condition,
309     typename constraint<
310       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
311     >::type)
312 {
313   boost::system::error_code ec;
314   std::size_t bytes_transferred = read(s,
315       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
316       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
317   boost::asio::detail::throw_error(ec, "read");
318   return bytes_transferred;
319 }
320 
321 namespace detail
322 {
323   template <typename AsyncReadStream, typename MutableBufferSequence,
324       typename MutableBufferIterator, typename CompletionCondition,
325       typename ReadHandler>
326   class read_op
327     : detail::base_from_completion_cond<CompletionCondition>
328   {
329   public:
read_op(AsyncReadStream & stream,const MutableBufferSequence & buffers,CompletionCondition & completion_condition,ReadHandler & handler)330     read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
331         CompletionCondition& completion_condition, ReadHandler& handler)
332       : detail::base_from_completion_cond<
333           CompletionCondition>(completion_condition),
334         stream_(stream),
335         buffers_(buffers),
336         start_(0),
337         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
338     {
339     }
340 
341 #if defined(BOOST_ASIO_HAS_MOVE)
read_op(const read_op & other)342     read_op(const read_op& other)
343       : detail::base_from_completion_cond<CompletionCondition>(other),
344         stream_(other.stream_),
345         buffers_(other.buffers_),
346         start_(other.start_),
347         handler_(other.handler_)
348     {
349     }
350 
read_op(read_op && other)351     read_op(read_op&& other)
352       : detail::base_from_completion_cond<CompletionCondition>(
353           BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
354             CompletionCondition>)(other)),
355         stream_(other.stream_),
356         buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
357         start_(other.start_),
358         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
359     {
360     }
361 #endif // defined(BOOST_ASIO_HAS_MOVE)
362 
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)363     void operator()(const boost::system::error_code& ec,
364         std::size_t bytes_transferred, int start = 0)
365     {
366       std::size_t max_size;
367       switch (start_ = start)
368       {
369         case 1:
370         max_size = this->check_for_completion(ec, buffers_.total_consumed());
371         do
372         {
373           {
374             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
375             stream_.async_read_some(buffers_.prepare(max_size),
376                 BOOST_ASIO_MOVE_CAST(read_op)(*this));
377           }
378           return; default:
379           buffers_.consume(bytes_transferred);
380           if ((!ec && bytes_transferred == 0) || buffers_.empty())
381             break;
382           max_size = this->check_for_completion(ec, buffers_.total_consumed());
383         } while (max_size > 0);
384 
385         handler_(ec, buffers_.total_consumed());
386       }
387     }
388 
389   //private:
390     typedef boost::asio::detail::consuming_buffers<mutable_buffer,
391         MutableBufferSequence, MutableBufferIterator> buffers_type;
392 
393     AsyncReadStream& stream_;
394     buffers_type buffers_;
395     int start_;
396     ReadHandler handler_;
397   };
398 
399   template <typename AsyncReadStream, typename MutableBufferSequence,
400       typename MutableBufferIterator, typename CompletionCondition,
401       typename ReadHandler>
402   inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)403   asio_handler_allocate(std::size_t size,
404       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
405         CompletionCondition, ReadHandler>* this_handler)
406   {
407 #if defined(BOOST_ASIO_NO_DEPRECATED)
408     boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
409     return asio_handler_allocate_is_no_longer_used();
410 #else // defined(BOOST_ASIO_NO_DEPRECATED)
411     return boost_asio_handler_alloc_helpers::allocate(
412         size, this_handler->handler_);
413 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
414   }
415 
416   template <typename AsyncReadStream, typename MutableBufferSequence,
417       typename MutableBufferIterator, typename CompletionCondition,
418       typename ReadHandler>
419   inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)420   asio_handler_deallocate(void* pointer, std::size_t size,
421       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
422         CompletionCondition, ReadHandler>* this_handler)
423   {
424     boost_asio_handler_alloc_helpers::deallocate(
425         pointer, size, this_handler->handler_);
426 #if defined(BOOST_ASIO_NO_DEPRECATED)
427     return asio_handler_deallocate_is_no_longer_used();
428 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
429   }
430 
431   template <typename AsyncReadStream, typename MutableBufferSequence,
432       typename MutableBufferIterator, typename CompletionCondition,
433       typename ReadHandler>
asio_handler_is_continuation(read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)434   inline bool asio_handler_is_continuation(
435       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
436         CompletionCondition, ReadHandler>* this_handler)
437   {
438     return this_handler->start_ == 0 ? true
439       : boost_asio_handler_cont_helpers::is_continuation(
440           this_handler->handler_);
441   }
442 
443   template <typename Function, typename AsyncReadStream,
444       typename MutableBufferSequence, typename MutableBufferIterator,
445       typename CompletionCondition, typename ReadHandler>
446   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)447   asio_handler_invoke(Function& function,
448       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
449         CompletionCondition, ReadHandler>* this_handler)
450   {
451     boost_asio_handler_invoke_helpers::invoke(
452         function, this_handler->handler_);
453 #if defined(BOOST_ASIO_NO_DEPRECATED)
454     return asio_handler_invoke_is_no_longer_used();
455 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
456   }
457 
458   template <typename Function, typename AsyncReadStream,
459       typename MutableBufferSequence, typename MutableBufferIterator,
460       typename CompletionCondition, typename ReadHandler>
461   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_op<AsyncReadStream,MutableBufferSequence,MutableBufferIterator,CompletionCondition,ReadHandler> * this_handler)462   asio_handler_invoke(const Function& function,
463       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
464         CompletionCondition, ReadHandler>* this_handler)
465   {
466     boost_asio_handler_invoke_helpers::invoke(
467         function, this_handler->handler_);
468 #if defined(BOOST_ASIO_NO_DEPRECATED)
469     return asio_handler_invoke_is_no_longer_used();
470 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
471   }
472 
473   template <typename AsyncReadStream, typename MutableBufferSequence,
474       typename MutableBufferIterator, typename CompletionCondition,
475       typename ReadHandler>
start_read_buffer_sequence_op(AsyncReadStream & stream,const MutableBufferSequence & buffers,const MutableBufferIterator &,CompletionCondition & completion_condition,ReadHandler & handler)476   inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
477       const MutableBufferSequence& buffers, const MutableBufferIterator&,
478       CompletionCondition& completion_condition, ReadHandler& handler)
479   {
480     detail::read_op<AsyncReadStream, MutableBufferSequence,
481       MutableBufferIterator, CompletionCondition, ReadHandler>(
482         stream, buffers, completion_condition, handler)(
483           boost::system::error_code(), 0, 1);
484   }
485 
486   template <typename AsyncReadStream>
487   class initiate_async_read_buffer_sequence
488   {
489   public:
490     typedef typename AsyncReadStream::executor_type executor_type;
491 
initiate_async_read_buffer_sequence(AsyncReadStream & stream)492     explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)
493       : stream_(stream)
494     {
495     }
496 
get_executor() const497     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
498     {
499       return stream_.get_executor();
500     }
501 
502     template <typename ReadHandler, typename MutableBufferSequence,
503         typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,const MutableBufferSequence & buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const504     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
505         const MutableBufferSequence& buffers,
506         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
507     {
508       // If you get an error on the following line it means that your handler
509       // does not meet the documented type requirements for a ReadHandler.
510       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
511 
512       non_const_lvalue<ReadHandler> handler2(handler);
513       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
514       start_read_buffer_sequence_op(stream_, buffers,
515           boost::asio::buffer_sequence_begin(buffers),
516           completion_cond2.value, handler2.value);
517     }
518 
519   private:
520     AsyncReadStream& stream_;
521   };
522 } // namespace detail
523 
524 #if !defined(GENERATING_DOCUMENTATION)
525 
526 template <typename AsyncReadStream, typename MutableBufferSequence,
527     typename MutableBufferIterator, typename CompletionCondition,
528     typename ReadHandler, typename Allocator>
529 struct associated_allocator<
530     detail::read_op<AsyncReadStream, MutableBufferSequence,
531       MutableBufferIterator, CompletionCondition, ReadHandler>,
532     Allocator>
533 {
534   typedef typename associated_allocator<ReadHandler, Allocator>::type type;
535 
getboost::asio::associated_allocator536   static type get(
537       const detail::read_op<AsyncReadStream, MutableBufferSequence,
538         MutableBufferIterator, CompletionCondition, ReadHandler>& h,
539       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
540   {
541     return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
542   }
543 };
544 
545 template <typename AsyncReadStream, typename MutableBufferSequence,
546     typename MutableBufferIterator, typename CompletionCondition,
547     typename ReadHandler, typename Executor>
548 struct associated_executor<
549     detail::read_op<AsyncReadStream, MutableBufferSequence,
550       MutableBufferIterator, CompletionCondition, ReadHandler>,
551     Executor>
552   : detail::associated_executor_forwarding_base<ReadHandler, Executor>
553 {
554   typedef typename associated_executor<ReadHandler, Executor>::type type;
555 
getboost::asio::associated_executor556   static type get(
557       const detail::read_op<AsyncReadStream, MutableBufferSequence,
558         MutableBufferIterator, CompletionCondition, ReadHandler>& h,
559       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
560   {
561     return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
562   }
563 };
564 
565 #endif // !defined(GENERATING_DOCUMENTATION)
566 
567 template <typename AsyncReadStream,
568     typename MutableBufferSequence, typename CompletionCondition,
569     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
570       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))571 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
572     void (boost::system::error_code, std::size_t))
573 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
574     CompletionCondition completion_condition,
575     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
576     typename constraint<
577       is_mutable_buffer_sequence<MutableBufferSequence>::value
578     >::type)
579 {
580   return async_initiate<ReadHandler,
581     void (boost::system::error_code, std::size_t)>(
582       detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,
583       buffers, BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
584 }
585 
586 template <typename AsyncReadStream, typename MutableBufferSequence,
587     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
588       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))589 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
590     void (boost::system::error_code, std::size_t))
591 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
592     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
593     typename constraint<
594       is_mutable_buffer_sequence<MutableBufferSequence>::value
595     >::type)
596 {
597   return async_initiate<ReadHandler,
598     void (boost::system::error_code, std::size_t)>(
599       detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),
600       handler, buffers, transfer_all());
601 }
602 
603 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
604 
605 namespace detail
606 {
607   template <typename AsyncReadStream, typename DynamicBuffer_v1,
608       typename CompletionCondition, typename ReadHandler>
609   class read_dynbuf_v1_op
610     : detail::base_from_completion_cond<CompletionCondition>
611   {
612   public:
613     template <typename BufferSequence>
read_dynbuf_v1_op(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,CompletionCondition & completion_condition,ReadHandler & handler)614     read_dynbuf_v1_op(AsyncReadStream& stream,
615         BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
616         CompletionCondition& completion_condition, ReadHandler& handler)
617       : detail::base_from_completion_cond<
618           CompletionCondition>(completion_condition),
619         stream_(stream),
620         buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
621         start_(0),
622         total_transferred_(0),
623         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
624     {
625     }
626 
627 #if defined(BOOST_ASIO_HAS_MOVE)
read_dynbuf_v1_op(const read_dynbuf_v1_op & other)628     read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
629       : detail::base_from_completion_cond<CompletionCondition>(other),
630         stream_(other.stream_),
631         buffers_(other.buffers_),
632         start_(other.start_),
633         total_transferred_(other.total_transferred_),
634         handler_(other.handler_)
635     {
636     }
637 
read_dynbuf_v1_op(read_dynbuf_v1_op && other)638     read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
639       : detail::base_from_completion_cond<CompletionCondition>(
640           BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
641             CompletionCondition>)(other)),
642         stream_(other.stream_),
643         buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
644         start_(other.start_),
645         total_transferred_(other.total_transferred_),
646         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
647     {
648     }
649 #endif // defined(BOOST_ASIO_HAS_MOVE)
650 
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)651     void operator()(const boost::system::error_code& ec,
652         std::size_t bytes_transferred, int start = 0)
653     {
654       std::size_t max_size, bytes_available;
655       switch (start_ = start)
656       {
657         case 1:
658         max_size = this->check_for_completion(ec, total_transferred_);
659         bytes_available = std::min<std::size_t>(
660               std::max<std::size_t>(512,
661                 buffers_.capacity() - buffers_.size()),
662               std::min<std::size_t>(max_size,
663                 buffers_.max_size() - buffers_.size()));
664         for (;;)
665         {
666           {
667             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
668             stream_.async_read_some(buffers_.prepare(bytes_available),
669                 BOOST_ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));
670           }
671           return; default:
672           total_transferred_ += bytes_transferred;
673           buffers_.commit(bytes_transferred);
674           max_size = this->check_for_completion(ec, total_transferred_);
675           bytes_available = std::min<std::size_t>(
676                 std::max<std::size_t>(512,
677                   buffers_.capacity() - buffers_.size()),
678                 std::min<std::size_t>(max_size,
679                   buffers_.max_size() - buffers_.size()));
680           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
681             break;
682         }
683 
684         handler_(ec, static_cast<const std::size_t&>(total_transferred_));
685       }
686     }
687 
688   //private:
689     AsyncReadStream& stream_;
690     DynamicBuffer_v1 buffers_;
691     int start_;
692     std::size_t total_transferred_;
693     ReadHandler handler_;
694   };
695 
696   template <typename AsyncReadStream, typename DynamicBuffer_v1,
697       typename CompletionCondition, typename ReadHandler>
698   inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)699   asio_handler_allocate(std::size_t size,
700       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
701         CompletionCondition, ReadHandler>* this_handler)
702   {
703 #if defined(BOOST_ASIO_NO_DEPRECATED)
704     boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
705     return asio_handler_allocate_is_no_longer_used();
706 #else // defined(BOOST_ASIO_NO_DEPRECATED)
707     return boost_asio_handler_alloc_helpers::allocate(
708         size, this_handler->handler_);
709 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
710   }
711 
712   template <typename AsyncReadStream, typename DynamicBuffer_v1,
713       typename CompletionCondition, typename ReadHandler>
714   inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)715   asio_handler_deallocate(void* pointer, std::size_t size,
716       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
717         CompletionCondition, ReadHandler>* this_handler)
718   {
719     boost_asio_handler_alloc_helpers::deallocate(
720         pointer, size, this_handler->handler_);
721 #if defined(BOOST_ASIO_NO_DEPRECATED)
722     return asio_handler_deallocate_is_no_longer_used();
723 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
724   }
725 
726   template <typename AsyncReadStream, typename DynamicBuffer_v1,
727       typename CompletionCondition, typename ReadHandler>
asio_handler_is_continuation(read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)728   inline bool asio_handler_is_continuation(
729       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
730         CompletionCondition, ReadHandler>* this_handler)
731   {
732     return this_handler->start_ == 0 ? true
733       : boost_asio_handler_cont_helpers::is_continuation(
734           this_handler->handler_);
735   }
736 
737   template <typename Function, typename AsyncReadStream,
738       typename DynamicBuffer_v1, typename CompletionCondition,
739       typename ReadHandler>
740   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)741   asio_handler_invoke(Function& function,
742       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
743         CompletionCondition, ReadHandler>* this_handler)
744   {
745     boost_asio_handler_invoke_helpers::invoke(
746         function, this_handler->handler_);
747 #if defined(BOOST_ASIO_NO_DEPRECATED)
748     return asio_handler_invoke_is_no_longer_used();
749 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
750   }
751 
752   template <typename Function, typename AsyncReadStream,
753       typename DynamicBuffer_v1, typename CompletionCondition,
754       typename ReadHandler>
755   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_dynbuf_v1_op<AsyncReadStream,DynamicBuffer_v1,CompletionCondition,ReadHandler> * this_handler)756   asio_handler_invoke(const Function& function,
757       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
758         CompletionCondition, ReadHandler>* this_handler)
759   {
760     boost_asio_handler_invoke_helpers::invoke(
761         function, this_handler->handler_);
762 #if defined(BOOST_ASIO_NO_DEPRECATED)
763     return asio_handler_invoke_is_no_longer_used();
764 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
765   }
766 
767   template <typename AsyncReadStream>
768   class initiate_async_read_dynbuf_v1
769   {
770   public:
771     typedef typename AsyncReadStream::executor_type executor_type;
772 
initiate_async_read_dynbuf_v1(AsyncReadStream & stream)773     explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
774       : stream_(stream)
775     {
776     }
777 
get_executor() const778     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
779     {
780       return stream_.get_executor();
781     }
782 
783     template <typename ReadHandler, typename DynamicBuffer_v1,
784         typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v1)buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const785     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
786         BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
787         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
788     {
789       // If you get an error on the following line it means that your handler
790       // does not meet the documented type requirements for a ReadHandler.
791       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
792 
793       non_const_lvalue<ReadHandler> handler2(handler);
794       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
795       read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,
796         CompletionCondition, typename decay<ReadHandler>::type>(
797           stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
798             completion_cond2.value, handler2.value)(
799               boost::system::error_code(), 0, 1);
800     }
801 
802   private:
803     AsyncReadStream& stream_;
804   };
805 } // namespace detail
806 
807 #if !defined(GENERATING_DOCUMENTATION)
808 
809 template <typename AsyncReadStream, typename DynamicBuffer_v1,
810     typename CompletionCondition, typename ReadHandler, typename Allocator>
811 struct associated_allocator<
812     detail::read_dynbuf_v1_op<AsyncReadStream,
813       DynamicBuffer_v1, CompletionCondition, ReadHandler>,
814     Allocator>
815 {
816   typedef typename associated_allocator<ReadHandler, Allocator>::type type;
817 
getboost::asio::associated_allocator818   static type get(
819       const detail::read_dynbuf_v1_op<AsyncReadStream,
820         DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
821       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
822   {
823     return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
824   }
825 };
826 
827 template <typename AsyncReadStream, typename DynamicBuffer_v1,
828     typename CompletionCondition, typename ReadHandler, typename Executor>
829 struct associated_executor<
830     detail::read_dynbuf_v1_op<AsyncReadStream,
831       DynamicBuffer_v1, CompletionCondition, ReadHandler>,
832     Executor>
833   : detail::associated_executor_forwarding_base<ReadHandler, Executor>
834 {
835   typedef typename associated_executor<ReadHandler, Executor>::type type;
836 
getboost::asio::associated_executor837   static type get(
838       const detail::read_dynbuf_v1_op<AsyncReadStream,
839         DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
840       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
841   {
842     return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
843   }
844 };
845 
846 #endif // !defined(GENERATING_DOCUMENTATION)
847 
848 template <typename AsyncReadStream, typename DynamicBuffer_v1,
849     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
850       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))851 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
852     void (boost::system::error_code, std::size_t))
853 async_read(AsyncReadStream& s,
854     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
855     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
856     typename constraint<
857       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
858     >::type,
859     typename constraint<
860       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
861     >::type)
862 {
863   return async_read(s,
864       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
865       transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
866 }
867 
868 template <typename AsyncReadStream,
869     typename DynamicBuffer_v1, typename CompletionCondition,
870     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
871       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))872 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
873     void (boost::system::error_code, std::size_t))
874 async_read(AsyncReadStream& s,
875     BOOST_ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
876     CompletionCondition completion_condition,
877     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
878     typename constraint<
879       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
880     >::type,
881     typename constraint<
882       !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
883     >::type)
884 {
885   return async_initiate<ReadHandler,
886     void (boost::system::error_code, std::size_t)>(
887       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
888       handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
889       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
890 }
891 
892 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
893 #if !defined(BOOST_ASIO_NO_IOSTREAM)
894 
895 template <typename AsyncReadStream, typename Allocator,
896     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
897       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))898 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
899     void (boost::system::error_code, std::size_t))
900 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
901     BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
902 {
903   return async_read(s, basic_streambuf_ref<Allocator>(b),
904       BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
905 }
906 
907 template <typename AsyncReadStream,
908     typename Allocator, typename CompletionCondition,
909     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
910       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))911 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
912     void (boost::system::error_code, std::size_t))
913 async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
914     CompletionCondition completion_condition,
915     BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
916 {
917   return async_read(s, basic_streambuf_ref<Allocator>(b),
918       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
919       BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
920 }
921 
922 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
923 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
924 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
925 
926 namespace detail
927 {
928   template <typename AsyncReadStream, typename DynamicBuffer_v2,
929       typename CompletionCondition, typename ReadHandler>
930   class read_dynbuf_v2_op
931     : detail::base_from_completion_cond<CompletionCondition>
932   {
933   public:
934     template <typename BufferSequence>
read_dynbuf_v2_op(AsyncReadStream & stream,BOOST_ASIO_MOVE_ARG (BufferSequence)buffers,CompletionCondition & completion_condition,ReadHandler & handler)935     read_dynbuf_v2_op(AsyncReadStream& stream,
936         BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
937         CompletionCondition& completion_condition, ReadHandler& handler)
938       : detail::base_from_completion_cond<
939           CompletionCondition>(completion_condition),
940         stream_(stream),
941         buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
942         start_(0),
943         total_transferred_(0),
944         bytes_available_(0),
945         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
946     {
947     }
948 
949 #if defined(BOOST_ASIO_HAS_MOVE)
read_dynbuf_v2_op(const read_dynbuf_v2_op & other)950     read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
951       : detail::base_from_completion_cond<CompletionCondition>(other),
952         stream_(other.stream_),
953         buffers_(other.buffers_),
954         start_(other.start_),
955         total_transferred_(other.total_transferred_),
956         bytes_available_(other.bytes_available_),
957         handler_(other.handler_)
958     {
959     }
960 
read_dynbuf_v2_op(read_dynbuf_v2_op && other)961     read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
962       : detail::base_from_completion_cond<CompletionCondition>(
963           BOOST_ASIO_MOVE_CAST(detail::base_from_completion_cond<
964             CompletionCondition>)(other)),
965         stream_(other.stream_),
966         buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
967         start_(other.start_),
968         total_transferred_(other.total_transferred_),
969         bytes_available_(other.bytes_available_),
970         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
971     {
972     }
973 #endif // defined(BOOST_ASIO_HAS_MOVE)
974 
operator ()(const boost::system::error_code & ec,std::size_t bytes_transferred,int start=0)975     void operator()(const boost::system::error_code& ec,
976         std::size_t bytes_transferred, int start = 0)
977     {
978       std::size_t max_size, pos;
979       switch (start_ = start)
980       {
981         case 1:
982         max_size = this->check_for_completion(ec, total_transferred_);
983         bytes_available_ = std::min<std::size_t>(
984               std::max<std::size_t>(512,
985                 buffers_.capacity() - buffers_.size()),
986               std::min<std::size_t>(max_size,
987                 buffers_.max_size() - buffers_.size()));
988         for (;;)
989         {
990           pos = buffers_.size();
991           buffers_.grow(bytes_available_);
992           {
993             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
994             stream_.async_read_some(buffers_.data(pos, bytes_available_),
995                 BOOST_ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));
996           }
997           return; default:
998           total_transferred_ += bytes_transferred;
999           buffers_.shrink(bytes_available_ - bytes_transferred);
1000           max_size = this->check_for_completion(ec, total_transferred_);
1001           bytes_available_ = std::min<std::size_t>(
1002                 std::max<std::size_t>(512,
1003                   buffers_.capacity() - buffers_.size()),
1004                 std::min<std::size_t>(max_size,
1005                   buffers_.max_size() - buffers_.size()));
1006           if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
1007             break;
1008         }
1009 
1010         handler_(ec, static_cast<const std::size_t&>(total_transferred_));
1011       }
1012     }
1013 
1014   //private:
1015     AsyncReadStream& stream_;
1016     DynamicBuffer_v2 buffers_;
1017     int start_;
1018     std::size_t total_transferred_;
1019     std::size_t bytes_available_;
1020     ReadHandler handler_;
1021   };
1022 
1023   template <typename AsyncReadStream, typename DynamicBuffer_v2,
1024       typename CompletionCondition, typename ReadHandler>
1025   inline asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1026   asio_handler_allocate(std::size_t size,
1027       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1028         CompletionCondition, ReadHandler>* this_handler)
1029   {
1030 #if defined(BOOST_ASIO_NO_DEPRECATED)
1031     boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
1032     return asio_handler_allocate_is_no_longer_used();
1033 #else // defined(BOOST_ASIO_NO_DEPRECATED)
1034     return boost_asio_handler_alloc_helpers::allocate(
1035         size, this_handler->handler_);
1036 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1037   }
1038 
1039   template <typename AsyncReadStream, typename DynamicBuffer_v2,
1040       typename CompletionCondition, typename ReadHandler>
1041   inline asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * pointer,std::size_t size,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1042   asio_handler_deallocate(void* pointer, std::size_t size,
1043       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1044         CompletionCondition, ReadHandler>* this_handler)
1045   {
1046     boost_asio_handler_alloc_helpers::deallocate(
1047         pointer, size, this_handler->handler_);
1048 #if defined(BOOST_ASIO_NO_DEPRECATED)
1049     return asio_handler_deallocate_is_no_longer_used();
1050 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1051   }
1052 
1053   template <typename AsyncReadStream, typename DynamicBuffer_v2,
1054       typename CompletionCondition, typename ReadHandler>
asio_handler_is_continuation(read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1055   inline bool asio_handler_is_continuation(
1056       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1057         CompletionCondition, ReadHandler>* this_handler)
1058   {
1059     return this_handler->start_ == 0 ? true
1060       : boost_asio_handler_cont_helpers::is_continuation(
1061           this_handler->handler_);
1062   }
1063 
1064   template <typename Function, typename AsyncReadStream,
1065       typename DynamicBuffer_v2, typename CompletionCondition,
1066       typename ReadHandler>
1067   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(Function & function,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1068   asio_handler_invoke(Function& function,
1069       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1070         CompletionCondition, ReadHandler>* this_handler)
1071   {
1072     boost_asio_handler_invoke_helpers::invoke(
1073         function, this_handler->handler_);
1074 #if defined(BOOST_ASIO_NO_DEPRECATED)
1075     return asio_handler_invoke_is_no_longer_used();
1076 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1077   }
1078 
1079   template <typename Function, typename AsyncReadStream,
1080       typename DynamicBuffer_v2, typename CompletionCondition,
1081       typename ReadHandler>
1082   inline asio_handler_invoke_is_deprecated
asio_handler_invoke(const Function & function,read_dynbuf_v2_op<AsyncReadStream,DynamicBuffer_v2,CompletionCondition,ReadHandler> * this_handler)1083   asio_handler_invoke(const Function& function,
1084       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
1085         CompletionCondition, ReadHandler>* this_handler)
1086   {
1087     boost_asio_handler_invoke_helpers::invoke(
1088         function, this_handler->handler_);
1089 #if defined(BOOST_ASIO_NO_DEPRECATED)
1090     return asio_handler_invoke_is_no_longer_used();
1091 #endif // defined(BOOST_ASIO_NO_DEPRECATED)
1092   }
1093 
1094   template <typename AsyncReadStream>
1095   class initiate_async_read_dynbuf_v2
1096   {
1097   public:
1098     typedef typename AsyncReadStream::executor_type executor_type;
1099 
initiate_async_read_dynbuf_v2(AsyncReadStream & stream)1100     explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
1101       : stream_(stream)
1102     {
1103     }
1104 
get_executor() const1105     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
1106     {
1107       return stream_.get_executor();
1108     }
1109 
1110     template <typename ReadHandler, typename DynamicBuffer_v2,
1111         typename CompletionCondition>
operator ()(BOOST_ASIO_MOVE_ARG (ReadHandler)handler,BOOST_ASIO_MOVE_ARG (DynamicBuffer_v2)buffers,BOOST_ASIO_MOVE_ARG (CompletionCondition)completion_cond) const1112     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1113         BOOST_ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
1114         BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
1115     {
1116       // If you get an error on the following line it means that your handler
1117       // does not meet the documented type requirements for a ReadHandler.
1118       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1119 
1120       non_const_lvalue<ReadHandler> handler2(handler);
1121       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
1122       read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,
1123         CompletionCondition, typename decay<ReadHandler>::type>(
1124           stream_, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1125             completion_cond2.value, handler2.value)(
1126               boost::system::error_code(), 0, 1);
1127     }
1128 
1129   private:
1130     AsyncReadStream& stream_;
1131   };
1132 } // namespace detail
1133 
1134 #if !defined(GENERATING_DOCUMENTATION)
1135 
1136 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1137     typename CompletionCondition, typename ReadHandler, typename Allocator>
1138 struct associated_allocator<
1139     detail::read_dynbuf_v2_op<AsyncReadStream,
1140       DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1141     Allocator>
1142 {
1143   typedef typename associated_allocator<ReadHandler, Allocator>::type type;
1144 
getboost::asio::associated_allocator1145   static type get(
1146       const detail::read_dynbuf_v2_op<AsyncReadStream,
1147         DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1148       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
1149   {
1150     return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
1151   }
1152 };
1153 
1154 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1155     typename CompletionCondition, typename ReadHandler, typename Executor>
1156 struct associated_executor<
1157     detail::read_dynbuf_v2_op<AsyncReadStream,
1158       DynamicBuffer_v2, CompletionCondition, ReadHandler>,
1159     Executor>
1160   : detail::associated_executor_forwarding_base<ReadHandler, Executor>
1161 {
1162   typedef typename associated_executor<ReadHandler, Executor>::type type;
1163 
getboost::asio::associated_executor1164   static type get(
1165       const detail::read_dynbuf_v2_op<AsyncReadStream,
1166         DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
1167       const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
1168   {
1169     return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
1170   }
1171 };
1172 
1173 #endif // !defined(GENERATING_DOCUMENTATION)
1174 
1175 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1176     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1177       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1178 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1179     void (boost::system::error_code, std::size_t))
1180 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1181     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1182     typename constraint<
1183       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1184     >::type)
1185 {
1186   return async_read(s,
1187       BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1188       transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
1189 }
1190 
1191 template <typename AsyncReadStream,
1192     typename DynamicBuffer_v2, typename CompletionCondition,
1193     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1194       std::size_t)) ReadHandler>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,void (boost::system::error_code,std::size_t))1195 inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
1196     void (boost::system::error_code, std::size_t))
1197 async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1198     CompletionCondition completion_condition,
1199     BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
1200     typename constraint<
1201       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1202     >::type)
1203 {
1204   return async_initiate<ReadHandler,
1205     void (boost::system::error_code, std::size_t)>(
1206       detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
1207       handler, BOOST_ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
1208       BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
1209 }
1210 
1211 } // namespace asio
1212 } // namespace boost
1213 
1214 #include <boost/asio/detail/pop_options.hpp>
1215 
1216 #endif // BOOST_ASIO_IMPL_READ_HPP
1217