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
0003
0004
0005
0006
0007
0008
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
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 }
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
0259 #endif
0260 #endif
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
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
0479
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 }
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
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
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
0661
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 }
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
0708
0709 #endif
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
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
0851
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 }
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
0898
0899 }
0900 }
0901
0902 #include <boost/asio/detail/pop_options.hpp>
0903
0904 #endif