read.hpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. //
  2. // impl/read.hpp
  3. // ~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_IMPL_READ_HPP
  11. #define ASIO_IMPL_READ_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include "asio/associator.hpp"
  17. #include "asio/buffer.hpp"
  18. #include "asio/detail/array_fwd.hpp"
  19. #include "asio/detail/base_from_cancellation_state.hpp"
  20. #include "asio/detail/base_from_completion_cond.hpp"
  21. #include "asio/detail/bind_handler.hpp"
  22. #include "asio/detail/consuming_buffers.hpp"
  23. #include "asio/detail/dependent_type.hpp"
  24. #include "asio/detail/handler_cont_helpers.hpp"
  25. #include "asio/detail/handler_tracking.hpp"
  26. #include "asio/detail/handler_type_requirements.hpp"
  27. #include "asio/detail/non_const_lvalue.hpp"
  28. #include "asio/detail/throw_error.hpp"
  29. #include "asio/error.hpp"
  30. #include "asio/detail/push_options.hpp"
  31. namespace asio {
  32. namespace detail
  33. {
  34. template <typename SyncReadStream, typename MutableBufferSequence,
  35. typename MutableBufferIterator, typename CompletionCondition>
  36. std::size_t read_buffer_seq(SyncReadStream& s,
  37. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  38. CompletionCondition completion_condition, asio::error_code& ec)
  39. {
  40. ec = asio::error_code();
  41. asio::detail::consuming_buffers<mutable_buffer,
  42. MutableBufferSequence, MutableBufferIterator> tmp(buffers);
  43. while (!tmp.empty())
  44. {
  45. if (std::size_t max_size = detail::adapt_completion_condition_result(
  46. completion_condition(ec, tmp.total_consumed())))
  47. tmp.consume(s.read_some(tmp.prepare(max_size), ec));
  48. else
  49. break;
  50. }
  51. return tmp.total_consumed();
  52. }
  53. } // namespace detail
  54. template <typename SyncReadStream, typename MutableBufferSequence,
  55. typename CompletionCondition>
  56. std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  57. CompletionCondition completion_condition, asio::error_code& ec,
  58. constraint_t<
  59. is_mutable_buffer_sequence<MutableBufferSequence>::value
  60. >)
  61. {
  62. return detail::read_buffer_seq(s, buffers,
  63. asio::buffer_sequence_begin(buffers),
  64. static_cast<CompletionCondition&&>(completion_condition), ec);
  65. }
  66. template <typename SyncReadStream, typename MutableBufferSequence>
  67. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  68. constraint_t<
  69. is_mutable_buffer_sequence<MutableBufferSequence>::value
  70. >)
  71. {
  72. asio::error_code ec;
  73. std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
  74. asio::detail::throw_error(ec, "read");
  75. return bytes_transferred;
  76. }
  77. template <typename SyncReadStream, typename MutableBufferSequence>
  78. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  79. asio::error_code& ec,
  80. constraint_t<
  81. is_mutable_buffer_sequence<MutableBufferSequence>::value
  82. >)
  83. {
  84. return read(s, buffers, transfer_all(), ec);
  85. }
  86. template <typename SyncReadStream, typename MutableBufferSequence,
  87. typename CompletionCondition>
  88. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  89. CompletionCondition completion_condition,
  90. constraint_t<
  91. is_mutable_buffer_sequence<MutableBufferSequence>::value
  92. >)
  93. {
  94. asio::error_code ec;
  95. std::size_t bytes_transferred = read(s, buffers,
  96. static_cast<CompletionCondition&&>(completion_condition), ec);
  97. asio::detail::throw_error(ec, "read");
  98. return bytes_transferred;
  99. }
  100. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  101. template <typename SyncReadStream, typename DynamicBuffer_v1,
  102. typename CompletionCondition>
  103. std::size_t read(SyncReadStream& s,
  104. DynamicBuffer_v1&& buffers,
  105. CompletionCondition completion_condition, asio::error_code& ec,
  106. constraint_t<
  107. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  108. >,
  109. constraint_t<
  110. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  111. >)
  112. {
  113. decay_t<DynamicBuffer_v1> b(
  114. static_cast<DynamicBuffer_v1&&>(buffers));
  115. ec = asio::error_code();
  116. std::size_t total_transferred = 0;
  117. std::size_t max_size = detail::adapt_completion_condition_result(
  118. completion_condition(ec, total_transferred));
  119. std::size_t bytes_available = std::min<std::size_t>(
  120. std::max<std::size_t>(512, b.capacity() - b.size()),
  121. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  122. while (bytes_available > 0)
  123. {
  124. std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
  125. b.commit(bytes_transferred);
  126. total_transferred += bytes_transferred;
  127. max_size = detail::adapt_completion_condition_result(
  128. completion_condition(ec, total_transferred));
  129. bytes_available = std::min<std::size_t>(
  130. std::max<std::size_t>(512, b.capacity() - b.size()),
  131. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  132. }
  133. return total_transferred;
  134. }
  135. template <typename SyncReadStream, typename DynamicBuffer_v1>
  136. inline std::size_t read(SyncReadStream& s,
  137. DynamicBuffer_v1&& buffers,
  138. constraint_t<
  139. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  140. >,
  141. constraint_t<
  142. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  143. >)
  144. {
  145. asio::error_code ec;
  146. std::size_t bytes_transferred = read(s,
  147. static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec);
  148. asio::detail::throw_error(ec, "read");
  149. return bytes_transferred;
  150. }
  151. template <typename SyncReadStream, typename DynamicBuffer_v1>
  152. inline std::size_t read(SyncReadStream& s,
  153. DynamicBuffer_v1&& buffers,
  154. asio::error_code& ec,
  155. constraint_t<
  156. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  157. >,
  158. constraint_t<
  159. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  160. >)
  161. {
  162. return read(s, static_cast<DynamicBuffer_v1&&>(buffers),
  163. transfer_all(), ec);
  164. }
  165. template <typename SyncReadStream, typename DynamicBuffer_v1,
  166. typename CompletionCondition>
  167. inline std::size_t read(SyncReadStream& s,
  168. DynamicBuffer_v1&& buffers,
  169. CompletionCondition completion_condition,
  170. constraint_t<
  171. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  172. >,
  173. constraint_t<
  174. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  175. >)
  176. {
  177. asio::error_code ec;
  178. std::size_t bytes_transferred = read(s,
  179. static_cast<DynamicBuffer_v1&&>(buffers),
  180. static_cast<CompletionCondition&&>(completion_condition), ec);
  181. asio::detail::throw_error(ec, "read");
  182. return bytes_transferred;
  183. }
  184. #if !defined(ASIO_NO_EXTENSIONS)
  185. #if !defined(ASIO_NO_IOSTREAM)
  186. template <typename SyncReadStream, typename Allocator,
  187. typename CompletionCondition>
  188. inline std::size_t read(SyncReadStream& s,
  189. asio::basic_streambuf<Allocator>& b,
  190. CompletionCondition completion_condition, asio::error_code& ec)
  191. {
  192. return read(s, basic_streambuf_ref<Allocator>(b),
  193. static_cast<CompletionCondition&&>(completion_condition), ec);
  194. }
  195. template <typename SyncReadStream, typename Allocator>
  196. inline std::size_t read(SyncReadStream& s,
  197. asio::basic_streambuf<Allocator>& b)
  198. {
  199. return read(s, basic_streambuf_ref<Allocator>(b));
  200. }
  201. template <typename SyncReadStream, typename Allocator>
  202. inline std::size_t read(SyncReadStream& s,
  203. asio::basic_streambuf<Allocator>& b,
  204. asio::error_code& ec)
  205. {
  206. return read(s, basic_streambuf_ref<Allocator>(b), ec);
  207. }
  208. template <typename SyncReadStream, typename Allocator,
  209. typename CompletionCondition>
  210. inline std::size_t read(SyncReadStream& s,
  211. asio::basic_streambuf<Allocator>& b,
  212. CompletionCondition completion_condition)
  213. {
  214. return read(s, basic_streambuf_ref<Allocator>(b),
  215. static_cast<CompletionCondition&&>(completion_condition));
  216. }
  217. #endif // !defined(ASIO_NO_IOSTREAM)
  218. #endif // !defined(ASIO_NO_EXTENSIONS)
  219. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  220. template <typename SyncReadStream, typename DynamicBuffer_v2,
  221. typename CompletionCondition>
  222. std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  223. CompletionCondition completion_condition, asio::error_code& ec,
  224. constraint_t<
  225. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  226. >)
  227. {
  228. DynamicBuffer_v2& b = buffers;
  229. ec = asio::error_code();
  230. std::size_t total_transferred = 0;
  231. std::size_t max_size = detail::adapt_completion_condition_result(
  232. completion_condition(ec, total_transferred));
  233. std::size_t bytes_available = std::min<std::size_t>(
  234. std::max<std::size_t>(512, b.capacity() - b.size()),
  235. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  236. while (bytes_available > 0)
  237. {
  238. std::size_t pos = b.size();
  239. b.grow(bytes_available);
  240. std::size_t bytes_transferred = s.read_some(
  241. b.data(pos, bytes_available), ec);
  242. b.shrink(bytes_available - bytes_transferred);
  243. total_transferred += bytes_transferred;
  244. max_size = detail::adapt_completion_condition_result(
  245. completion_condition(ec, total_transferred));
  246. bytes_available = std::min<std::size_t>(
  247. std::max<std::size_t>(512, b.capacity() - b.size()),
  248. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  249. }
  250. return total_transferred;
  251. }
  252. template <typename SyncReadStream, typename DynamicBuffer_v2>
  253. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  254. constraint_t<
  255. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  256. >)
  257. {
  258. asio::error_code ec;
  259. std::size_t bytes_transferred = read(s,
  260. static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec);
  261. asio::detail::throw_error(ec, "read");
  262. return bytes_transferred;
  263. }
  264. template <typename SyncReadStream, typename DynamicBuffer_v2>
  265. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  266. asio::error_code& ec,
  267. constraint_t<
  268. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  269. >)
  270. {
  271. return read(s, static_cast<DynamicBuffer_v2&&>(buffers),
  272. transfer_all(), ec);
  273. }
  274. template <typename SyncReadStream, typename DynamicBuffer_v2,
  275. typename CompletionCondition>
  276. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  277. CompletionCondition completion_condition,
  278. constraint_t<
  279. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  280. >)
  281. {
  282. asio::error_code ec;
  283. std::size_t bytes_transferred = read(s,
  284. static_cast<DynamicBuffer_v2&&>(buffers),
  285. static_cast<CompletionCondition&&>(completion_condition), ec);
  286. asio::detail::throw_error(ec, "read");
  287. return bytes_transferred;
  288. }
  289. namespace detail
  290. {
  291. template <typename AsyncReadStream, typename MutableBufferSequence,
  292. typename MutableBufferIterator, typename CompletionCondition,
  293. typename ReadHandler>
  294. class read_op
  295. : public base_from_cancellation_state<ReadHandler>,
  296. base_from_completion_cond<CompletionCondition>
  297. {
  298. public:
  299. read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
  300. CompletionCondition& completion_condition, ReadHandler& handler)
  301. : base_from_cancellation_state<ReadHandler>(
  302. handler, enable_partial_cancellation()),
  303. base_from_completion_cond<CompletionCondition>(completion_condition),
  304. stream_(stream),
  305. buffers_(buffers),
  306. start_(0),
  307. handler_(static_cast<ReadHandler&&>(handler))
  308. {
  309. }
  310. read_op(const read_op& other)
  311. : base_from_cancellation_state<ReadHandler>(other),
  312. base_from_completion_cond<CompletionCondition>(other),
  313. stream_(other.stream_),
  314. buffers_(other.buffers_),
  315. start_(other.start_),
  316. handler_(other.handler_)
  317. {
  318. }
  319. read_op(read_op&& other)
  320. : base_from_cancellation_state<ReadHandler>(
  321. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  322. base_from_completion_cond<CompletionCondition>(
  323. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  324. stream_(other.stream_),
  325. buffers_(static_cast<buffers_type&&>(other.buffers_)),
  326. start_(other.start_),
  327. handler_(static_cast<ReadHandler&&>(other.handler_))
  328. {
  329. }
  330. void operator()(asio::error_code ec,
  331. std::size_t bytes_transferred, int start = 0)
  332. {
  333. std::size_t max_size;
  334. switch (start_ = start)
  335. {
  336. case 1:
  337. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  338. for (;;)
  339. {
  340. {
  341. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
  342. stream_.async_read_some(buffers_.prepare(max_size),
  343. static_cast<read_op&&>(*this));
  344. }
  345. return; default:
  346. buffers_.consume(bytes_transferred);
  347. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  348. break;
  349. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  350. if (max_size == 0)
  351. break;
  352. if (this->cancelled() != cancellation_type::none)
  353. {
  354. ec = error::operation_aborted;
  355. break;
  356. }
  357. }
  358. static_cast<ReadHandler&&>(handler_)(
  359. static_cast<const asio::error_code&>(ec),
  360. static_cast<const std::size_t&>(buffers_.total_consumed()));
  361. }
  362. }
  363. //private:
  364. typedef asio::detail::consuming_buffers<mutable_buffer,
  365. MutableBufferSequence, MutableBufferIterator> buffers_type;
  366. AsyncReadStream& stream_;
  367. buffers_type buffers_;
  368. int start_;
  369. ReadHandler handler_;
  370. };
  371. template <typename AsyncReadStream, typename MutableBufferSequence,
  372. typename MutableBufferIterator, typename CompletionCondition,
  373. typename ReadHandler>
  374. inline bool asio_handler_is_continuation(
  375. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  376. CompletionCondition, ReadHandler>* this_handler)
  377. {
  378. return this_handler->start_ == 0 ? true
  379. : asio_handler_cont_helpers::is_continuation(
  380. this_handler->handler_);
  381. }
  382. template <typename AsyncReadStream, typename MutableBufferSequence,
  383. typename MutableBufferIterator, typename CompletionCondition,
  384. typename ReadHandler>
  385. inline void start_read_op(AsyncReadStream& stream,
  386. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  387. CompletionCondition& completion_condition, ReadHandler& handler)
  388. {
  389. read_op<AsyncReadStream, MutableBufferSequence,
  390. MutableBufferIterator, CompletionCondition, ReadHandler>(
  391. stream, buffers, completion_condition, handler)(
  392. asio::error_code(), 0, 1);
  393. }
  394. template <typename AsyncReadStream>
  395. class initiate_async_read
  396. {
  397. public:
  398. typedef typename AsyncReadStream::executor_type executor_type;
  399. explicit initiate_async_read(AsyncReadStream& stream)
  400. : stream_(stream)
  401. {
  402. }
  403. executor_type get_executor() const noexcept
  404. {
  405. return stream_.get_executor();
  406. }
  407. template <typename ReadHandler, typename MutableBufferSequence,
  408. typename CompletionCondition>
  409. void operator()(ReadHandler&& handler,
  410. const MutableBufferSequence& buffers,
  411. CompletionCondition&& completion_cond) const
  412. {
  413. // If you get an error on the following line it means that your handler
  414. // does not meet the documented type requirements for a ReadHandler.
  415. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  416. non_const_lvalue<ReadHandler> handler2(handler);
  417. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  418. start_read_op(stream_, buffers,
  419. asio::buffer_sequence_begin(buffers),
  420. completion_cond2.value, handler2.value);
  421. }
  422. private:
  423. AsyncReadStream& stream_;
  424. };
  425. } // namespace detail
  426. #if !defined(GENERATING_DOCUMENTATION)
  427. template <template <typename, typename> class Associator,
  428. typename AsyncReadStream, typename MutableBufferSequence,
  429. typename MutableBufferIterator, typename CompletionCondition,
  430. typename ReadHandler, typename DefaultCandidate>
  431. struct associator<Associator,
  432. detail::read_op<AsyncReadStream, MutableBufferSequence,
  433. MutableBufferIterator, CompletionCondition, ReadHandler>,
  434. DefaultCandidate>
  435. : Associator<ReadHandler, DefaultCandidate>
  436. {
  437. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  438. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  439. MutableBufferIterator, CompletionCondition, ReadHandler>& h) noexcept
  440. {
  441. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  442. }
  443. static auto get(
  444. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  445. MutableBufferIterator, CompletionCondition, ReadHandler>& h,
  446. const DefaultCandidate& c) noexcept
  447. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  448. {
  449. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  450. }
  451. };
  452. #endif // !defined(GENERATING_DOCUMENTATION)
  453. template <typename AsyncReadStream,
  454. typename MutableBufferSequence, typename CompletionCondition,
  455. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  456. std::size_t)) ReadToken>
  457. inline auto async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  458. CompletionCondition completion_condition, ReadToken&& token,
  459. constraint_t<
  460. is_mutable_buffer_sequence<MutableBufferSequence>::value
  461. >)
  462. -> decltype(
  463. async_initiate<ReadToken,
  464. void (asio::error_code, std::size_t)>(
  465. declval<detail::initiate_async_read<AsyncReadStream>>(), token, buffers,
  466. static_cast<CompletionCondition&&>(completion_condition)))
  467. {
  468. return async_initiate<ReadToken,
  469. void (asio::error_code, std::size_t)>(
  470. detail::initiate_async_read<AsyncReadStream>(s), token, buffers,
  471. static_cast<CompletionCondition&&>(completion_condition));
  472. }
  473. template <typename AsyncReadStream, typename MutableBufferSequence,
  474. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  475. std::size_t)) ReadToken>
  476. inline auto async_read(AsyncReadStream& s,
  477. const MutableBufferSequence& buffers, ReadToken&& token,
  478. constraint_t<
  479. is_mutable_buffer_sequence<MutableBufferSequence>::value
  480. >)
  481. -> decltype(
  482. async_initiate<ReadToken,
  483. void (asio::error_code, std::size_t)>(
  484. declval<detail::initiate_async_read<AsyncReadStream>>(),
  485. token, buffers, transfer_all()))
  486. {
  487. return async_initiate<ReadToken,
  488. void (asio::error_code, std::size_t)>(
  489. detail::initiate_async_read<AsyncReadStream>(s),
  490. token, buffers, transfer_all());
  491. }
  492. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  493. namespace detail
  494. {
  495. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  496. typename CompletionCondition, typename ReadHandler>
  497. class read_dynbuf_v1_op
  498. : public base_from_cancellation_state<ReadHandler>,
  499. base_from_completion_cond<CompletionCondition>
  500. {
  501. public:
  502. template <typename BufferSequence>
  503. read_dynbuf_v1_op(AsyncReadStream& stream,
  504. BufferSequence&& buffers,
  505. CompletionCondition& completion_condition, ReadHandler& handler)
  506. : base_from_cancellation_state<ReadHandler>(
  507. handler, enable_partial_cancellation()),
  508. base_from_completion_cond<CompletionCondition>(completion_condition),
  509. stream_(stream),
  510. buffers_(static_cast<BufferSequence&&>(buffers)),
  511. start_(0),
  512. total_transferred_(0),
  513. handler_(static_cast<ReadHandler&&>(handler))
  514. {
  515. }
  516. read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
  517. : base_from_cancellation_state<ReadHandler>(other),
  518. base_from_completion_cond<CompletionCondition>(other),
  519. stream_(other.stream_),
  520. buffers_(other.buffers_),
  521. start_(other.start_),
  522. total_transferred_(other.total_transferred_),
  523. handler_(other.handler_)
  524. {
  525. }
  526. read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
  527. : base_from_cancellation_state<ReadHandler>(
  528. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  529. base_from_completion_cond<CompletionCondition>(
  530. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  531. stream_(other.stream_),
  532. buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
  533. start_(other.start_),
  534. total_transferred_(other.total_transferred_),
  535. handler_(static_cast<ReadHandler&&>(other.handler_))
  536. {
  537. }
  538. void operator()(asio::error_code ec,
  539. std::size_t bytes_transferred, int start = 0)
  540. {
  541. std::size_t max_size, bytes_available;
  542. switch (start_ = start)
  543. {
  544. case 1:
  545. max_size = this->check_for_completion(ec, total_transferred_);
  546. bytes_available = std::min<std::size_t>(
  547. std::max<std::size_t>(512,
  548. buffers_.capacity() - buffers_.size()),
  549. std::min<std::size_t>(max_size,
  550. buffers_.max_size() - buffers_.size()));
  551. for (;;)
  552. {
  553. {
  554. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
  555. stream_.async_read_some(buffers_.prepare(bytes_available),
  556. static_cast<read_dynbuf_v1_op&&>(*this));
  557. }
  558. return; default:
  559. total_transferred_ += bytes_transferred;
  560. buffers_.commit(bytes_transferred);
  561. max_size = this->check_for_completion(ec, total_transferred_);
  562. bytes_available = std::min<std::size_t>(
  563. std::max<std::size_t>(512,
  564. buffers_.capacity() - buffers_.size()),
  565. std::min<std::size_t>(max_size,
  566. buffers_.max_size() - buffers_.size()));
  567. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  568. break;
  569. if (this->cancelled() != cancellation_type::none)
  570. {
  571. ec = error::operation_aborted;
  572. break;
  573. }
  574. }
  575. static_cast<ReadHandler&&>(handler_)(
  576. static_cast<const asio::error_code&>(ec),
  577. static_cast<const std::size_t&>(total_transferred_));
  578. }
  579. }
  580. //private:
  581. AsyncReadStream& stream_;
  582. DynamicBuffer_v1 buffers_;
  583. int start_;
  584. std::size_t total_transferred_;
  585. ReadHandler handler_;
  586. };
  587. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  588. typename CompletionCondition, typename ReadHandler>
  589. inline bool asio_handler_is_continuation(
  590. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  591. CompletionCondition, ReadHandler>* this_handler)
  592. {
  593. return this_handler->start_ == 0 ? true
  594. : asio_handler_cont_helpers::is_continuation(
  595. this_handler->handler_);
  596. }
  597. template <typename AsyncReadStream>
  598. class initiate_async_read_dynbuf_v1
  599. {
  600. public:
  601. typedef typename AsyncReadStream::executor_type executor_type;
  602. explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)
  603. : stream_(stream)
  604. {
  605. }
  606. executor_type get_executor() const noexcept
  607. {
  608. return stream_.get_executor();
  609. }
  610. template <typename ReadHandler, typename DynamicBuffer_v1,
  611. typename CompletionCondition>
  612. void operator()(ReadHandler&& handler,
  613. DynamicBuffer_v1&& buffers,
  614. CompletionCondition&& completion_cond) const
  615. {
  616. // If you get an error on the following line it means that your handler
  617. // does not meet the documented type requirements for a ReadHandler.
  618. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  619. non_const_lvalue<ReadHandler> handler2(handler);
  620. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  621. read_dynbuf_v1_op<AsyncReadStream, decay_t<DynamicBuffer_v1>,
  622. CompletionCondition, decay_t<ReadHandler>>(
  623. stream_, static_cast<DynamicBuffer_v1&&>(buffers),
  624. completion_cond2.value, handler2.value)(
  625. asio::error_code(), 0, 1);
  626. }
  627. private:
  628. AsyncReadStream& stream_;
  629. };
  630. } // namespace detail
  631. #if !defined(GENERATING_DOCUMENTATION)
  632. template <template <typename, typename> class Associator,
  633. typename AsyncReadStream, typename DynamicBuffer_v1,
  634. typename CompletionCondition, typename ReadHandler,
  635. typename DefaultCandidate>
  636. struct associator<Associator,
  637. detail::read_dynbuf_v1_op<AsyncReadStream,
  638. DynamicBuffer_v1, CompletionCondition, ReadHandler>,
  639. DefaultCandidate>
  640. : Associator<ReadHandler, DefaultCandidate>
  641. {
  642. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  643. const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  644. CompletionCondition, ReadHandler>& h) noexcept
  645. {
  646. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  647. }
  648. static auto get(
  649. const detail::read_dynbuf_v1_op<AsyncReadStream,
  650. DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
  651. const DefaultCandidate& c) noexcept
  652. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  653. {
  654. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  655. }
  656. };
  657. #endif // !defined(GENERATING_DOCUMENTATION)
  658. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  659. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  660. std::size_t)) ReadToken>
  661. inline auto async_read(AsyncReadStream& s,
  662. DynamicBuffer_v1&& buffers, ReadToken&& token,
  663. constraint_t<
  664. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  665. >,
  666. constraint_t<
  667. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  668. >)
  669. -> decltype(
  670. async_initiate<ReadToken,
  671. void (asio::error_code, std::size_t)>(
  672. declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
  673. token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all()))
  674. {
  675. return async_initiate<ReadToken,
  676. void (asio::error_code, std::size_t)>(
  677. detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
  678. token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all());
  679. }
  680. template <typename AsyncReadStream,
  681. typename DynamicBuffer_v1, typename CompletionCondition,
  682. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  683. std::size_t)) ReadToken>
  684. inline auto async_read(AsyncReadStream& s, DynamicBuffer_v1&& buffers,
  685. CompletionCondition completion_condition, ReadToken&& token,
  686. constraint_t<
  687. is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
  688. >,
  689. constraint_t<
  690. !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
  691. >)
  692. -> decltype(
  693. async_initiate<ReadToken,
  694. void (asio::error_code, std::size_t)>(
  695. declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
  696. token, static_cast<DynamicBuffer_v1&&>(buffers),
  697. static_cast<CompletionCondition&&>(completion_condition)))
  698. {
  699. return async_initiate<ReadToken,
  700. void (asio::error_code, std::size_t)>(
  701. detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
  702. token, static_cast<DynamicBuffer_v1&&>(buffers),
  703. static_cast<CompletionCondition&&>(completion_condition));
  704. }
  705. #if !defined(ASIO_NO_EXTENSIONS)
  706. #if !defined(ASIO_NO_IOSTREAM)
  707. template <typename AsyncReadStream, typename Allocator,
  708. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  709. std::size_t)) ReadToken>
  710. inline auto async_read(AsyncReadStream& s,
  711. basic_streambuf<Allocator>& b, ReadToken&& token)
  712. -> decltype(
  713. async_initiate<ReadToken,
  714. void (asio::error_code, std::size_t)>(
  715. declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
  716. token, basic_streambuf_ref<Allocator>(b), transfer_all()))
  717. {
  718. return async_initiate<ReadToken,
  719. void (asio::error_code, std::size_t)>(
  720. detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
  721. token, basic_streambuf_ref<Allocator>(b), transfer_all());
  722. }
  723. template <typename AsyncReadStream,
  724. typename Allocator, typename CompletionCondition,
  725. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  726. std::size_t)) ReadToken>
  727. inline auto async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
  728. CompletionCondition completion_condition, ReadToken&& token)
  729. -> decltype(
  730. async_initiate<ReadToken,
  731. void (asio::error_code, std::size_t)>(
  732. declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(),
  733. token, basic_streambuf_ref<Allocator>(b),
  734. static_cast<CompletionCondition&&>(completion_condition)))
  735. {
  736. return async_initiate<ReadToken,
  737. void (asio::error_code, std::size_t)>(
  738. detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),
  739. token, basic_streambuf_ref<Allocator>(b),
  740. static_cast<CompletionCondition&&>(completion_condition));
  741. }
  742. #endif // !defined(ASIO_NO_IOSTREAM)
  743. #endif // !defined(ASIO_NO_EXTENSIONS)
  744. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  745. namespace detail
  746. {
  747. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  748. typename CompletionCondition, typename ReadHandler>
  749. class read_dynbuf_v2_op
  750. : public base_from_cancellation_state<ReadHandler>,
  751. base_from_completion_cond<CompletionCondition>
  752. {
  753. public:
  754. template <typename BufferSequence>
  755. read_dynbuf_v2_op(AsyncReadStream& stream,
  756. BufferSequence&& buffers,
  757. CompletionCondition& completion_condition, ReadHandler& handler)
  758. : base_from_cancellation_state<ReadHandler>(
  759. handler, enable_partial_cancellation()),
  760. base_from_completion_cond<CompletionCondition>(completion_condition),
  761. stream_(stream),
  762. buffers_(static_cast<BufferSequence&&>(buffers)),
  763. start_(0),
  764. total_transferred_(0),
  765. bytes_available_(0),
  766. handler_(static_cast<ReadHandler&&>(handler))
  767. {
  768. }
  769. read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
  770. : base_from_cancellation_state<ReadHandler>(other),
  771. base_from_completion_cond<CompletionCondition>(other),
  772. stream_(other.stream_),
  773. buffers_(other.buffers_),
  774. start_(other.start_),
  775. total_transferred_(other.total_transferred_),
  776. bytes_available_(other.bytes_available_),
  777. handler_(other.handler_)
  778. {
  779. }
  780. read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
  781. : base_from_cancellation_state<ReadHandler>(
  782. static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
  783. base_from_completion_cond<CompletionCondition>(
  784. static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
  785. stream_(other.stream_),
  786. buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
  787. start_(other.start_),
  788. total_transferred_(other.total_transferred_),
  789. bytes_available_(other.bytes_available_),
  790. handler_(static_cast<ReadHandler&&>(other.handler_))
  791. {
  792. }
  793. void operator()(asio::error_code ec,
  794. std::size_t bytes_transferred, int start = 0)
  795. {
  796. std::size_t max_size, pos;
  797. switch (start_ = start)
  798. {
  799. case 1:
  800. max_size = this->check_for_completion(ec, total_transferred_);
  801. bytes_available_ = std::min<std::size_t>(
  802. std::max<std::size_t>(512,
  803. buffers_.capacity() - buffers_.size()),
  804. std::min<std::size_t>(max_size,
  805. buffers_.max_size() - buffers_.size()));
  806. for (;;)
  807. {
  808. pos = buffers_.size();
  809. buffers_.grow(bytes_available_);
  810. {
  811. ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));
  812. stream_.async_read_some(buffers_.data(pos, bytes_available_),
  813. static_cast<read_dynbuf_v2_op&&>(*this));
  814. }
  815. return; default:
  816. total_transferred_ += bytes_transferred;
  817. buffers_.shrink(bytes_available_ - bytes_transferred);
  818. max_size = this->check_for_completion(ec, total_transferred_);
  819. bytes_available_ = std::min<std::size_t>(
  820. std::max<std::size_t>(512,
  821. buffers_.capacity() - buffers_.size()),
  822. std::min<std::size_t>(max_size,
  823. buffers_.max_size() - buffers_.size()));
  824. if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
  825. break;
  826. if (this->cancelled() != cancellation_type::none)
  827. {
  828. ec = error::operation_aborted;
  829. break;
  830. }
  831. }
  832. static_cast<ReadHandler&&>(handler_)(
  833. static_cast<const asio::error_code&>(ec),
  834. static_cast<const std::size_t&>(total_transferred_));
  835. }
  836. }
  837. //private:
  838. AsyncReadStream& stream_;
  839. DynamicBuffer_v2 buffers_;
  840. int start_;
  841. std::size_t total_transferred_;
  842. std::size_t bytes_available_;
  843. ReadHandler handler_;
  844. };
  845. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  846. typename CompletionCondition, typename ReadHandler>
  847. inline bool asio_handler_is_continuation(
  848. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  849. CompletionCondition, ReadHandler>* this_handler)
  850. {
  851. return this_handler->start_ == 0 ? true
  852. : asio_handler_cont_helpers::is_continuation(
  853. this_handler->handler_);
  854. }
  855. template <typename AsyncReadStream>
  856. class initiate_async_read_dynbuf_v2
  857. {
  858. public:
  859. typedef typename AsyncReadStream::executor_type executor_type;
  860. explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)
  861. : stream_(stream)
  862. {
  863. }
  864. executor_type get_executor() const noexcept
  865. {
  866. return stream_.get_executor();
  867. }
  868. template <typename ReadHandler, typename DynamicBuffer_v2,
  869. typename CompletionCondition>
  870. void operator()(ReadHandler&& handler,
  871. DynamicBuffer_v2&& buffers,
  872. CompletionCondition&& completion_cond) const
  873. {
  874. // If you get an error on the following line it means that your handler
  875. // does not meet the documented type requirements for a ReadHandler.
  876. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  877. non_const_lvalue<ReadHandler> handler2(handler);
  878. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  879. read_dynbuf_v2_op<AsyncReadStream, decay_t<DynamicBuffer_v2>,
  880. CompletionCondition, decay_t<ReadHandler>>(
  881. stream_, static_cast<DynamicBuffer_v2&&>(buffers),
  882. completion_cond2.value, handler2.value)(
  883. asio::error_code(), 0, 1);
  884. }
  885. private:
  886. AsyncReadStream& stream_;
  887. };
  888. } // namespace detail
  889. #if !defined(GENERATING_DOCUMENTATION)
  890. template <template <typename, typename> class Associator,
  891. typename AsyncReadStream, typename DynamicBuffer_v2,
  892. typename CompletionCondition, typename ReadHandler,
  893. typename DefaultCandidate>
  894. struct associator<Associator,
  895. detail::read_dynbuf_v2_op<AsyncReadStream,
  896. DynamicBuffer_v2, CompletionCondition, ReadHandler>,
  897. DefaultCandidate>
  898. : Associator<ReadHandler, DefaultCandidate>
  899. {
  900. static typename Associator<ReadHandler, DefaultCandidate>::type get(
  901. const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  902. CompletionCondition, ReadHandler>& h) noexcept
  903. {
  904. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  905. }
  906. static auto get(
  907. const detail::read_dynbuf_v2_op<AsyncReadStream,
  908. DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
  909. const DefaultCandidate& c) noexcept
  910. -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
  911. {
  912. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  913. }
  914. };
  915. #endif // !defined(GENERATING_DOCUMENTATION)
  916. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  917. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  918. std::size_t)) ReadToken>
  919. inline auto async_read(AsyncReadStream& s,
  920. DynamicBuffer_v2 buffers, ReadToken&& token,
  921. constraint_t<
  922. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  923. >)
  924. -> decltype(
  925. async_initiate<ReadToken,
  926. void (asio::error_code, std::size_t)>(
  927. declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(),
  928. token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all()))
  929. {
  930. return async_initiate<ReadToken,
  931. void (asio::error_code, std::size_t)>(
  932. detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
  933. token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all());
  934. }
  935. template <typename AsyncReadStream,
  936. typename DynamicBuffer_v2, typename CompletionCondition,
  937. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,
  938. std::size_t)) ReadToken>
  939. inline auto async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  940. CompletionCondition completion_condition, ReadToken&& token,
  941. constraint_t<
  942. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  943. >)
  944. -> decltype(
  945. async_initiate<ReadToken,
  946. void (asio::error_code, std::size_t)>(
  947. declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(),
  948. token, static_cast<DynamicBuffer_v2&&>(buffers),
  949. static_cast<CompletionCondition&&>(completion_condition)))
  950. {
  951. return async_initiate<ReadToken,
  952. void (asio::error_code, std::size_t)>(
  953. detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),
  954. token, static_cast<DynamicBuffer_v2&&>(buffers),
  955. static_cast<CompletionCondition&&>(completion_condition));
  956. }
  957. } // namespace asio
  958. #include "asio/detail/pop_options.hpp"
  959. #endif // ASIO_IMPL_READ_HPP