Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:56

0001 //
0002 // impl/read.hpp
0003 // ~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_IMPL_READ_HPP
0012 #define BOOST_ASIO_IMPL_READ_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <algorithm>
0019 #include <boost/asio/associator.hpp>
0020 #include <boost/asio/buffer.hpp>
0021 #include <boost/asio/detail/array_fwd.hpp>
0022 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0023 #include <boost/asio/detail/base_from_completion_cond.hpp>
0024 #include <boost/asio/detail/bind_handler.hpp>
0025 #include <boost/asio/detail/consuming_buffers.hpp>
0026 #include <boost/asio/detail/dependent_type.hpp>
0027 #include <boost/asio/detail/handler_cont_helpers.hpp>
0028 #include <boost/asio/detail/handler_tracking.hpp>
0029 #include <boost/asio/detail/handler_type_requirements.hpp>
0030 #include <boost/asio/detail/non_const_lvalue.hpp>
0031 #include <boost/asio/detail/throw_error.hpp>
0032 #include <boost/asio/error.hpp>
0033 
0034 #include <boost/asio/detail/push_options.hpp>
0035 
0036 namespace boost {
0037 namespace asio {
0038 
0039 namespace detail
0040 {
0041   template <typename SyncReadStream, typename MutableBufferSequence,
0042       typename MutableBufferIterator, typename CompletionCondition>
0043   std::size_t read_buffer_seq(SyncReadStream& s,
0044       const MutableBufferSequence& buffers, const MutableBufferIterator&,
0045       CompletionCondition completion_condition, boost::system::error_code& ec)
0046   {
0047     ec = boost::system::error_code();
0048     boost::asio::detail::consuming_buffers<mutable_buffer,
0049         MutableBufferSequence, MutableBufferIterator> tmp(buffers);
0050     while (!tmp.empty())
0051     {
0052       if (std::size_t max_size = detail::adapt_completion_condition_result(
0053             completion_condition(ec, tmp.total_consumed())))
0054         tmp.consume(s.read_some(tmp.prepare(max_size), ec));
0055       else
0056         break;
0057     }
0058     return tmp.total_consumed();
0059   }
0060 } // namespace detail
0061 
0062 template <typename SyncReadStream, typename MutableBufferSequence,
0063     typename CompletionCondition>
0064 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0065     CompletionCondition completion_condition, boost::system::error_code& ec,
0066     constraint_t<
0067       is_mutable_buffer_sequence<MutableBufferSequence>::value
0068     >)
0069 {
0070   return detail::read_buffer_seq(s, buffers,
0071       boost::asio::buffer_sequence_begin(buffers),
0072       static_cast<CompletionCondition&&>(completion_condition), ec);
0073 }
0074 
0075 template <typename SyncReadStream, typename MutableBufferSequence>
0076 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0077     constraint_t<
0078       is_mutable_buffer_sequence<MutableBufferSequence>::value
0079     >)
0080 {
0081   boost::system::error_code ec;
0082   std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
0083   boost::asio::detail::throw_error(ec, "read");
0084   return bytes_transferred;
0085 }
0086 
0087 template <typename SyncReadStream, typename MutableBufferSequence>
0088 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0089     boost::system::error_code& ec,
0090     constraint_t<
0091       is_mutable_buffer_sequence<MutableBufferSequence>::value
0092     >)
0093 {
0094   return read(s, buffers, transfer_all(), ec);
0095 }
0096 
0097 template <typename SyncReadStream, typename MutableBufferSequence,
0098     typename CompletionCondition>
0099 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0100     CompletionCondition completion_condition,
0101     constraint_t<
0102       is_mutable_buffer_sequence<MutableBufferSequence>::value
0103     >)
0104 {
0105   boost::system::error_code ec;
0106   std::size_t bytes_transferred = read(s, buffers,
0107       static_cast<CompletionCondition&&>(completion_condition), ec);
0108   boost::asio::detail::throw_error(ec, "read");
0109   return bytes_transferred;
0110 }
0111 
0112 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0113 
0114 template <typename SyncReadStream, typename DynamicBuffer_v1,
0115     typename CompletionCondition>
0116 std::size_t read(SyncReadStream& s,
0117     DynamicBuffer_v1&& buffers,
0118     CompletionCondition completion_condition, boost::system::error_code& ec,
0119     constraint_t<
0120       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0121     >,
0122     constraint_t<
0123       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0124     >)
0125 {
0126   decay_t<DynamicBuffer_v1> b(
0127       static_cast<DynamicBuffer_v1&&>(buffers));
0128 
0129   ec = boost::system::error_code();
0130   std::size_t total_transferred = 0;
0131   std::size_t max_size = detail::adapt_completion_condition_result(
0132         completion_condition(ec, total_transferred));
0133   std::size_t bytes_available = std::min<std::size_t>(
0134         std::max<std::size_t>(512, b.capacity() - b.size()),
0135         std::min<std::size_t>(max_size, b.max_size() - b.size()));
0136   while (bytes_available > 0)
0137   {
0138     std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
0139     b.commit(bytes_transferred);
0140     total_transferred += bytes_transferred;
0141     max_size = detail::adapt_completion_condition_result(
0142           completion_condition(ec, total_transferred));
0143     bytes_available = std::min<std::size_t>(
0144           std::max<std::size_t>(512, b.capacity() - b.size()),
0145           std::min<std::size_t>(max_size, b.max_size() - b.size()));
0146   }
0147   return total_transferred;
0148 }
0149 
0150 template <typename SyncReadStream, typename DynamicBuffer_v1>
0151 inline std::size_t read(SyncReadStream& s,
0152     DynamicBuffer_v1&& buffers,
0153     constraint_t<
0154       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0155     >,
0156     constraint_t<
0157       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0158     >)
0159 {
0160   boost::system::error_code ec;
0161   std::size_t bytes_transferred = read(s,
0162       static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec);
0163   boost::asio::detail::throw_error(ec, "read");
0164   return bytes_transferred;
0165 }
0166 
0167 template <typename SyncReadStream, typename DynamicBuffer_v1>
0168 inline std::size_t read(SyncReadStream& s,
0169     DynamicBuffer_v1&& buffers,
0170     boost::system::error_code& ec,
0171     constraint_t<
0172       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0173     >,
0174     constraint_t<
0175       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0176     >)
0177 {
0178   return read(s, static_cast<DynamicBuffer_v1&&>(buffers),
0179       transfer_all(), ec);
0180 }
0181 
0182 template <typename SyncReadStream, typename DynamicBuffer_v1,
0183     typename CompletionCondition>
0184 inline std::size_t read(SyncReadStream& s,
0185     DynamicBuffer_v1&& buffers,
0186     CompletionCondition completion_condition,
0187     constraint_t<
0188       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0189     >,
0190     constraint_t<
0191       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0192     >)
0193 {
0194   boost::system::error_code ec;
0195   std::size_t bytes_transferred = read(s,
0196       static_cast<DynamicBuffer_v1&&>(buffers),
0197       static_cast<CompletionCondition&&>(completion_condition), ec);
0198   boost::asio::detail::throw_error(ec, "read");
0199   return bytes_transferred;
0200 }
0201 
0202 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0203 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0204 
0205 template <typename SyncReadStream, typename Allocator,
0206     typename CompletionCondition>
0207 inline std::size_t read(SyncReadStream& s,
0208     boost::asio::basic_streambuf<Allocator>& b,
0209     CompletionCondition completion_condition, boost::system::error_code& ec)
0210 {
0211   return read(s, basic_streambuf_ref<Allocator>(b),
0212       static_cast<CompletionCondition&&>(completion_condition), ec);
0213 }
0214 
0215 template <typename SyncReadStream, typename Allocator>
0216 inline std::size_t read(SyncReadStream& s,
0217     boost::asio::basic_streambuf<Allocator>& b)
0218 {
0219   return read(s, basic_streambuf_ref<Allocator>(b));
0220 }
0221 
0222 template <typename SyncReadStream, typename Allocator>
0223 inline std::size_t read(SyncReadStream& s,
0224     boost::asio::basic_streambuf<Allocator>& b,
0225     boost::system::error_code& ec)
0226 {
0227   return read(s, basic_streambuf_ref<Allocator>(b), ec);
0228 }
0229 
0230 template <typename SyncReadStream, typename Allocator,
0231     typename CompletionCondition>
0232 inline std::size_t read(SyncReadStream& s,
0233     boost::asio::basic_streambuf<Allocator>& b,
0234     CompletionCondition completion_condition)
0235 {
0236   return read(s, basic_streambuf_ref<Allocator>(b),
0237       static_cast<CompletionCondition&&>(completion_condition));
0238 }
0239 
0240 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0241 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0242 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0243 
0244 template <typename SyncReadStream, typename DynamicBuffer_v2,
0245     typename CompletionCondition>
0246 std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0247     CompletionCondition completion_condition, boost::system::error_code& ec,
0248     constraint_t<
0249       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0250     >)
0251 {
0252   DynamicBuffer_v2& b = buffers;
0253 
0254   ec = boost::system::error_code();
0255   std::size_t total_transferred = 0;
0256   std::size_t max_size = detail::adapt_completion_condition_result(
0257         completion_condition(ec, total_transferred));
0258   std::size_t bytes_available = std::min<std::size_t>(
0259         std::max<std::size_t>(512, b.capacity() - b.size()),
0260         std::min<std::size_t>(max_size, b.max_size() - b.size()));
0261   while (bytes_available > 0)
0262   {
0263     std::size_t pos = b.size();
0264     b.grow(bytes_available);
0265     std::size_t bytes_transferred = s.read_some(
0266         b.data(pos, bytes_available), ec);
0267     b.shrink(bytes_available - bytes_transferred);
0268     total_transferred += bytes_transferred;
0269     max_size = detail::adapt_completion_condition_result(
0270           completion_condition(ec, total_transferred));
0271     bytes_available = std::min<std::size_t>(
0272           std::max<std::size_t>(512, b.capacity() - b.size()),
0273           std::min<std::size_t>(max_size, b.max_size() - b.size()));
0274   }
0275   return total_transferred;
0276 }
0277 
0278 template <typename SyncReadStream, typename DynamicBuffer_v2>
0279 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0280     constraint_t<
0281       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0282     >)
0283 {
0284   boost::system::error_code ec;
0285   std::size_t bytes_transferred = read(s,
0286       static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec);
0287   boost::asio::detail::throw_error(ec, "read");
0288   return bytes_transferred;
0289 }
0290 
0291 template <typename SyncReadStream, typename DynamicBuffer_v2>
0292 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0293     boost::system::error_code& ec,
0294     constraint_t<
0295       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0296     >)
0297 {
0298   return read(s, static_cast<DynamicBuffer_v2&&>(buffers),
0299       transfer_all(), ec);
0300 }
0301 
0302 template <typename SyncReadStream, typename DynamicBuffer_v2,
0303     typename CompletionCondition>
0304 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0305     CompletionCondition completion_condition,
0306     constraint_t<
0307       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0308     >)
0309 {
0310   boost::system::error_code ec;
0311   std::size_t bytes_transferred = read(s,
0312       static_cast<DynamicBuffer_v2&&>(buffers),
0313       static_cast<CompletionCondition&&>(completion_condition), ec);
0314   boost::asio::detail::throw_error(ec, "read");
0315   return bytes_transferred;
0316 }
0317 
0318 namespace detail
0319 {
0320   template <typename AsyncReadStream, typename MutableBufferSequence,
0321       typename MutableBufferIterator, typename CompletionCondition,
0322       typename ReadHandler>
0323   class read_op
0324     : public base_from_cancellation_state<ReadHandler>,
0325       base_from_completion_cond<CompletionCondition>
0326   {
0327   public:
0328     read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
0329         CompletionCondition& completion_condition, ReadHandler& handler)
0330       : base_from_cancellation_state<ReadHandler>(
0331           handler, enable_partial_cancellation()),
0332         base_from_completion_cond<CompletionCondition>(completion_condition),
0333         stream_(stream),
0334         buffers_(buffers),
0335         start_(0),
0336         handler_(static_cast<ReadHandler&&>(handler))
0337     {
0338     }
0339 
0340     read_op(const read_op& other)
0341       : base_from_cancellation_state<ReadHandler>(other),
0342         base_from_completion_cond<CompletionCondition>(other),
0343         stream_(other.stream_),
0344         buffers_(other.buffers_),
0345         start_(other.start_),
0346         handler_(other.handler_)
0347     {
0348     }
0349 
0350     read_op(read_op&& other)
0351       : base_from_cancellation_state<ReadHandler>(
0352           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0353         base_from_completion_cond<CompletionCondition>(
0354           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0355         stream_(other.stream_),
0356         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0357         start_(other.start_),
0358         handler_(static_cast<ReadHandler&&>(other.handler_))
0359     {
0360     }
0361 
0362     void operator()(boost::system::error_code ec,
0363         std::size_t bytes_transferred, int start = 0)
0364     {
0365       std::size_t max_size;
0366       switch (start_ = start)
0367       {
0368         case 1:
0369         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0370         for (;;)
0371         {
0372           {
0373             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0374             stream_.async_read_some(buffers_.prepare(max_size),
0375                 static_cast<read_op&&>(*this));
0376           }
0377           return; default:
0378           buffers_.consume(bytes_transferred);
0379           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0380             break;
0381           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0382           if (max_size == 0)
0383             break;
0384           if (this->cancelled() != cancellation_type::none)
0385           {
0386             ec = error::operation_aborted;
0387             break;
0388           }
0389         }
0390 
0391         static_cast<ReadHandler&&>(handler_)(
0392             static_cast<const boost::system::error_code&>(ec),
0393             static_cast<const std::size_t&>(buffers_.total_consumed()));
0394       }
0395     }
0396 
0397   //private:
0398     typedef boost::asio::detail::consuming_buffers<mutable_buffer,
0399         MutableBufferSequence, MutableBufferIterator> buffers_type;
0400 
0401     AsyncReadStream& stream_;
0402     buffers_type buffers_;
0403     int start_;
0404     ReadHandler handler_;
0405   };
0406 
0407   template <typename AsyncReadStream, typename MutableBufferSequence,
0408       typename MutableBufferIterator, typename CompletionCondition,
0409       typename ReadHandler>
0410   inline bool asio_handler_is_continuation(
0411       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
0412         CompletionCondition, ReadHandler>* this_handler)
0413   {
0414     return this_handler->start_ == 0 ? true
0415       : boost_asio_handler_cont_helpers::is_continuation(
0416           this_handler->handler_);
0417   }
0418 
0419   template <typename AsyncReadStream, typename MutableBufferSequence,
0420       typename MutableBufferIterator, typename CompletionCondition,
0421       typename ReadHandler>
0422   inline void start_read_op(AsyncReadStream& stream,
0423       const MutableBufferSequence& buffers, const MutableBufferIterator&,
0424       CompletionCondition& completion_condition, ReadHandler& handler)
0425   {
0426     read_op<AsyncReadStream, MutableBufferSequence,
0427       MutableBufferIterator, CompletionCondition, ReadHandler>(
0428         stream, buffers, completion_condition, handler)(
0429           boost::system::error_code(), 0, 1);
0430   }
0431 
0432   template <typename AsyncReadStream>
0433   class initiate_async_read
0434   {
0435   public:
0436     typedef typename AsyncReadStream::executor_type executor_type;
0437 
0438     explicit initiate_async_read(AsyncReadStream& stream)
0439       : stream_(stream)
0440     {
0441     }
0442 
0443     executor_type get_executor() const noexcept
0444     {
0445       return stream_.get_executor();
0446     }
0447 
0448     template <typename ReadHandler, typename MutableBufferSequence,
0449         typename CompletionCondition>
0450     void operator()(ReadHandler&& handler,
0451         const MutableBufferSequence& buffers,
0452         CompletionCondition&& completion_cond) const
0453     {
0454       // If you get an error on the following line it means that your handler
0455       // does not meet the documented type requirements for a ReadHandler.
0456       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0457 
0458       non_const_lvalue<ReadHandler> handler2(handler);
0459       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0460       start_read_op(stream_, buffers,
0461           boost::asio::buffer_sequence_begin(buffers),
0462           completion_cond2.value, handler2.value);
0463     }
0464 
0465   private:
0466     AsyncReadStream& stream_;
0467   };
0468 } // namespace detail
0469 
0470 #if !defined(GENERATING_DOCUMENTATION)
0471 
0472 template <template <typename, typename> class Associator,
0473     typename AsyncReadStream, typename MutableBufferSequence,
0474     typename MutableBufferIterator, typename CompletionCondition,
0475     typename ReadHandler, typename DefaultCandidate>
0476 struct associator<Associator,
0477     detail::read_op<AsyncReadStream, MutableBufferSequence,
0478       MutableBufferIterator, CompletionCondition, ReadHandler>,
0479     DefaultCandidate>
0480   : Associator<ReadHandler, DefaultCandidate>
0481 {
0482   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0483       const detail::read_op<AsyncReadStream, MutableBufferSequence,
0484         MutableBufferIterator, CompletionCondition, ReadHandler>& h) noexcept
0485   {
0486     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0487   }
0488 
0489   static auto get(
0490       const detail::read_op<AsyncReadStream, MutableBufferSequence,
0491         MutableBufferIterator, CompletionCondition, ReadHandler>& h,
0492       const DefaultCandidate& c) noexcept
0493     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0494   {
0495     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0496   }
0497 };
0498 
0499 #endif // !defined(GENERATING_DOCUMENTATION)
0500 
0501 template <typename AsyncReadStream,
0502     typename MutableBufferSequence, typename CompletionCondition,
0503     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0504       std::size_t)) ReadToken>
0505 inline auto async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
0506     CompletionCondition completion_condition, ReadToken&& token,
0507     constraint_t<
0508       is_mutable_buffer_sequence<MutableBufferSequence>::value
0509     >)
0510   -> decltype(
0511     async_initiate<ReadToken,
0512       void (boost::system::error_code, std::size_t)>(
0513         declval<detail::initiate_async_read<AsyncReadStream>>(), token, buffers,
0514         static_cast<CompletionCondition&&>(completion_condition)))
0515 {
0516   return async_initiate<ReadToken,
0517     void (boost::system::error_code, std::size_t)>(
0518       detail::initiate_async_read<AsyncReadStream>(s), token, buffers,
0519       static_cast<CompletionCondition&&>(completion_condition));
0520 }
0521 
0522 template <typename AsyncReadStream, typename MutableBufferSequence,
0523     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0524       std::size_t)) ReadToken>
0525 inline auto async_read(AsyncReadStream& s,
0526     const MutableBufferSequence& buffers, ReadToken&& token,
0527     constraint_t<
0528       is_mutable_buffer_sequence<MutableBufferSequence>::value
0529     >)
0530   -> decltype(
0531     async_initiate<ReadToken,
0532       void (boost::system::error_code, std::size_t)>(
0533         declval<detail::initiate_async_read<AsyncReadStream>>(),
0534         token, buffers, transfer_all()))
0535 {
0536   return async_initiate<ReadToken,
0537     void (boost::system::error_code, std::size_t)>(
0538       detail::initiate_async_read<AsyncReadStream>(s),
0539       token, buffers, transfer_all());
0540 }
0541 
0542 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0543 
0544 namespace detail
0545 {
0546   template <typename AsyncReadStream, typename DynamicBuffer_v1,
0547       typename CompletionCondition, typename ReadHandler>
0548   class read_dynbuf_v1_op
0549     : public base_from_cancellation_state<ReadHandler>,
0550       base_from_completion_cond<CompletionCondition>
0551   {
0552   public:
0553     template <typename BufferSequence>
0554     read_dynbuf_v1_op(AsyncReadStream& stream,
0555         BufferSequence&& buffers,
0556         CompletionCondition& completion_condition, ReadHandler& handler)
0557       : base_from_cancellation_state<ReadHandler>(
0558           handler, enable_partial_cancellation()),
0559         base_from_completion_cond<CompletionCondition>(completion_condition),
0560         stream_(stream),
0561         buffers_(static_cast<BufferSequence&&>(buffers)),
0562         start_(0),
0563         total_transferred_(0),
0564         handler_(static_cast<ReadHandler&&>(handler))
0565     {
0566     }
0567 
0568     read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
0569       : base_from_cancellation_state<ReadHandler>(other),
0570         base_from_completion_cond<CompletionCondition>(other),
0571         stream_(other.stream_),
0572         buffers_(other.buffers_),
0573         start_(other.start_),
0574         total_transferred_(other.total_transferred_),
0575         handler_(other.handler_)
0576     {
0577     }
0578 
0579     read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
0580       : base_from_cancellation_state<ReadHandler>(
0581           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0582         base_from_completion_cond<CompletionCondition>(
0583           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0584         stream_(other.stream_),
0585         buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
0586         start_(other.start_),
0587         total_transferred_(other.total_transferred_),
0588         handler_(static_cast<ReadHandler&&>(other.handler_))
0589     {
0590     }
0591 
0592     void operator()(boost::system::error_code ec,
0593         std::size_t bytes_transferred, int start = 0)
0594     {
0595       std::size_t max_size, bytes_available;
0596       switch (start_ = start)
0597       {
0598         case 1:
0599         max_size = this->check_for_completion(ec, total_transferred_);
0600         bytes_available = std::min<std::size_t>(
0601               std::max<std::size_t>(512,
0602                 buffers_.capacity() - buffers_.size()),
0603               std::min<std::size_t>(max_size,
0604                 buffers_.max_size() - buffers_.size()));
0605         for (;;)
0606         {
0607           {
0608             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0609             stream_.async_read_some(buffers_.prepare(bytes_available),
0610                 static_cast<read_dynbuf_v1_op&&>(*this));
0611           }
0612           return; default:
0613           total_transferred_ += bytes_transferred;
0614           buffers_.commit(bytes_transferred);
0615           max_size = this->check_for_completion(ec, total_transferred_);
0616           bytes_available = std::min<std::size_t>(
0617                 std::max<std::size_t>(512,
0618                   buffers_.capacity() - buffers_.size()),
0619                 std::min<std::size_t>(max_size,
0620                   buffers_.max_size() - buffers_.size()));
0621           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
0622             break;
0623           if (this->cancelled() != cancellation_type::none)
0624           {
0625             ec = error::operation_aborted;
0626             break;
0627           }
0628         }
0629 
0630         static_cast<ReadHandler&&>(handler_)(
0631             static_cast<const boost::system::error_code&>(ec),
0632             static_cast<const std::size_t&>(total_transferred_));
0633       }
0634     }
0635 
0636   //private:
0637     AsyncReadStream& stream_;
0638     DynamicBuffer_v1 buffers_;
0639     int start_;
0640     std::size_t total_transferred_;
0641     ReadHandler handler_;
0642   };
0643 
0644   template <typename AsyncReadStream, typename DynamicBuffer_v1,
0645       typename CompletionCondition, typename ReadHandler>
0646   inline bool asio_handler_is_continuation(
0647       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
0648         CompletionCondition, ReadHandler>* this_handler)
0649   {
0650     return this_handler->start_ == 0 ? true
0651       : boost_asio_handler_cont_helpers::is_continuation(
0652           this_handler->handler_);
0653   }
0654 
0655   template <typename AsyncReadStream>
0656   class initiate_async_read_dynbuf_v1
0657   {
0658   public:
0659     typedef typename AsyncReadStream::executor_type executor_type;
0660 
0661     explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
0662       : stream_(stream)
0663     {
0664     }
0665 
0666     executor_type get_executor() const noexcept
0667     {
0668       return stream_.get_executor();
0669     }
0670 
0671     template <typename ReadHandler, typename DynamicBuffer_v1,
0672         typename CompletionCondition>
0673     void operator()(ReadHandler&& handler,
0674         DynamicBuffer_v1&& buffers,
0675         CompletionCondition&& completion_cond) const
0676     {
0677       // If you get an error on the following line it means that your handler
0678       // does not meet the documented type requirements for a ReadHandler.
0679       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0680 
0681       non_const_lvalue<ReadHandler> handler2(handler);
0682       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0683       read_dynbuf_v1_op<AsyncReadStream, decay_t<DynamicBuffer_v1>,
0684         CompletionCondition, decay_t<ReadHandler>>(
0685           stream_, static_cast<DynamicBuffer_v1&&>(buffers),
0686             completion_cond2.value, handler2.value)(
0687               boost::system::error_code(), 0, 1);
0688     }
0689 
0690   private:
0691     AsyncReadStream& stream_;
0692   };
0693 } // namespace detail
0694 
0695 #if !defined(GENERATING_DOCUMENTATION)
0696 
0697 template <template <typename, typename> class Associator,
0698     typename AsyncReadStream, typename DynamicBuffer_v1,
0699     typename CompletionCondition, typename ReadHandler,
0700     typename DefaultCandidate>
0701 struct associator<Associator,
0702     detail::read_dynbuf_v1_op<AsyncReadStream,
0703       DynamicBuffer_v1, CompletionCondition, ReadHandler>,
0704     DefaultCandidate>
0705   : Associator<ReadHandler, DefaultCandidate>
0706 {
0707   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0708       const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
0709         CompletionCondition, ReadHandler>& h) noexcept
0710   {
0711     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0712   }
0713 
0714   static auto get(
0715       const detail::read_dynbuf_v1_op<AsyncReadStream,
0716         DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
0717       const DefaultCandidate& c) noexcept
0718     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0719   {
0720     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0721   }
0722 };
0723 
0724 #endif // !defined(GENERATING_DOCUMENTATION)
0725 
0726 template <typename AsyncReadStream, typename DynamicBuffer_v1,
0727     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0728       std::size_t)) ReadToken>
0729 inline auto async_read(AsyncReadStream& s,
0730     DynamicBuffer_v1&& buffers, ReadToken&& token,
0731     constraint_t<
0732       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0733     >,
0734     constraint_t<
0735       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0736     >)
0737   -> decltype(
0738     async_initiate<ReadToken,
0739       void (boost::system::error_code, std::size_t)>(
0740         declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
0741         token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all()))
0742 {
0743   return async_initiate<ReadToken,
0744     void (boost::system::error_code, std::size_t)>(
0745       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
0746       token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all());
0747 }
0748 
0749 template <typename AsyncReadStream,
0750     typename DynamicBuffer_v1, typename CompletionCondition,
0751     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0752       std::size_t)) ReadToken>
0753 inline auto async_read(AsyncReadStream& s, DynamicBuffer_v1&& buffers,
0754     CompletionCondition completion_condition, ReadToken&& token,
0755     constraint_t<
0756       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0757     >,
0758     constraint_t<
0759       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0760     >)
0761   -> decltype(
0762     async_initiate<ReadToken,
0763       void (boost::system::error_code, std::size_t)>(
0764         declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
0765         token, static_cast<DynamicBuffer_v1&&>(buffers),
0766         static_cast<CompletionCondition&&>(completion_condition)))
0767 {
0768   return async_initiate<ReadToken,
0769     void (boost::system::error_code, std::size_t)>(
0770       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
0771       token, static_cast<DynamicBuffer_v1&&>(buffers),
0772       static_cast<CompletionCondition&&>(completion_condition));
0773 }
0774 
0775 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0776 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0777 
0778 template <typename AsyncReadStream, typename Allocator,
0779     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0780       std::size_t)) ReadToken>
0781 inline auto async_read(AsyncReadStream& s,
0782     basic_streambuf<Allocator>& b, ReadToken&& token)
0783   -> decltype(
0784     async_initiate<ReadToken,
0785       void (boost::system::error_code, std::size_t)>(
0786         declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
0787         token, basic_streambuf_ref<Allocator>(b), transfer_all()))
0788 {
0789   return async_initiate<ReadToken,
0790     void (boost::system::error_code, std::size_t)>(
0791       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
0792       token, basic_streambuf_ref<Allocator>(b), transfer_all());
0793 }
0794 
0795 template <typename AsyncReadStream,
0796     typename Allocator, typename CompletionCondition,
0797     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0798       std::size_t)) ReadToken>
0799 inline auto async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
0800     CompletionCondition completion_condition, ReadToken&& token)
0801   -> decltype(
0802     async_initiate<ReadToken,
0803       void (boost::system::error_code, std::size_t)>(
0804         declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
0805         token, basic_streambuf_ref<Allocator>(b),
0806         static_cast<CompletionCondition&&>(completion_condition)))
0807 {
0808   return async_initiate<ReadToken,
0809     void (boost::system::error_code, std::size_t)>(
0810       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
0811       token, basic_streambuf_ref<Allocator>(b),
0812       static_cast<CompletionCondition&&>(completion_condition));
0813 }
0814 
0815 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0816 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0817 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0818 
0819 namespace detail
0820 {
0821   template <typename AsyncReadStream, typename DynamicBuffer_v2,
0822       typename CompletionCondition, typename ReadHandler>
0823   class read_dynbuf_v2_op
0824     : public base_from_cancellation_state<ReadHandler>,
0825       base_from_completion_cond<CompletionCondition>
0826   {
0827   public:
0828     template <typename BufferSequence>
0829     read_dynbuf_v2_op(AsyncReadStream& stream,
0830         BufferSequence&& buffers,
0831         CompletionCondition& completion_condition, ReadHandler& handler)
0832       : base_from_cancellation_state<ReadHandler>(
0833           handler, enable_partial_cancellation()),
0834         base_from_completion_cond<CompletionCondition>(completion_condition),
0835         stream_(stream),
0836         buffers_(static_cast<BufferSequence&&>(buffers)),
0837         start_(0),
0838         total_transferred_(0),
0839         bytes_available_(0),
0840         handler_(static_cast<ReadHandler&&>(handler))
0841     {
0842     }
0843 
0844     read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
0845       : base_from_cancellation_state<ReadHandler>(other),
0846         base_from_completion_cond<CompletionCondition>(other),
0847         stream_(other.stream_),
0848         buffers_(other.buffers_),
0849         start_(other.start_),
0850         total_transferred_(other.total_transferred_),
0851         bytes_available_(other.bytes_available_),
0852         handler_(other.handler_)
0853     {
0854     }
0855 
0856     read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
0857       : base_from_cancellation_state<ReadHandler>(
0858           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0859         base_from_completion_cond<CompletionCondition>(
0860           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0861         stream_(other.stream_),
0862         buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
0863         start_(other.start_),
0864         total_transferred_(other.total_transferred_),
0865         bytes_available_(other.bytes_available_),
0866         handler_(static_cast<ReadHandler&&>(other.handler_))
0867     {
0868     }
0869 
0870     void operator()(boost::system::error_code ec,
0871         std::size_t bytes_transferred, int start = 0)
0872     {
0873       std::size_t max_size, pos;
0874       switch (start_ = start)
0875       {
0876         case 1:
0877         max_size = this->check_for_completion(ec, total_transferred_);
0878         bytes_available_ = std::min<std::size_t>(
0879               std::max<std::size_t>(512,
0880                 buffers_.capacity() - buffers_.size()),
0881               std::min<std::size_t>(max_size,
0882                 buffers_.max_size() - buffers_.size()));
0883         for (;;)
0884         {
0885           pos = buffers_.size();
0886           buffers_.grow(bytes_available_);
0887           {
0888             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0889             stream_.async_read_some(buffers_.data(pos, bytes_available_),
0890                 static_cast<read_dynbuf_v2_op&&>(*this));
0891           }
0892           return; default:
0893           total_transferred_ += bytes_transferred;
0894           buffers_.shrink(bytes_available_ - bytes_transferred);
0895           max_size = this->check_for_completion(ec, total_transferred_);
0896           bytes_available_ = std::min<std::size_t>(
0897                 std::max<std::size_t>(512,
0898                   buffers_.capacity() - buffers_.size()),
0899                 std::min<std::size_t>(max_size,
0900                   buffers_.max_size() - buffers_.size()));
0901           if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
0902             break;
0903           if (this->cancelled() != cancellation_type::none)
0904           {
0905             ec = error::operation_aborted;
0906             break;
0907           }
0908         }
0909 
0910         static_cast<ReadHandler&&>(handler_)(
0911             static_cast<const boost::system::error_code&>(ec),
0912             static_cast<const std::size_t&>(total_transferred_));
0913       }
0914     }
0915 
0916   //private:
0917     AsyncReadStream& stream_;
0918     DynamicBuffer_v2 buffers_;
0919     int start_;
0920     std::size_t total_transferred_;
0921     std::size_t bytes_available_;
0922     ReadHandler handler_;
0923   };
0924 
0925   template <typename AsyncReadStream, typename DynamicBuffer_v2,
0926       typename CompletionCondition, typename ReadHandler>
0927   inline bool asio_handler_is_continuation(
0928       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
0929         CompletionCondition, ReadHandler>* this_handler)
0930   {
0931     return this_handler->start_ == 0 ? true
0932       : boost_asio_handler_cont_helpers::is_continuation(
0933           this_handler->handler_);
0934   }
0935 
0936   template <typename AsyncReadStream>
0937   class initiate_async_read_dynbuf_v2
0938   {
0939   public:
0940     typedef typename AsyncReadStream::executor_type executor_type;
0941 
0942     explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
0943       : stream_(stream)
0944     {
0945     }
0946 
0947     executor_type get_executor() const noexcept
0948     {
0949       return stream_.get_executor();
0950     }
0951 
0952     template <typename ReadHandler, typename DynamicBuffer_v2,
0953         typename CompletionCondition>
0954     void operator()(ReadHandler&& handler,
0955         DynamicBuffer_v2&& buffers,
0956         CompletionCondition&& completion_cond) const
0957     {
0958       // If you get an error on the following line it means that your handler
0959       // does not meet the documented type requirements for a ReadHandler.
0960       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0961 
0962       non_const_lvalue<ReadHandler> handler2(handler);
0963       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0964       read_dynbuf_v2_op<AsyncReadStream, decay_t<DynamicBuffer_v2>,
0965         CompletionCondition, decay_t<ReadHandler>>(
0966           stream_, static_cast<DynamicBuffer_v2&&>(buffers),
0967             completion_cond2.value, handler2.value)(
0968               boost::system::error_code(), 0, 1);
0969     }
0970 
0971   private:
0972     AsyncReadStream& stream_;
0973   };
0974 } // namespace detail
0975 
0976 #if !defined(GENERATING_DOCUMENTATION)
0977 
0978 template <template <typename, typename> class Associator,
0979     typename AsyncReadStream, typename DynamicBuffer_v2,
0980     typename CompletionCondition, typename ReadHandler,
0981     typename DefaultCandidate>
0982 struct associator<Associator,
0983     detail::read_dynbuf_v2_op<AsyncReadStream,
0984       DynamicBuffer_v2, CompletionCondition, ReadHandler>,
0985     DefaultCandidate>
0986   : Associator<ReadHandler, DefaultCandidate>
0987 {
0988   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0989       const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
0990         CompletionCondition, ReadHandler>& h) noexcept
0991   {
0992     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0993   }
0994 
0995   static auto get(
0996       const detail::read_dynbuf_v2_op<AsyncReadStream,
0997         DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
0998       const DefaultCandidate& c) noexcept
0999     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
1000   {
1001     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
1002   }
1003 };
1004 
1005 #endif // !defined(GENERATING_DOCUMENTATION)
1006 
1007 template <typename AsyncReadStream, typename DynamicBuffer_v2,
1008     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1009       std::size_t)) ReadToken>
1010 inline auto async_read(AsyncReadStream& s,
1011     DynamicBuffer_v2 buffers, ReadToken&& token,
1012     constraint_t<
1013       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1014     >)
1015   -> decltype(
1016     async_initiate<ReadToken,
1017       void (boost::system::error_code, std::size_t)>(
1018         declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(),
1019         token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all()))
1020 {
1021   return async_initiate<ReadToken,
1022     void (boost::system::error_code, std::size_t)>(
1023       detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
1024       token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all());
1025 }
1026 
1027 template <typename AsyncReadStream,
1028     typename DynamicBuffer_v2, typename CompletionCondition,
1029     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1030       std::size_t)) ReadToken>
1031 inline auto async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
1032     CompletionCondition completion_condition, ReadToken&& token,
1033     constraint_t<
1034       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
1035     >)
1036   -> decltype(
1037     async_initiate<ReadToken,
1038       void (boost::system::error_code, std::size_t)>(
1039         declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(),
1040         token, static_cast<DynamicBuffer_v2&&>(buffers),
1041         static_cast<CompletionCondition&&>(completion_condition)))
1042 {
1043   return async_initiate<ReadToken,
1044     void (boost::system::error_code, std::size_t)>(
1045       detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
1046       token, static_cast<DynamicBuffer_v2&&>(buffers),
1047       static_cast<CompletionCondition&&>(completion_condition));
1048 }
1049 
1050 } // namespace asio
1051 } // namespace boost
1052 
1053 #include <boost/asio/detail/pop_options.hpp>
1054 
1055 #endif // BOOST_ASIO_IMPL_READ_HPP