read_at.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. //
  2. // impl/read_at.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef 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/associator.hpp>
  17. #include <boost/asio/buffer.hpp>
  18. #include <boost/asio/detail/array_fwd.hpp>
  19. #include <boost/asio/detail/base_from_cancellation_state.hpp>
  20. #include <boost/asio/detail/base_from_completion_cond.hpp>
  21. #include <boost/asio/detail/bind_handler.hpp>
  22. #include <boost/asio/detail/consuming_buffers.hpp>
  23. #include <boost/asio/detail/dependent_type.hpp>
  24. #include <boost/asio/detail/handler_alloc_helpers.hpp>
  25. #include <boost/asio/detail/handler_cont_helpers.hpp>
  26. #include <boost/asio/detail/handler_invoke_helpers.hpp>
  27. #include <boost/asio/detail/handler_tracking.hpp>
  28. #include <boost/asio/detail/handler_type_requirements.hpp>
  29. #include <boost/asio/detail/non_const_lvalue.hpp>
  30. #include <boost/asio/detail/throw_error.hpp>
  31. #include <boost/asio/error.hpp>
  32. #include <boost/asio/detail/push_options.hpp>
  33. namespace boost {
  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. boost::system::error_code& ec)
  43. {
  44. ec = boost::system::error_code();
  45. boost::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, boost::system::error_code& ec)
  66. {
  67. return detail::read_at_buffer_sequence(d, offset, buffers,
  68. boost::asio::buffer_sequence_begin(buffers),
  69. BOOST_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. boost::system::error_code ec;
  76. std::size_t bytes_transferred = read_at(
  77. d, offset, buffers, transfer_all(), ec);
  78. boost::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. boost::system::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. boost::system::error_code ec;
  95. std::size_t bytes_transferred = read_at(d, offset, buffers,
  96. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  97. boost::asio::detail::throw_error(ec, "read_at");
  98. return bytes_transferred;
  99. }
  100. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  101. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  102. template <typename SyncRandomAccessReadDevice, typename Allocator,
  103. typename CompletionCondition>
  104. std::size_t read_at(SyncRandomAccessReadDevice& d,
  105. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  106. CompletionCondition completion_condition, boost::system::error_code& ec)
  107. {
  108. ec = boost::system::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, boost::asio::basic_streambuf<Allocator>& b)
  128. {
  129. boost::system::error_code ec;
  130. std::size_t bytes_transferred = read_at(
  131. d, offset, b, transfer_all(), ec);
  132. boost::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, boost::asio::basic_streambuf<Allocator>& b,
  138. boost::system::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, boost::asio::basic_streambuf<Allocator>& b,
  146. CompletionCondition completion_condition)
  147. {
  148. boost::system::error_code ec;
  149. std::size_t bytes_transferred = read_at(d, offset, b,
  150. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  151. boost::asio::detail::throw_error(ec, "read_at");
  152. return bytes_transferred;
  153. }
  154. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  155. #endif // !defined(BOOST_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_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  177. {
  178. }
  179. #if defined(BOOST_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. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  193. ReadHandler>)(other)),
  194. base_from_completion_cond<CompletionCondition>(
  195. BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
  196. CompletionCondition>)(other)),
  197. device_(other.device_),
  198. offset_(other.offset_),
  199. buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
  200. start_(other.start_),
  201. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  202. {
  203. }
  204. #endif // defined(BOOST_ASIO_HAS_MOVE)
  205. void operator()(boost::system::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. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
  217. device_.async_read_some_at(
  218. offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
  219. BOOST_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 = boost::asio::error::operation_aborted;
  231. break;
  232. }
  233. }
  234. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
  235. static_cast<const boost::system::error_code&>(ec),
  236. static_cast<const std::size_t&>(buffers_.total_consumed()));
  237. }
  238. }
  239. //private:
  240. typedef boost::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(BOOST_ASIO_NO_DEPRECATED)
  257. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  258. return asio_handler_allocate_is_no_longer_used();
  259. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  260. return boost_asio_handler_alloc_helpers::allocate(
  261. size, this_handler->handler_);
  262. #endif // defined(BOOST_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. boost_asio_handler_alloc_helpers::deallocate(
  273. pointer, size, this_handler->handler_);
  274. #if defined(BOOST_ASIO_NO_DEPRECATED)
  275. return asio_handler_deallocate_is_no_longer_used();
  276. #endif // defined(BOOST_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. : boost_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. 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 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. boost_asio_handler_invoke_helpers::invoke(
  312. function, this_handler->handler_);
  313. #if defined(BOOST_ASIO_NO_DEPRECATED)
  314. return asio_handler_invoke_is_no_longer_used();
  315. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  316. }
  317. template <typename AsyncRandomAccessReadDevice,
  318. typename MutableBufferSequence, typename MutableBufferIterator,
  319. typename CompletionCondition, typename ReadHandler>
  320. inline void start_read_at_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. boost::system::error_code(), 0, 1);
  329. }
  330. template <typename AsyncRandomAccessReadDevice>
  331. class initiate_async_read_at
  332. {
  333. public:
  334. typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
  335. explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)
  336. : device_(device)
  337. {
  338. }
  339. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  340. {
  341. return device_.get_executor();
  342. }
  343. template <typename ReadHandler, typename MutableBufferSequence,
  344. typename CompletionCondition>
  345. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  346. uint64_t offset, const MutableBufferSequence& buffers,
  347. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  348. {
  349. // If you get an error on the following line it means that your handler
  350. // does not meet the documented type requirements for a ReadHandler.
  351. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  352. non_const_lvalue<ReadHandler> handler2(handler);
  353. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  354. start_read_at_op(device_, offset, buffers,
  355. boost::asio::buffer_sequence_begin(buffers),
  356. completion_cond2.value, handler2.value);
  357. }
  358. private:
  359. AsyncRandomAccessReadDevice& device_;
  360. };
  361. } // namespace detail
  362. #if !defined(GENERATING_DOCUMENTATION)
  363. template <template <typename, typename> class Associator,
  364. typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  365. typename MutableBufferIterator, typename CompletionCondition,
  366. typename ReadHandler, typename DefaultCandidate>
  367. struct associator<Associator,
  368. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  369. MutableBufferIterator, CompletionCondition, ReadHandler>,
  370. DefaultCandidate>
  371. : Associator<ReadHandler, DefaultCandidate>
  372. {
  373. static typename Associator<ReadHandler, DefaultCandidate>::type
  374. get(const detail::read_at_op<AsyncRandomAccessReadDevice,
  375. MutableBufferSequence, MutableBufferIterator,
  376. CompletionCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  377. {
  378. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  379. }
  380. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  381. typename Associator<ReadHandler, DefaultCandidate>::type)
  382. get(const detail::read_at_op<AsyncRandomAccessReadDevice,
  383. MutableBufferSequence, MutableBufferIterator,
  384. CompletionCondition, ReadHandler>& h,
  385. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  386. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  387. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  388. {
  389. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  390. }
  391. };
  392. #endif // !defined(GENERATING_DOCUMENTATION)
  393. template <typename AsyncRandomAccessReadDevice,
  394. typename MutableBufferSequence, typename CompletionCondition,
  395. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  396. std::size_t)) ReadToken>
  397. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  398. void (boost::system::error_code, std::size_t))
  399. async_read_at(AsyncRandomAccessReadDevice& d,
  400. uint64_t offset, const MutableBufferSequence& buffers,
  401. CompletionCondition completion_condition,
  402. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  403. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  404. async_initiate<ReadToken,
  405. void (boost::system::error_code, std::size_t)>(
  406. declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),
  407. token, offset, buffers,
  408. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
  409. {
  410. return async_initiate<ReadToken,
  411. void (boost::system::error_code, std::size_t)>(
  412. detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
  413. token, offset, buffers,
  414. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  415. }
  416. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  417. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  418. std::size_t)) ReadToken>
  419. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  420. void (boost::system::error_code, std::size_t))
  421. async_read_at(AsyncRandomAccessReadDevice& d,
  422. uint64_t offset, const MutableBufferSequence& buffers,
  423. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  424. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  425. async_initiate<ReadToken,
  426. void (boost::system::error_code, std::size_t)>(
  427. declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),
  428. token, offset, buffers, transfer_all())))
  429. {
  430. return async_initiate<ReadToken,
  431. void (boost::system::error_code, std::size_t)>(
  432. detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
  433. token, offset, buffers, transfer_all());
  434. }
  435. #if !defined(BOOST_ASIO_NO_EXTENSIONS)
  436. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  437. namespace detail
  438. {
  439. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  440. typename CompletionCondition, typename ReadHandler>
  441. class read_at_streambuf_op
  442. : public base_from_cancellation_state<ReadHandler>,
  443. base_from_completion_cond<CompletionCondition>
  444. {
  445. public:
  446. read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
  447. uint64_t offset, basic_streambuf<Allocator>& streambuf,
  448. CompletionCondition& completion_condition, ReadHandler& handler)
  449. : base_from_cancellation_state<ReadHandler>(
  450. handler, enable_partial_cancellation()),
  451. base_from_completion_cond<CompletionCondition>(completion_condition),
  452. device_(device),
  453. offset_(offset),
  454. streambuf_(streambuf),
  455. start_(0),
  456. total_transferred_(0),
  457. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
  458. {
  459. }
  460. #if defined(BOOST_ASIO_HAS_MOVE)
  461. read_at_streambuf_op(const read_at_streambuf_op& other)
  462. : base_from_cancellation_state<ReadHandler>(other),
  463. base_from_completion_cond<CompletionCondition>(other),
  464. device_(other.device_),
  465. offset_(other.offset_),
  466. streambuf_(other.streambuf_),
  467. start_(other.start_),
  468. total_transferred_(other.total_transferred_),
  469. handler_(other.handler_)
  470. {
  471. }
  472. read_at_streambuf_op(read_at_streambuf_op&& other)
  473. : base_from_cancellation_state<ReadHandler>(
  474. BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
  475. ReadHandler>)(other)),
  476. base_from_completion_cond<CompletionCondition>(
  477. BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
  478. CompletionCondition>)(other)),
  479. device_(other.device_),
  480. offset_(other.offset_),
  481. streambuf_(other.streambuf_),
  482. start_(other.start_),
  483. total_transferred_(other.total_transferred_),
  484. handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  485. {
  486. }
  487. #endif // defined(BOOST_ASIO_HAS_MOVE)
  488. void operator()(boost::system::error_code ec,
  489. std::size_t bytes_transferred, int start = 0)
  490. {
  491. std::size_t max_size, bytes_available;
  492. switch (start_ = start)
  493. {
  494. case 1:
  495. max_size = this->check_for_completion(ec, total_transferred_);
  496. bytes_available = read_size_helper(streambuf_, max_size);
  497. for (;;)
  498. {
  499. {
  500. BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
  501. device_.async_read_some_at(offset_ + total_transferred_,
  502. streambuf_.prepare(bytes_available),
  503. BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
  504. }
  505. return; default:
  506. total_transferred_ += bytes_transferred;
  507. streambuf_.commit(bytes_transferred);
  508. max_size = this->check_for_completion(ec, total_transferred_);
  509. bytes_available = read_size_helper(streambuf_, max_size);
  510. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  511. break;
  512. if (this->cancelled() != cancellation_type::none)
  513. {
  514. ec = boost::asio::error::operation_aborted;
  515. break;
  516. }
  517. }
  518. BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
  519. static_cast<const boost::system::error_code&>(ec),
  520. static_cast<const std::size_t&>(total_transferred_));
  521. }
  522. }
  523. //private:
  524. AsyncRandomAccessReadDevice& device_;
  525. uint64_t offset_;
  526. boost::asio::basic_streambuf<Allocator>& streambuf_;
  527. int start_;
  528. std::size_t total_transferred_;
  529. ReadHandler handler_;
  530. };
  531. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  532. typename CompletionCondition, typename ReadHandler>
  533. inline asio_handler_allocate_is_deprecated
  534. asio_handler_allocate(std::size_t size,
  535. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  536. CompletionCondition, ReadHandler>* this_handler)
  537. {
  538. #if defined(BOOST_ASIO_NO_DEPRECATED)
  539. boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
  540. return asio_handler_allocate_is_no_longer_used();
  541. #else // defined(BOOST_ASIO_NO_DEPRECATED)
  542. return boost_asio_handler_alloc_helpers::allocate(
  543. size, this_handler->handler_);
  544. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  545. }
  546. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  547. typename CompletionCondition, typename ReadHandler>
  548. inline asio_handler_deallocate_is_deprecated
  549. asio_handler_deallocate(void* pointer, std::size_t size,
  550. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  551. CompletionCondition, ReadHandler>* this_handler)
  552. {
  553. boost_asio_handler_alloc_helpers::deallocate(
  554. pointer, size, this_handler->handler_);
  555. #if defined(BOOST_ASIO_NO_DEPRECATED)
  556. return asio_handler_deallocate_is_no_longer_used();
  557. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  558. }
  559. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  560. typename CompletionCondition, typename ReadHandler>
  561. inline bool asio_handler_is_continuation(
  562. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  563. CompletionCondition, ReadHandler>* this_handler)
  564. {
  565. return this_handler->start_ == 0 ? true
  566. : boost_asio_handler_cont_helpers::is_continuation(
  567. this_handler->handler_);
  568. }
  569. template <typename Function, typename AsyncRandomAccessReadDevice,
  570. typename Allocator, typename CompletionCondition, typename ReadHandler>
  571. inline asio_handler_invoke_is_deprecated
  572. asio_handler_invoke(Function& function,
  573. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  574. CompletionCondition, ReadHandler>* this_handler)
  575. {
  576. boost_asio_handler_invoke_helpers::invoke(
  577. function, this_handler->handler_);
  578. #if defined(BOOST_ASIO_NO_DEPRECATED)
  579. return asio_handler_invoke_is_no_longer_used();
  580. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  581. }
  582. template <typename Function, typename AsyncRandomAccessReadDevice,
  583. typename Allocator, typename CompletionCondition, typename ReadHandler>
  584. inline asio_handler_invoke_is_deprecated
  585. asio_handler_invoke(const Function& function,
  586. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  587. CompletionCondition, ReadHandler>* this_handler)
  588. {
  589. boost_asio_handler_invoke_helpers::invoke(
  590. function, this_handler->handler_);
  591. #if defined(BOOST_ASIO_NO_DEPRECATED)
  592. return asio_handler_invoke_is_no_longer_used();
  593. #endif // defined(BOOST_ASIO_NO_DEPRECATED)
  594. }
  595. template <typename AsyncRandomAccessReadDevice>
  596. class initiate_async_read_at_streambuf
  597. {
  598. public:
  599. typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
  600. explicit initiate_async_read_at_streambuf(
  601. AsyncRandomAccessReadDevice& device)
  602. : device_(device)
  603. {
  604. }
  605. executor_type get_executor() const BOOST_ASIO_NOEXCEPT
  606. {
  607. return device_.get_executor();
  608. }
  609. template <typename ReadHandler,
  610. typename Allocator, typename CompletionCondition>
  611. void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
  612. uint64_t offset, basic_streambuf<Allocator>* b,
  613. BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  614. {
  615. // If you get an error on the following line it means that your handler
  616. // does not meet the documented type requirements for a ReadHandler.
  617. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  618. non_const_lvalue<ReadHandler> handler2(handler);
  619. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  620. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  621. CompletionCondition, typename decay<ReadHandler>::type>(
  622. device_, offset, *b, completion_cond2.value, handler2.value)(
  623. boost::system::error_code(), 0, 1);
  624. }
  625. private:
  626. AsyncRandomAccessReadDevice& device_;
  627. };
  628. } // namespace detail
  629. #if !defined(GENERATING_DOCUMENTATION)
  630. template <template <typename, typename> class Associator,
  631. typename AsyncRandomAccessReadDevice, typename Executor,
  632. typename CompletionCondition, typename ReadHandler,
  633. typename DefaultCandidate>
  634. struct associator<Associator,
  635. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  636. Executor, CompletionCondition, ReadHandler>,
  637. DefaultCandidate>
  638. : Associator<ReadHandler, DefaultCandidate>
  639. {
  640. static typename Associator<ReadHandler, DefaultCandidate>::type
  641. get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  642. Executor, CompletionCondition, ReadHandler>& h) BOOST_ASIO_NOEXCEPT
  643. {
  644. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
  645. }
  646. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  647. typename Associator<ReadHandler, DefaultCandidate>::type)
  648. get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  649. Executor, CompletionCondition, ReadHandler>& h,
  650. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  651. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  652. Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))
  653. {
  654. return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
  655. }
  656. };
  657. #endif // !defined(GENERATING_DOCUMENTATION)
  658. template <typename AsyncRandomAccessReadDevice,
  659. typename Allocator, typename CompletionCondition,
  660. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  661. std::size_t)) ReadToken>
  662. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  663. void (boost::system::error_code, std::size_t))
  664. async_read_at(AsyncRandomAccessReadDevice& d,
  665. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  666. CompletionCondition completion_condition,
  667. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  668. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  669. async_initiate<ReadToken,
  670. void (boost::system::error_code, std::size_t)>(
  671. declval<detail::initiate_async_read_at_streambuf<
  672. AsyncRandomAccessReadDevice> >(),
  673. token, offset, &b,
  674. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition))))
  675. {
  676. return async_initiate<ReadToken,
  677. void (boost::system::error_code, std::size_t)>(
  678. detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
  679. token, offset, &b,
  680. BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  681. }
  682. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  683. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  684. std::size_t)) ReadToken>
  685. inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,
  686. void (boost::system::error_code, std::size_t))
  687. async_read_at(AsyncRandomAccessReadDevice& d,
  688. uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
  689. BOOST_ASIO_MOVE_ARG(ReadToken) token)
  690. BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((
  691. async_initiate<ReadToken,
  692. void (boost::system::error_code, std::size_t)>(
  693. declval<detail::initiate_async_read_at_streambuf<
  694. AsyncRandomAccessReadDevice> >(),
  695. token, offset, &b, transfer_all())))
  696. {
  697. return async_initiate<ReadToken,
  698. void (boost::system::error_code, std::size_t)>(
  699. detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
  700. token, offset, &b, transfer_all());
  701. }
  702. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  703. #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
  704. } // namespace asio
  705. } // namespace boost
  706. #include <boost/asio/detail/pop_options.hpp>
  707. #endif // BOOST_ASIO_IMPL_READ_AT_HPP