read_at.hpp 26 KB

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