read_at.hpp 28 KB

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