Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/asio/impl/read.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // impl/read.hpp
0003 // ~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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     constraint_t<
0070       is_completion_condition<CompletionCondition>::value
0071     >)
0072 {
0073   return detail::read_buffer_seq(s, buffers,
0074       boost::asio::buffer_sequence_begin(buffers),
0075       static_cast<CompletionCondition&&>(completion_condition), ec);
0076 }
0077 
0078 template <typename SyncReadStream, typename MutableBufferSequence>
0079 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0080     constraint_t<
0081       is_mutable_buffer_sequence<MutableBufferSequence>::value
0082     >)
0083 {
0084   boost::system::error_code ec;
0085   std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
0086   boost::asio::detail::throw_error(ec, "read");
0087   return bytes_transferred;
0088 }
0089 
0090 template <typename SyncReadStream, typename MutableBufferSequence>
0091 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0092     boost::system::error_code& ec,
0093     constraint_t<
0094       is_mutable_buffer_sequence<MutableBufferSequence>::value
0095     >)
0096 {
0097   return read(s, buffers, transfer_all(), ec);
0098 }
0099 
0100 template <typename SyncReadStream, typename MutableBufferSequence,
0101     typename CompletionCondition>
0102 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
0103     CompletionCondition completion_condition,
0104     constraint_t<
0105       is_mutable_buffer_sequence<MutableBufferSequence>::value
0106     >,
0107     constraint_t<
0108       is_completion_condition<CompletionCondition>::value
0109     >)
0110 {
0111   boost::system::error_code ec;
0112   std::size_t bytes_transferred = read(s, buffers,
0113       static_cast<CompletionCondition&&>(completion_condition), ec);
0114   boost::asio::detail::throw_error(ec, "read");
0115   return bytes_transferred;
0116 }
0117 
0118 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0119 
0120 template <typename SyncReadStream, typename DynamicBuffer_v1,
0121     typename CompletionCondition>
0122 std::size_t read(SyncReadStream& s,
0123     DynamicBuffer_v1&& buffers,
0124     CompletionCondition completion_condition, boost::system::error_code& ec,
0125     constraint_t<
0126       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0127     >,
0128     constraint_t<
0129       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0130     >,
0131     constraint_t<
0132       is_completion_condition<CompletionCondition>::value
0133     >)
0134 {
0135   decay_t<DynamicBuffer_v1> b(
0136       static_cast<DynamicBuffer_v1&&>(buffers));
0137 
0138   ec = boost::system::error_code();
0139   std::size_t total_transferred = 0;
0140   std::size_t max_size = detail::adapt_completion_condition_result(
0141         completion_condition(ec, total_transferred));
0142   std::size_t bytes_available = std::min<std::size_t>(
0143         std::max<std::size_t>(512, b.capacity() - b.size()),
0144         std::min<std::size_t>(max_size, b.max_size() - b.size()));
0145   while (bytes_available > 0)
0146   {
0147     std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
0148     b.commit(bytes_transferred);
0149     total_transferred += bytes_transferred;
0150     max_size = detail::adapt_completion_condition_result(
0151           completion_condition(ec, total_transferred));
0152     bytes_available = std::min<std::size_t>(
0153           std::max<std::size_t>(512, b.capacity() - b.size()),
0154           std::min<std::size_t>(max_size, b.max_size() - b.size()));
0155   }
0156   return total_transferred;
0157 }
0158 
0159 template <typename SyncReadStream, typename DynamicBuffer_v1>
0160 inline std::size_t read(SyncReadStream& s,
0161     DynamicBuffer_v1&& buffers,
0162     constraint_t<
0163       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0164     >,
0165     constraint_t<
0166       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0167     >)
0168 {
0169   boost::system::error_code ec;
0170   std::size_t bytes_transferred = read(s,
0171       static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec);
0172   boost::asio::detail::throw_error(ec, "read");
0173   return bytes_transferred;
0174 }
0175 
0176 template <typename SyncReadStream, typename DynamicBuffer_v1>
0177 inline std::size_t read(SyncReadStream& s,
0178     DynamicBuffer_v1&& buffers,
0179     boost::system::error_code& ec,
0180     constraint_t<
0181       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0182     >,
0183     constraint_t<
0184       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0185     >)
0186 {
0187   return read(s, static_cast<DynamicBuffer_v1&&>(buffers),
0188       transfer_all(), ec);
0189 }
0190 
0191 template <typename SyncReadStream, typename DynamicBuffer_v1,
0192     typename CompletionCondition>
0193 inline std::size_t read(SyncReadStream& s,
0194     DynamicBuffer_v1&& buffers,
0195     CompletionCondition completion_condition,
0196     constraint_t<
0197       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0198     >,
0199     constraint_t<
0200       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0201     >,
0202     constraint_t<
0203       is_completion_condition<CompletionCondition>::value
0204     >)
0205 {
0206   boost::system::error_code ec;
0207   std::size_t bytes_transferred = read(s,
0208       static_cast<DynamicBuffer_v1&&>(buffers),
0209       static_cast<CompletionCondition&&>(completion_condition), ec);
0210   boost::asio::detail::throw_error(ec, "read");
0211   return bytes_transferred;
0212 }
0213 
0214 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0215 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0216 
0217 template <typename SyncReadStream, typename Allocator,
0218     typename CompletionCondition>
0219 inline std::size_t read(SyncReadStream& s,
0220     boost::asio::basic_streambuf<Allocator>& b,
0221     CompletionCondition completion_condition, boost::system::error_code& ec,
0222     constraint_t<
0223       is_completion_condition<CompletionCondition>::value
0224     >)
0225 {
0226   return read(s, basic_streambuf_ref<Allocator>(b),
0227       static_cast<CompletionCondition&&>(completion_condition), ec);
0228 }
0229 
0230 template <typename SyncReadStream, typename Allocator>
0231 inline std::size_t read(SyncReadStream& s,
0232     boost::asio::basic_streambuf<Allocator>& b)
0233 {
0234   return read(s, basic_streambuf_ref<Allocator>(b));
0235 }
0236 
0237 template <typename SyncReadStream, typename Allocator>
0238 inline std::size_t read(SyncReadStream& s,
0239     boost::asio::basic_streambuf<Allocator>& b,
0240     boost::system::error_code& ec)
0241 {
0242   return read(s, basic_streambuf_ref<Allocator>(b), ec);
0243 }
0244 
0245 template <typename SyncReadStream, typename Allocator,
0246     typename CompletionCondition>
0247 inline std::size_t read(SyncReadStream& s,
0248     boost::asio::basic_streambuf<Allocator>& b,
0249     CompletionCondition completion_condition,
0250     constraint_t<
0251       is_completion_condition<CompletionCondition>::value
0252     >)
0253 {
0254   return read(s, basic_streambuf_ref<Allocator>(b),
0255       static_cast<CompletionCondition&&>(completion_condition));
0256 }
0257 
0258 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0259 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0260 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0261 
0262 template <typename SyncReadStream, typename DynamicBuffer_v2,
0263     typename CompletionCondition>
0264 std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0265     CompletionCondition completion_condition, boost::system::error_code& ec,
0266     constraint_t<
0267       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0268     >,
0269     constraint_t<
0270       is_completion_condition<CompletionCondition>::value
0271     >)
0272 {
0273   DynamicBuffer_v2& b = buffers;
0274 
0275   ec = boost::system::error_code();
0276   std::size_t total_transferred = 0;
0277   std::size_t max_size = detail::adapt_completion_condition_result(
0278         completion_condition(ec, total_transferred));
0279   std::size_t bytes_available = std::min<std::size_t>(
0280         std::max<std::size_t>(512, b.capacity() - b.size()),
0281         std::min<std::size_t>(max_size, b.max_size() - b.size()));
0282   while (bytes_available > 0)
0283   {
0284     std::size_t pos = b.size();
0285     b.grow(bytes_available);
0286     std::size_t bytes_transferred = s.read_some(
0287         b.data(pos, bytes_available), ec);
0288     b.shrink(bytes_available - bytes_transferred);
0289     total_transferred += bytes_transferred;
0290     max_size = detail::adapt_completion_condition_result(
0291           completion_condition(ec, total_transferred));
0292     bytes_available = std::min<std::size_t>(
0293           std::max<std::size_t>(512, b.capacity() - b.size()),
0294           std::min<std::size_t>(max_size, b.max_size() - b.size()));
0295   }
0296   return total_transferred;
0297 }
0298 
0299 template <typename SyncReadStream, typename DynamicBuffer_v2>
0300 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0301     constraint_t<
0302       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0303     >)
0304 {
0305   boost::system::error_code ec;
0306   std::size_t bytes_transferred = read(s,
0307       static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec);
0308   boost::asio::detail::throw_error(ec, "read");
0309   return bytes_transferred;
0310 }
0311 
0312 template <typename SyncReadStream, typename DynamicBuffer_v2>
0313 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0314     boost::system::error_code& ec,
0315     constraint_t<
0316       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0317     >)
0318 {
0319   return read(s, static_cast<DynamicBuffer_v2&&>(buffers),
0320       transfer_all(), ec);
0321 }
0322 
0323 template <typename SyncReadStream, typename DynamicBuffer_v2,
0324     typename CompletionCondition>
0325 inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
0326     CompletionCondition completion_condition,
0327     constraint_t<
0328       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0329     >,
0330     constraint_t<
0331       is_completion_condition<CompletionCondition>::value
0332     >)
0333 {
0334   boost::system::error_code ec;
0335   std::size_t bytes_transferred = read(s,
0336       static_cast<DynamicBuffer_v2&&>(buffers),
0337       static_cast<CompletionCondition&&>(completion_condition), ec);
0338   boost::asio::detail::throw_error(ec, "read");
0339   return bytes_transferred;
0340 }
0341 
0342 namespace detail
0343 {
0344   template <typename AsyncReadStream, typename MutableBufferSequence,
0345       typename MutableBufferIterator, typename CompletionCondition,
0346       typename ReadHandler>
0347   class read_op
0348     : public base_from_cancellation_state<ReadHandler>,
0349       base_from_completion_cond<CompletionCondition>
0350   {
0351   public:
0352     read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
0353         CompletionCondition& completion_condition, ReadHandler& handler)
0354       : base_from_cancellation_state<ReadHandler>(
0355           handler, enable_partial_cancellation()),
0356         base_from_completion_cond<CompletionCondition>(completion_condition),
0357         stream_(stream),
0358         buffers_(buffers),
0359         start_(0),
0360         handler_(static_cast<ReadHandler&&>(handler))
0361     {
0362     }
0363 
0364     read_op(const read_op& other)
0365       : base_from_cancellation_state<ReadHandler>(other),
0366         base_from_completion_cond<CompletionCondition>(other),
0367         stream_(other.stream_),
0368         buffers_(other.buffers_),
0369         start_(other.start_),
0370         handler_(other.handler_)
0371     {
0372     }
0373 
0374     read_op(read_op&& other)
0375       : base_from_cancellation_state<ReadHandler>(
0376           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0377         base_from_completion_cond<CompletionCondition>(
0378           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0379         stream_(other.stream_),
0380         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0381         start_(other.start_),
0382         handler_(static_cast<ReadHandler&&>(other.handler_))
0383     {
0384     }
0385 
0386     void operator()(boost::system::error_code ec,
0387         std::size_t bytes_transferred, int start = 0)
0388     {
0389       std::size_t max_size;
0390       switch (start_ = start)
0391       {
0392         case 1:
0393         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0394         for (;;)
0395         {
0396           {
0397             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0398             stream_.async_read_some(buffers_.prepare(max_size),
0399                 static_cast<read_op&&>(*this));
0400           }
0401           return; default:
0402           buffers_.consume(bytes_transferred);
0403           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0404             break;
0405           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0406           if (max_size == 0)
0407             break;
0408           if (this->cancelled() != cancellation_type::none)
0409           {
0410             ec = error::operation_aborted;
0411             break;
0412           }
0413         }
0414 
0415         static_cast<ReadHandler&&>(handler_)(
0416             static_cast<const boost::system::error_code&>(ec),
0417             static_cast<const std::size_t&>(buffers_.total_consumed()));
0418       }
0419     }
0420 
0421   //private:
0422     typedef boost::asio::detail::consuming_buffers<mutable_buffer,
0423         MutableBufferSequence, MutableBufferIterator> buffers_type;
0424 
0425     AsyncReadStream& stream_;
0426     buffers_type buffers_;
0427     int start_;
0428     ReadHandler handler_;
0429   };
0430 
0431   template <typename AsyncReadStream, typename MutableBufferSequence,
0432       typename MutableBufferIterator, typename CompletionCondition,
0433       typename ReadHandler>
0434   inline bool asio_handler_is_continuation(
0435       read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
0436         CompletionCondition, ReadHandler>* this_handler)
0437   {
0438     return this_handler->start_ == 0 ? true
0439       : boost_asio_handler_cont_helpers::is_continuation(
0440           this_handler->handler_);
0441   }
0442 
0443   template <typename AsyncReadStream, typename MutableBufferSequence,
0444       typename MutableBufferIterator, typename CompletionCondition,
0445       typename ReadHandler>
0446   inline void start_read_op(AsyncReadStream& stream,
0447       const MutableBufferSequence& buffers, const MutableBufferIterator&,
0448       CompletionCondition& completion_condition, ReadHandler& handler)
0449   {
0450     read_op<AsyncReadStream, MutableBufferSequence,
0451       MutableBufferIterator, CompletionCondition, ReadHandler>(
0452         stream, buffers, completion_condition, handler)(
0453           boost::system::error_code(), 0, 1);
0454   }
0455 
0456   template <typename AsyncReadStream>
0457   class initiate_async_read
0458   {
0459   public:
0460     typedef typename AsyncReadStream::executor_type executor_type;
0461 
0462     explicit initiate_async_read(AsyncReadStream& stream)
0463       : stream_(stream)
0464     {
0465     }
0466 
0467     executor_type get_executor() const noexcept
0468     {
0469       return stream_.get_executor();
0470     }
0471 
0472     template <typename ReadHandler, typename MutableBufferSequence,
0473         typename CompletionCondition>
0474     void operator()(ReadHandler&& handler,
0475         const MutableBufferSequence& buffers,
0476         CompletionCondition&& completion_cond) const
0477     {
0478       // If you get an error on the following line it means that your handler
0479       // does not meet the documented type requirements for a ReadHandler.
0480       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0481 
0482       non_const_lvalue<ReadHandler> handler2(handler);
0483       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0484       start_read_op(stream_, buffers,
0485           boost::asio::buffer_sequence_begin(buffers),
0486           completion_cond2.value, handler2.value);
0487     }
0488 
0489   private:
0490     AsyncReadStream& stream_;
0491   };
0492 } // namespace detail
0493 
0494 #if !defined(GENERATING_DOCUMENTATION)
0495 
0496 template <template <typename, typename> class Associator,
0497     typename AsyncReadStream, typename MutableBufferSequence,
0498     typename MutableBufferIterator, typename CompletionCondition,
0499     typename ReadHandler, typename DefaultCandidate>
0500 struct associator<Associator,
0501     detail::read_op<AsyncReadStream, MutableBufferSequence,
0502       MutableBufferIterator, CompletionCondition, ReadHandler>,
0503     DefaultCandidate>
0504   : Associator<ReadHandler, DefaultCandidate>
0505 {
0506   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0507       const detail::read_op<AsyncReadStream, MutableBufferSequence,
0508         MutableBufferIterator, CompletionCondition, ReadHandler>& h) noexcept
0509   {
0510     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0511   }
0512 
0513   static auto get(
0514       const detail::read_op<AsyncReadStream, MutableBufferSequence,
0515         MutableBufferIterator, CompletionCondition, ReadHandler>& h,
0516       const DefaultCandidate& c) noexcept
0517     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0518   {
0519     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0520   }
0521 };
0522 
0523 #endif // !defined(GENERATING_DOCUMENTATION)
0524 
0525 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0526 
0527 namespace detail
0528 {
0529   template <typename AsyncReadStream, typename DynamicBuffer_v1,
0530       typename CompletionCondition, typename ReadHandler>
0531   class read_dynbuf_v1_op
0532     : public base_from_cancellation_state<ReadHandler>,
0533       base_from_completion_cond<CompletionCondition>
0534   {
0535   public:
0536     template <typename BufferSequence>
0537     read_dynbuf_v1_op(AsyncReadStream& stream,
0538         BufferSequence&& buffers,
0539         CompletionCondition& completion_condition, ReadHandler& handler)
0540       : base_from_cancellation_state<ReadHandler>(
0541           handler, enable_partial_cancellation()),
0542         base_from_completion_cond<CompletionCondition>(completion_condition),
0543         stream_(stream),
0544         buffers_(static_cast<BufferSequence&&>(buffers)),
0545         start_(0),
0546         total_transferred_(0),
0547         handler_(static_cast<ReadHandler&&>(handler))
0548     {
0549     }
0550 
0551     read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
0552       : base_from_cancellation_state<ReadHandler>(other),
0553         base_from_completion_cond<CompletionCondition>(other),
0554         stream_(other.stream_),
0555         buffers_(other.buffers_),
0556         start_(other.start_),
0557         total_transferred_(other.total_transferred_),
0558         handler_(other.handler_)
0559     {
0560     }
0561 
0562     read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
0563       : base_from_cancellation_state<ReadHandler>(
0564           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0565         base_from_completion_cond<CompletionCondition>(
0566           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0567         stream_(other.stream_),
0568         buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
0569         start_(other.start_),
0570         total_transferred_(other.total_transferred_),
0571         handler_(static_cast<ReadHandler&&>(other.handler_))
0572     {
0573     }
0574 
0575     void operator()(boost::system::error_code ec,
0576         std::size_t bytes_transferred, int start = 0)
0577     {
0578       std::size_t max_size, bytes_available;
0579       switch (start_ = start)
0580       {
0581         case 1:
0582         max_size = this->check_for_completion(ec, total_transferred_);
0583         bytes_available = std::min<std::size_t>(
0584               std::max<std::size_t>(512,
0585                 buffers_.capacity() - buffers_.size()),
0586               std::min<std::size_t>(max_size,
0587                 buffers_.max_size() - buffers_.size()));
0588         for (;;)
0589         {
0590           {
0591             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0592             stream_.async_read_some(buffers_.prepare(bytes_available),
0593                 static_cast<read_dynbuf_v1_op&&>(*this));
0594           }
0595           return; default:
0596           total_transferred_ += bytes_transferred;
0597           buffers_.commit(bytes_transferred);
0598           max_size = this->check_for_completion(ec, total_transferred_);
0599           bytes_available = std::min<std::size_t>(
0600                 std::max<std::size_t>(512,
0601                   buffers_.capacity() - buffers_.size()),
0602                 std::min<std::size_t>(max_size,
0603                   buffers_.max_size() - buffers_.size()));
0604           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
0605             break;
0606           if (this->cancelled() != cancellation_type::none)
0607           {
0608             ec = error::operation_aborted;
0609             break;
0610           }
0611         }
0612 
0613         static_cast<ReadHandler&&>(handler_)(
0614             static_cast<const boost::system::error_code&>(ec),
0615             static_cast<const std::size_t&>(total_transferred_));
0616       }
0617     }
0618 
0619   //private:
0620     AsyncReadStream& stream_;
0621     DynamicBuffer_v1 buffers_;
0622     int start_;
0623     std::size_t total_transferred_;
0624     ReadHandler handler_;
0625   };
0626 
0627   template <typename AsyncReadStream, typename DynamicBuffer_v1,
0628       typename CompletionCondition, typename ReadHandler>
0629   inline bool asio_handler_is_continuation(
0630       read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
0631         CompletionCondition, ReadHandler>* this_handler)
0632   {
0633     return this_handler->start_ == 0 ? true
0634       : boost_asio_handler_cont_helpers::is_continuation(
0635           this_handler->handler_);
0636   }
0637 
0638   template <typename AsyncReadStream>
0639   class initiate_async_read_dynbuf_v1
0640   {
0641   public:
0642     typedef typename AsyncReadStream::executor_type executor_type;
0643 
0644     explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
0645       : stream_(stream)
0646     {
0647     }
0648 
0649     executor_type get_executor() const noexcept
0650     {
0651       return stream_.get_executor();
0652     }
0653 
0654     template <typename ReadHandler, typename DynamicBuffer_v1,
0655         typename CompletionCondition>
0656     void operator()(ReadHandler&& handler,
0657         DynamicBuffer_v1&& buffers,
0658         CompletionCondition&& completion_cond) const
0659     {
0660       // If you get an error on the following line it means that your handler
0661       // does not meet the documented type requirements for a ReadHandler.
0662       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0663 
0664       non_const_lvalue<ReadHandler> handler2(handler);
0665       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0666       read_dynbuf_v1_op<AsyncReadStream, decay_t<DynamicBuffer_v1>,
0667         CompletionCondition, decay_t<ReadHandler>>(
0668           stream_, static_cast<DynamicBuffer_v1&&>(buffers),
0669             completion_cond2.value, handler2.value)(
0670               boost::system::error_code(), 0, 1);
0671     }
0672 
0673   private:
0674     AsyncReadStream& stream_;
0675   };
0676 } // namespace detail
0677 
0678 #if !defined(GENERATING_DOCUMENTATION)
0679 
0680 template <template <typename, typename> class Associator,
0681     typename AsyncReadStream, typename DynamicBuffer_v1,
0682     typename CompletionCondition, typename ReadHandler,
0683     typename DefaultCandidate>
0684 struct associator<Associator,
0685     detail::read_dynbuf_v1_op<AsyncReadStream,
0686       DynamicBuffer_v1, CompletionCondition, ReadHandler>,
0687     DefaultCandidate>
0688   : Associator<ReadHandler, DefaultCandidate>
0689 {
0690   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0691       const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
0692         CompletionCondition, ReadHandler>& h) noexcept
0693   {
0694     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0695   }
0696 
0697   static auto get(
0698       const detail::read_dynbuf_v1_op<AsyncReadStream,
0699         DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
0700       const DefaultCandidate& c) noexcept
0701     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0702   {
0703     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0704   }
0705 };
0706 
0707 #endif // !defined(GENERATING_DOCUMENTATION)
0708 
0709 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0710 
0711 namespace detail
0712 {
0713   template <typename AsyncReadStream, typename DynamicBuffer_v2,
0714       typename CompletionCondition, typename ReadHandler>
0715   class read_dynbuf_v2_op
0716     : public base_from_cancellation_state<ReadHandler>,
0717       base_from_completion_cond<CompletionCondition>
0718   {
0719   public:
0720     template <typename BufferSequence>
0721     read_dynbuf_v2_op(AsyncReadStream& stream,
0722         BufferSequence&& buffers,
0723         CompletionCondition& completion_condition, ReadHandler& handler)
0724       : base_from_cancellation_state<ReadHandler>(
0725           handler, enable_partial_cancellation()),
0726         base_from_completion_cond<CompletionCondition>(completion_condition),
0727         stream_(stream),
0728         buffers_(static_cast<BufferSequence&&>(buffers)),
0729         start_(0),
0730         total_transferred_(0),
0731         bytes_available_(0),
0732         handler_(static_cast<ReadHandler&&>(handler))
0733     {
0734     }
0735 
0736     read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
0737       : base_from_cancellation_state<ReadHandler>(other),
0738         base_from_completion_cond<CompletionCondition>(other),
0739         stream_(other.stream_),
0740         buffers_(other.buffers_),
0741         start_(other.start_),
0742         total_transferred_(other.total_transferred_),
0743         bytes_available_(other.bytes_available_),
0744         handler_(other.handler_)
0745     {
0746     }
0747 
0748     read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
0749       : base_from_cancellation_state<ReadHandler>(
0750           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0751         base_from_completion_cond<CompletionCondition>(
0752           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0753         stream_(other.stream_),
0754         buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
0755         start_(other.start_),
0756         total_transferred_(other.total_transferred_),
0757         bytes_available_(other.bytes_available_),
0758         handler_(static_cast<ReadHandler&&>(other.handler_))
0759     {
0760     }
0761 
0762     void operator()(boost::system::error_code ec,
0763         std::size_t bytes_transferred, int start = 0)
0764     {
0765       std::size_t max_size, pos;
0766       switch (start_ = start)
0767       {
0768         case 1:
0769         max_size = this->check_for_completion(ec, total_transferred_);
0770         bytes_available_ = std::min<std::size_t>(
0771               std::max<std::size_t>(512,
0772                 buffers_.capacity() - buffers_.size()),
0773               std::min<std::size_t>(max_size,
0774                 buffers_.max_size() - buffers_.size()));
0775         for (;;)
0776         {
0777           pos = buffers_.size();
0778           buffers_.grow(bytes_available_);
0779           {
0780             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
0781             stream_.async_read_some(buffers_.data(pos, bytes_available_),
0782                 static_cast<read_dynbuf_v2_op&&>(*this));
0783           }
0784           return; default:
0785           total_transferred_ += bytes_transferred;
0786           buffers_.shrink(bytes_available_ - bytes_transferred);
0787           max_size = this->check_for_completion(ec, total_transferred_);
0788           bytes_available_ = std::min<std::size_t>(
0789                 std::max<std::size_t>(512,
0790                   buffers_.capacity() - buffers_.size()),
0791                 std::min<std::size_t>(max_size,
0792                   buffers_.max_size() - buffers_.size()));
0793           if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
0794             break;
0795           if (this->cancelled() != cancellation_type::none)
0796           {
0797             ec = error::operation_aborted;
0798             break;
0799           }
0800         }
0801 
0802         static_cast<ReadHandler&&>(handler_)(
0803             static_cast<const boost::system::error_code&>(ec),
0804             static_cast<const std::size_t&>(total_transferred_));
0805       }
0806     }
0807 
0808   //private:
0809     AsyncReadStream& stream_;
0810     DynamicBuffer_v2 buffers_;
0811     int start_;
0812     std::size_t total_transferred_;
0813     std::size_t bytes_available_;
0814     ReadHandler handler_;
0815   };
0816 
0817   template <typename AsyncReadStream, typename DynamicBuffer_v2,
0818       typename CompletionCondition, typename ReadHandler>
0819   inline bool asio_handler_is_continuation(
0820       read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
0821         CompletionCondition, ReadHandler>* this_handler)
0822   {
0823     return this_handler->start_ == 0 ? true
0824       : boost_asio_handler_cont_helpers::is_continuation(
0825           this_handler->handler_);
0826   }
0827 
0828   template <typename AsyncReadStream>
0829   class initiate_async_read_dynbuf_v2
0830   {
0831   public:
0832     typedef typename AsyncReadStream::executor_type executor_type;
0833 
0834     explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
0835       : stream_(stream)
0836     {
0837     }
0838 
0839     executor_type get_executor() const noexcept
0840     {
0841       return stream_.get_executor();
0842     }
0843 
0844     template <typename ReadHandler, typename DynamicBuffer_v2,
0845         typename CompletionCondition>
0846     void operator()(ReadHandler&& handler,
0847         DynamicBuffer_v2&& buffers,
0848         CompletionCondition&& completion_cond) const
0849     {
0850       // If you get an error on the following line it means that your handler
0851       // does not meet the documented type requirements for a ReadHandler.
0852       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0853 
0854       non_const_lvalue<ReadHandler> handler2(handler);
0855       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0856       read_dynbuf_v2_op<AsyncReadStream, decay_t<DynamicBuffer_v2>,
0857         CompletionCondition, decay_t<ReadHandler>>(
0858           stream_, static_cast<DynamicBuffer_v2&&>(buffers),
0859             completion_cond2.value, handler2.value)(
0860               boost::system::error_code(), 0, 1);
0861     }
0862 
0863   private:
0864     AsyncReadStream& stream_;
0865   };
0866 } // namespace detail
0867 
0868 #if !defined(GENERATING_DOCUMENTATION)
0869 
0870 template <template <typename, typename> class Associator,
0871     typename AsyncReadStream, typename DynamicBuffer_v2,
0872     typename CompletionCondition, typename ReadHandler,
0873     typename DefaultCandidate>
0874 struct associator<Associator,
0875     detail::read_dynbuf_v2_op<AsyncReadStream,
0876       DynamicBuffer_v2, CompletionCondition, ReadHandler>,
0877     DefaultCandidate>
0878   : Associator<ReadHandler, DefaultCandidate>
0879 {
0880   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0881       const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
0882         CompletionCondition, ReadHandler>& h) noexcept
0883   {
0884     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0885   }
0886 
0887   static auto get(
0888       const detail::read_dynbuf_v2_op<AsyncReadStream,
0889         DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
0890       const DefaultCandidate& c) noexcept
0891     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0892   {
0893     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0894   }
0895 };
0896 
0897 #endif // !defined(GENERATING_DOCUMENTATION)
0898 
0899 } // namespace asio
0900 } // namespace boost
0901 
0902 #include <boost/asio/detail/pop_options.hpp>
0903 
0904 #endif // BOOST_ASIO_IMPL_READ_HPP