read.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. //
  2. // impl/read.hpp
  3. // ~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 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/buffer.hpp"
  17. #include "asio/completion_condition.hpp"
  18. #include "asio/detail/array_fwd.hpp"
  19. #include "asio/detail/base_from_completion_cond.hpp"
  20. #include "asio/detail/bind_handler.hpp"
  21. #include "asio/detail/consuming_buffers.hpp"
  22. #include "asio/detail/dependent_type.hpp"
  23. #include "asio/detail/handler_alloc_helpers.hpp"
  24. #include "asio/detail/handler_cont_helpers.hpp"
  25. #include "asio/detail/handler_invoke_helpers.hpp"
  26. #include "asio/detail/handler_type_requirements.hpp"
  27. #include "asio/detail/throw_error.hpp"
  28. #include "asio/error.hpp"
  29. #include "asio/detail/push_options.hpp"
  30. namespace asio {
  31. template <typename SyncReadStream, typename MutableBufferSequence,
  32. typename CompletionCondition>
  33. std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  34. CompletionCondition completion_condition, asio::error_code& ec)
  35. {
  36. ec = asio::error_code();
  37. asio::detail::consuming_buffers<
  38. mutable_buffer, MutableBufferSequence> tmp(buffers);
  39. std::size_t total_transferred = 0;
  40. tmp.prepare(detail::adapt_completion_condition_result(
  41. completion_condition(ec, total_transferred)));
  42. while (tmp.begin() != tmp.end())
  43. {
  44. std::size_t bytes_transferred = s.read_some(tmp, ec);
  45. tmp.consume(bytes_transferred);
  46. total_transferred += bytes_transferred;
  47. tmp.prepare(detail::adapt_completion_condition_result(
  48. completion_condition(ec, total_transferred)));
  49. }
  50. return total_transferred;
  51. }
  52. template <typename SyncReadStream, typename MutableBufferSequence>
  53. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
  54. {
  55. asio::error_code ec;
  56. std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
  57. asio::detail::throw_error(ec, "read");
  58. return bytes_transferred;
  59. }
  60. template <typename SyncReadStream, typename MutableBufferSequence>
  61. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  62. asio::error_code& ec)
  63. {
  64. return read(s, buffers, transfer_all(), ec);
  65. }
  66. template <typename SyncReadStream, typename MutableBufferSequence,
  67. typename CompletionCondition>
  68. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  69. CompletionCondition completion_condition)
  70. {
  71. asio::error_code ec;
  72. std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
  73. asio::detail::throw_error(ec, "read");
  74. return bytes_transferred;
  75. }
  76. #if !defined(ASIO_NO_IOSTREAM)
  77. template <typename SyncReadStream, typename Allocator,
  78. typename CompletionCondition>
  79. std::size_t read(SyncReadStream& s,
  80. asio::basic_streambuf<Allocator>& b,
  81. CompletionCondition completion_condition, asio::error_code& ec)
  82. {
  83. ec = asio::error_code();
  84. std::size_t total_transferred = 0;
  85. std::size_t max_size = detail::adapt_completion_condition_result(
  86. completion_condition(ec, total_transferred));
  87. std::size_t bytes_available = read_size_helper(b, max_size);
  88. while (bytes_available > 0)
  89. {
  90. std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
  91. b.commit(bytes_transferred);
  92. total_transferred += bytes_transferred;
  93. max_size = detail::adapt_completion_condition_result(
  94. completion_condition(ec, total_transferred));
  95. bytes_available = read_size_helper(b, max_size);
  96. }
  97. return total_transferred;
  98. }
  99. template <typename SyncReadStream, typename Allocator>
  100. inline std::size_t read(SyncReadStream& s,
  101. asio::basic_streambuf<Allocator>& b)
  102. {
  103. asio::error_code ec;
  104. std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
  105. asio::detail::throw_error(ec, "read");
  106. return bytes_transferred;
  107. }
  108. template <typename SyncReadStream, typename Allocator>
  109. inline std::size_t read(SyncReadStream& s,
  110. asio::basic_streambuf<Allocator>& b,
  111. asio::error_code& ec)
  112. {
  113. return read(s, b, transfer_all(), ec);
  114. }
  115. template <typename SyncReadStream, typename Allocator,
  116. typename CompletionCondition>
  117. inline std::size_t read(SyncReadStream& s,
  118. asio::basic_streambuf<Allocator>& b,
  119. CompletionCondition completion_condition)
  120. {
  121. asio::error_code ec;
  122. std::size_t bytes_transferred = read(s, b, completion_condition, ec);
  123. asio::detail::throw_error(ec, "read");
  124. return bytes_transferred;
  125. }
  126. #endif // !defined(ASIO_NO_IOSTREAM)
  127. namespace detail
  128. {
  129. template <typename AsyncReadStream, typename MutableBufferSequence,
  130. typename CompletionCondition, typename ReadHandler>
  131. class read_op
  132. : detail::base_from_completion_cond<CompletionCondition>
  133. {
  134. public:
  135. read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
  136. CompletionCondition completion_condition, ReadHandler& handler)
  137. : detail::base_from_completion_cond<
  138. CompletionCondition>(completion_condition),
  139. stream_(stream),
  140. buffers_(buffers),
  141. start_(0),
  142. total_transferred_(0),
  143. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  144. {
  145. }
  146. #if defined(ASIO_HAS_MOVE)
  147. read_op(const read_op& other)
  148. : detail::base_from_completion_cond<CompletionCondition>(other),
  149. stream_(other.stream_),
  150. buffers_(other.buffers_),
  151. start_(other.start_),
  152. total_transferred_(other.total_transferred_),
  153. handler_(other.handler_)
  154. {
  155. }
  156. read_op(read_op&& other)
  157. : detail::base_from_completion_cond<CompletionCondition>(other),
  158. stream_(other.stream_),
  159. buffers_(other.buffers_),
  160. start_(other.start_),
  161. total_transferred_(other.total_transferred_),
  162. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  163. {
  164. }
  165. #endif // defined(ASIO_HAS_MOVE)
  166. void operator()(const asio::error_code& ec,
  167. std::size_t bytes_transferred, int start = 0)
  168. {
  169. switch (start_ = start)
  170. {
  171. case 1:
  172. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  173. for (;;)
  174. {
  175. stream_.async_read_some(buffers_,
  176. ASIO_MOVE_CAST(read_op)(*this));
  177. return; default:
  178. total_transferred_ += bytes_transferred;
  179. buffers_.consume(bytes_transferred);
  180. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  181. if ((!ec && bytes_transferred == 0)
  182. || buffers_.begin() == buffers_.end())
  183. break;
  184. }
  185. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  186. }
  187. }
  188. //private:
  189. AsyncReadStream& stream_;
  190. asio::detail::consuming_buffers<
  191. mutable_buffer, MutableBufferSequence> buffers_;
  192. int start_;
  193. std::size_t total_transferred_;
  194. ReadHandler handler_;
  195. };
  196. template <typename AsyncReadStream,
  197. typename CompletionCondition, typename ReadHandler>
  198. class read_op<AsyncReadStream, asio::mutable_buffers_1,
  199. CompletionCondition, ReadHandler>
  200. : detail::base_from_completion_cond<CompletionCondition>
  201. {
  202. public:
  203. read_op(AsyncReadStream& stream,
  204. const asio::mutable_buffers_1& buffers,
  205. CompletionCondition completion_condition, ReadHandler& handler)
  206. : detail::base_from_completion_cond<
  207. CompletionCondition>(completion_condition),
  208. stream_(stream),
  209. buffer_(buffers),
  210. start_(0),
  211. total_transferred_(0),
  212. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  213. {
  214. }
  215. #if defined(ASIO_HAS_MOVE)
  216. read_op(const read_op& other)
  217. : detail::base_from_completion_cond<CompletionCondition>(other),
  218. stream_(other.stream_),
  219. buffer_(other.buffer_),
  220. start_(other.start_),
  221. total_transferred_(other.total_transferred_),
  222. handler_(other.handler_)
  223. {
  224. }
  225. read_op(read_op&& other)
  226. : detail::base_from_completion_cond<CompletionCondition>(other),
  227. stream_(other.stream_),
  228. buffer_(other.buffer_),
  229. start_(other.start_),
  230. total_transferred_(other.total_transferred_),
  231. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  232. {
  233. }
  234. #endif // defined(ASIO_HAS_MOVE)
  235. void operator()(const asio::error_code& ec,
  236. std::size_t bytes_transferred, int start = 0)
  237. {
  238. std::size_t n = 0;
  239. switch (start_ = start)
  240. {
  241. case 1:
  242. n = this->check_for_completion(ec, total_transferred_);
  243. for (;;)
  244. {
  245. stream_.async_read_some(
  246. asio::buffer(buffer_ + total_transferred_, n),
  247. ASIO_MOVE_CAST(read_op)(*this));
  248. return; default:
  249. total_transferred_ += bytes_transferred;
  250. if ((!ec && bytes_transferred == 0)
  251. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  252. || total_transferred_ == asio::buffer_size(buffer_))
  253. break;
  254. }
  255. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  256. }
  257. }
  258. //private:
  259. AsyncReadStream& stream_;
  260. asio::mutable_buffer buffer_;
  261. int start_;
  262. std::size_t total_transferred_;
  263. ReadHandler handler_;
  264. };
  265. template <typename AsyncReadStream, typename Elem,
  266. typename CompletionCondition, typename ReadHandler>
  267. class read_op<AsyncReadStream, boost::array<Elem, 2>,
  268. CompletionCondition, ReadHandler>
  269. : detail::base_from_completion_cond<CompletionCondition>
  270. {
  271. public:
  272. read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers,
  273. CompletionCondition completion_condition, ReadHandler& handler)
  274. : detail::base_from_completion_cond<
  275. CompletionCondition>(completion_condition),
  276. stream_(stream),
  277. buffers_(buffers),
  278. start_(0),
  279. total_transferred_(0),
  280. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  281. {
  282. }
  283. #if defined(ASIO_HAS_MOVE)
  284. read_op(const read_op& other)
  285. : detail::base_from_completion_cond<CompletionCondition>(other),
  286. stream_(other.stream_),
  287. buffers_(other.buffers_),
  288. start_(other.start_),
  289. total_transferred_(other.total_transferred_),
  290. handler_(other.handler_)
  291. {
  292. }
  293. read_op(read_op&& other)
  294. : detail::base_from_completion_cond<CompletionCondition>(other),
  295. stream_(other.stream_),
  296. buffers_(other.buffers_),
  297. start_(other.start_),
  298. total_transferred_(other.total_transferred_),
  299. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  300. {
  301. }
  302. #endif // defined(ASIO_HAS_MOVE)
  303. void operator()(const asio::error_code& ec,
  304. std::size_t bytes_transferred, int start = 0)
  305. {
  306. typename asio::detail::dependent_type<Elem,
  307. boost::array<asio::mutable_buffer, 2> >::type bufs = {{
  308. asio::mutable_buffer(buffers_[0]),
  309. asio::mutable_buffer(buffers_[1]) }};
  310. std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
  311. std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
  312. std::size_t n = 0;
  313. switch (start_ = start)
  314. {
  315. case 1:
  316. n = this->check_for_completion(ec, total_transferred_);
  317. for (;;)
  318. {
  319. bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
  320. bufs[1] = asio::buffer(
  321. bufs[1] + (total_transferred_ < buffer_size0
  322. ? 0 : total_transferred_ - buffer_size0),
  323. n - asio::buffer_size(bufs[0]));
  324. stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this));
  325. return; default:
  326. total_transferred_ += bytes_transferred;
  327. if ((!ec && bytes_transferred == 0)
  328. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  329. || total_transferred_ == buffer_size0 + buffer_size1)
  330. break;
  331. }
  332. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  333. }
  334. }
  335. //private:
  336. AsyncReadStream& stream_;
  337. boost::array<Elem, 2> buffers_;
  338. int start_;
  339. std::size_t total_transferred_;
  340. ReadHandler handler_;
  341. };
  342. #if defined(ASIO_HAS_STD_ARRAY)
  343. template <typename AsyncReadStream, typename Elem,
  344. typename CompletionCondition, typename ReadHandler>
  345. class read_op<AsyncReadStream, std::array<Elem, 2>,
  346. CompletionCondition, ReadHandler>
  347. : detail::base_from_completion_cond<CompletionCondition>
  348. {
  349. public:
  350. read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers,
  351. CompletionCondition completion_condition, ReadHandler& handler)
  352. : detail::base_from_completion_cond<
  353. CompletionCondition>(completion_condition),
  354. stream_(stream),
  355. buffers_(buffers),
  356. start_(0),
  357. total_transferred_(0),
  358. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  359. {
  360. }
  361. #if defined(ASIO_HAS_MOVE)
  362. read_op(const read_op& other)
  363. : detail::base_from_completion_cond<CompletionCondition>(other),
  364. stream_(other.stream_),
  365. buffers_(other.buffers_),
  366. start_(other.start_),
  367. total_transferred_(other.total_transferred_),
  368. handler_(other.handler_)
  369. {
  370. }
  371. read_op(read_op&& other)
  372. : detail::base_from_completion_cond<CompletionCondition>(other),
  373. stream_(other.stream_),
  374. buffers_(other.buffers_),
  375. start_(other.start_),
  376. total_transferred_(other.total_transferred_),
  377. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  378. {
  379. }
  380. #endif // defined(ASIO_HAS_MOVE)
  381. void operator()(const asio::error_code& ec,
  382. std::size_t bytes_transferred, int start = 0)
  383. {
  384. typename asio::detail::dependent_type<Elem,
  385. std::array<asio::mutable_buffer, 2> >::type bufs = {{
  386. asio::mutable_buffer(buffers_[0]),
  387. asio::mutable_buffer(buffers_[1]) }};
  388. std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
  389. std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
  390. std::size_t n = 0;
  391. switch (start_ = start)
  392. {
  393. case 1:
  394. n = this->check_for_completion(ec, total_transferred_);
  395. for (;;)
  396. {
  397. bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
  398. bufs[1] = asio::buffer(
  399. bufs[1] + (total_transferred_ < buffer_size0
  400. ? 0 : total_transferred_ - buffer_size0),
  401. n - asio::buffer_size(bufs[0]));
  402. stream_.async_read_some(bufs, ASIO_MOVE_CAST(read_op)(*this));
  403. return; default:
  404. total_transferred_ += bytes_transferred;
  405. if ((!ec && bytes_transferred == 0)
  406. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  407. || total_transferred_ == buffer_size0 + buffer_size1)
  408. break;
  409. }
  410. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  411. }
  412. }
  413. //private:
  414. AsyncReadStream& stream_;
  415. std::array<Elem, 2> buffers_;
  416. int start_;
  417. std::size_t total_transferred_;
  418. ReadHandler handler_;
  419. };
  420. #endif // defined(ASIO_HAS_STD_ARRAY)
  421. template <typename AsyncReadStream, typename MutableBufferSequence,
  422. typename CompletionCondition, typename ReadHandler>
  423. inline void* asio_handler_allocate(std::size_t size,
  424. read_op<AsyncReadStream, MutableBufferSequence,
  425. CompletionCondition, ReadHandler>* this_handler)
  426. {
  427. return asio_handler_alloc_helpers::allocate(
  428. size, this_handler->handler_);
  429. }
  430. template <typename AsyncReadStream, typename MutableBufferSequence,
  431. typename CompletionCondition, typename ReadHandler>
  432. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  433. read_op<AsyncReadStream, MutableBufferSequence,
  434. CompletionCondition, ReadHandler>* this_handler)
  435. {
  436. asio_handler_alloc_helpers::deallocate(
  437. pointer, size, this_handler->handler_);
  438. }
  439. template <typename AsyncReadStream, typename MutableBufferSequence,
  440. typename CompletionCondition, typename ReadHandler>
  441. inline bool asio_handler_is_continuation(
  442. read_op<AsyncReadStream, MutableBufferSequence,
  443. CompletionCondition, ReadHandler>* this_handler)
  444. {
  445. return this_handler->start_ == 0 ? true
  446. : asio_handler_cont_helpers::is_continuation(
  447. this_handler->handler_);
  448. }
  449. template <typename Function, typename AsyncReadStream,
  450. typename MutableBufferSequence, typename CompletionCondition,
  451. typename ReadHandler>
  452. inline void asio_handler_invoke(Function& function,
  453. read_op<AsyncReadStream, MutableBufferSequence,
  454. CompletionCondition, ReadHandler>* this_handler)
  455. {
  456. asio_handler_invoke_helpers::invoke(
  457. function, this_handler->handler_);
  458. }
  459. template <typename Function, typename AsyncReadStream,
  460. typename MutableBufferSequence, typename CompletionCondition,
  461. typename ReadHandler>
  462. inline void asio_handler_invoke(const Function& function,
  463. read_op<AsyncReadStream, MutableBufferSequence,
  464. CompletionCondition, ReadHandler>* this_handler)
  465. {
  466. asio_handler_invoke_helpers::invoke(
  467. function, this_handler->handler_);
  468. }
  469. } // namespace detail
  470. template <typename AsyncReadStream, typename MutableBufferSequence,
  471. typename CompletionCondition, typename ReadHandler>
  472. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  473. void (asio::error_code, std::size_t))
  474. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  475. CompletionCondition completion_condition,
  476. ASIO_MOVE_ARG(ReadHandler) handler)
  477. {
  478. // If you get an error on the following line it means that your handler does
  479. // not meet the documented type requirements for a ReadHandler.
  480. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  481. detail::async_result_init<
  482. ReadHandler, void (asio::error_code, std::size_t)> init(
  483. ASIO_MOVE_CAST(ReadHandler)(handler));
  484. detail::read_op<AsyncReadStream, MutableBufferSequence,
  485. CompletionCondition, ASIO_HANDLER_TYPE(
  486. ReadHandler, void (asio::error_code, std::size_t))>(
  487. s, buffers, completion_condition, init.handler)(
  488. asio::error_code(), 0, 1);
  489. return init.result.get();
  490. }
  491. template <typename AsyncReadStream, typename MutableBufferSequence,
  492. typename ReadHandler>
  493. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  494. void (asio::error_code, std::size_t))
  495. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  496. ASIO_MOVE_ARG(ReadHandler) handler)
  497. {
  498. // If you get an error on the following line it means that your handler does
  499. // not meet the documented type requirements for a ReadHandler.
  500. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  501. detail::async_result_init<
  502. ReadHandler, void (asio::error_code, std::size_t)> init(
  503. ASIO_MOVE_CAST(ReadHandler)(handler));
  504. detail::read_op<AsyncReadStream, MutableBufferSequence,
  505. detail::transfer_all_t, ASIO_HANDLER_TYPE(
  506. ReadHandler, void (asio::error_code, std::size_t))>(
  507. s, buffers, transfer_all(), init.handler)(
  508. asio::error_code(), 0, 1);
  509. return init.result.get();
  510. }
  511. #if !defined(ASIO_NO_IOSTREAM)
  512. namespace detail
  513. {
  514. template <typename AsyncReadStream, typename Allocator,
  515. typename CompletionCondition, typename ReadHandler>
  516. class read_streambuf_op
  517. : detail::base_from_completion_cond<CompletionCondition>
  518. {
  519. public:
  520. read_streambuf_op(AsyncReadStream& stream,
  521. basic_streambuf<Allocator>& streambuf,
  522. CompletionCondition completion_condition, ReadHandler& handler)
  523. : detail::base_from_completion_cond<
  524. CompletionCondition>(completion_condition),
  525. stream_(stream),
  526. streambuf_(streambuf),
  527. start_(0),
  528. total_transferred_(0),
  529. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  530. {
  531. }
  532. #if defined(ASIO_HAS_MOVE)
  533. read_streambuf_op(const read_streambuf_op& other)
  534. : detail::base_from_completion_cond<CompletionCondition>(other),
  535. stream_(other.stream_),
  536. streambuf_(other.streambuf_),
  537. start_(other.start_),
  538. total_transferred_(other.total_transferred_),
  539. handler_(other.handler_)
  540. {
  541. }
  542. read_streambuf_op(read_streambuf_op&& other)
  543. : detail::base_from_completion_cond<CompletionCondition>(other),
  544. stream_(other.stream_),
  545. streambuf_(other.streambuf_),
  546. start_(other.start_),
  547. total_transferred_(other.total_transferred_),
  548. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  549. {
  550. }
  551. #endif // defined(ASIO_HAS_MOVE)
  552. void operator()(const asio::error_code& ec,
  553. std::size_t bytes_transferred, int start = 0)
  554. {
  555. std::size_t max_size, bytes_available;
  556. switch (start_ = start)
  557. {
  558. case 1:
  559. max_size = this->check_for_completion(ec, total_transferred_);
  560. bytes_available = read_size_helper(streambuf_, max_size);
  561. for (;;)
  562. {
  563. stream_.async_read_some(streambuf_.prepare(bytes_available),
  564. ASIO_MOVE_CAST(read_streambuf_op)(*this));
  565. return; default:
  566. total_transferred_ += bytes_transferred;
  567. streambuf_.commit(bytes_transferred);
  568. max_size = this->check_for_completion(ec, total_transferred_);
  569. bytes_available = read_size_helper(streambuf_, max_size);
  570. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  571. break;
  572. }
  573. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  574. }
  575. }
  576. //private:
  577. AsyncReadStream& stream_;
  578. asio::basic_streambuf<Allocator>& streambuf_;
  579. int start_;
  580. std::size_t total_transferred_;
  581. ReadHandler handler_;
  582. };
  583. template <typename AsyncReadStream, typename Allocator,
  584. typename CompletionCondition, typename ReadHandler>
  585. inline void* asio_handler_allocate(std::size_t size,
  586. read_streambuf_op<AsyncReadStream, Allocator,
  587. CompletionCondition, ReadHandler>* this_handler)
  588. {
  589. return asio_handler_alloc_helpers::allocate(
  590. size, this_handler->handler_);
  591. }
  592. template <typename AsyncReadStream, typename Allocator,
  593. typename CompletionCondition, typename ReadHandler>
  594. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  595. read_streambuf_op<AsyncReadStream, Allocator,
  596. CompletionCondition, ReadHandler>* this_handler)
  597. {
  598. asio_handler_alloc_helpers::deallocate(
  599. pointer, size, this_handler->handler_);
  600. }
  601. template <typename AsyncReadStream, typename Allocator,
  602. typename CompletionCondition, typename ReadHandler>
  603. inline bool asio_handler_is_continuation(
  604. read_streambuf_op<AsyncReadStream, Allocator,
  605. CompletionCondition, ReadHandler>* this_handler)
  606. {
  607. return this_handler->start_ == 0 ? true
  608. : asio_handler_cont_helpers::is_continuation(
  609. this_handler->handler_);
  610. }
  611. template <typename Function, typename AsyncReadStream,
  612. typename Allocator, typename CompletionCondition, typename ReadHandler>
  613. inline void asio_handler_invoke(Function& function,
  614. read_streambuf_op<AsyncReadStream, Allocator,
  615. CompletionCondition, ReadHandler>* this_handler)
  616. {
  617. asio_handler_invoke_helpers::invoke(
  618. function, this_handler->handler_);
  619. }
  620. template <typename Function, typename AsyncReadStream,
  621. typename Allocator, typename CompletionCondition, typename ReadHandler>
  622. inline void asio_handler_invoke(const Function& function,
  623. read_streambuf_op<AsyncReadStream, Allocator,
  624. CompletionCondition, ReadHandler>* this_handler)
  625. {
  626. asio_handler_invoke_helpers::invoke(
  627. function, this_handler->handler_);
  628. }
  629. } // namespace detail
  630. template <typename AsyncReadStream, typename Allocator,
  631. typename CompletionCondition, typename ReadHandler>
  632. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  633. void (asio::error_code, std::size_t))
  634. async_read(AsyncReadStream& s,
  635. asio::basic_streambuf<Allocator>& b,
  636. CompletionCondition completion_condition,
  637. ASIO_MOVE_ARG(ReadHandler) handler)
  638. {
  639. // If you get an error on the following line it means that your handler does
  640. // not meet the documented type requirements for a ReadHandler.
  641. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  642. detail::async_result_init<
  643. ReadHandler, void (asio::error_code, std::size_t)> init(
  644. ASIO_MOVE_CAST(ReadHandler)(handler));
  645. detail::read_streambuf_op<AsyncReadStream, Allocator,
  646. CompletionCondition, ASIO_HANDLER_TYPE(
  647. ReadHandler, void (asio::error_code, std::size_t))>(
  648. s, b, completion_condition, init.handler)(
  649. asio::error_code(), 0, 1);
  650. return init.result.get();
  651. }
  652. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  653. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  654. void (asio::error_code, std::size_t))
  655. async_read(AsyncReadStream& s,
  656. asio::basic_streambuf<Allocator>& b,
  657. ASIO_MOVE_ARG(ReadHandler) handler)
  658. {
  659. // If you get an error on the following line it means that your handler does
  660. // not meet the documented type requirements for a ReadHandler.
  661. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  662. detail::async_result_init<
  663. ReadHandler, void (asio::error_code, std::size_t)> init(
  664. ASIO_MOVE_CAST(ReadHandler)(handler));
  665. detail::read_streambuf_op<AsyncReadStream, Allocator,
  666. detail::transfer_all_t, ASIO_HANDLER_TYPE(
  667. ReadHandler, void (asio::error_code, std::size_t))>(
  668. s, b, transfer_all(), init.handler)(
  669. asio::error_code(), 0, 1);
  670. return init.result.get();
  671. }
  672. #endif // !defined(ASIO_NO_IOSTREAM)
  673. } // namespace asio
  674. #include "asio/detail/pop_options.hpp"
  675. #endif // ASIO_IMPL_READ_HPP