File indexing completed on 2025-01-18 09:28:56
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 {
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
0241 #endif
0242 #endif
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
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
0455
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 }
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
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
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
0678
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 }
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
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
0816 #endif
0817 #endif
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
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
0959
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 }
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
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 }
1051 }
1052
1053 #include <boost/asio/detail/pop_options.hpp>
1054
1055 #endif