Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

889 lines
31KB

  1. //
  2. // impl/read_at.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_IMPL_READ_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/associated_allocator.hpp"
  17. #include "asio/associated_executor.hpp"
  18. #include "asio/buffer.hpp"
  19. #include "asio/completion_condition.hpp"
  20. #include "asio/detail/array_fwd.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_type_requirements.hpp"
  29. #include "asio/detail/throw_error.hpp"
  30. #include "asio/error.hpp"
  31. #include "asio/detail/push_options.hpp"
  32. namespace asio {
  33. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  34. typename CompletionCondition>
  35. std::size_t read_at(SyncRandomAccessReadDevice& d,
  36. uint64_t offset, const MutableBufferSequence& buffers,
  37. CompletionCondition completion_condition, asio::error_code& ec)
  38. {
  39. ec = asio::error_code();
  40. asio::detail::consuming_buffers<
  41. mutable_buffer, MutableBufferSequence> tmp(buffers);
  42. std::size_t total_transferred = 0;
  43. tmp.prepare(detail::adapt_completion_condition_result(
  44. completion_condition(ec, total_transferred)));
  45. while (tmp.begin() != tmp.end())
  46. {
  47. std::size_t bytes_transferred = d.read_some_at(
  48. offset + total_transferred, tmp, ec);
  49. tmp.consume(bytes_transferred);
  50. total_transferred += bytes_transferred;
  51. tmp.prepare(detail::adapt_completion_condition_result(
  52. completion_condition(ec, total_transferred)));
  53. }
  54. return total_transferred;
  55. }
  56. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
  57. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  58. uint64_t offset, const MutableBufferSequence& buffers)
  59. {
  60. asio::error_code ec;
  61. std::size_t bytes_transferred = read_at(
  62. d, offset, buffers, transfer_all(), ec);
  63. asio::detail::throw_error(ec, "read_at");
  64. return bytes_transferred;
  65. }
  66. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
  67. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  68. uint64_t offset, const MutableBufferSequence& buffers,
  69. asio::error_code& ec)
  70. {
  71. return read_at(d, offset, buffers, transfer_all(), ec);
  72. }
  73. template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
  74. typename CompletionCondition>
  75. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  76. uint64_t offset, const MutableBufferSequence& buffers,
  77. CompletionCondition completion_condition)
  78. {
  79. asio::error_code ec;
  80. std::size_t bytes_transferred = read_at(
  81. d, offset, buffers, completion_condition, ec);
  82. asio::detail::throw_error(ec, "read_at");
  83. return bytes_transferred;
  84. }
  85. #if !defined(ASIO_NO_IOSTREAM)
  86. template <typename SyncRandomAccessReadDevice, typename Allocator,
  87. typename CompletionCondition>
  88. std::size_t read_at(SyncRandomAccessReadDevice& d,
  89. uint64_t offset, asio::basic_streambuf<Allocator>& b,
  90. CompletionCondition completion_condition, asio::error_code& ec)
  91. {
  92. ec = asio::error_code();
  93. std::size_t total_transferred = 0;
  94. std::size_t max_size = detail::adapt_completion_condition_result(
  95. completion_condition(ec, total_transferred));
  96. std::size_t bytes_available = read_size_helper(b, max_size);
  97. while (bytes_available > 0)
  98. {
  99. std::size_t bytes_transferred = d.read_some_at(
  100. offset + total_transferred, b.prepare(bytes_available), ec);
  101. b.commit(bytes_transferred);
  102. total_transferred += bytes_transferred;
  103. max_size = detail::adapt_completion_condition_result(
  104. completion_condition(ec, total_transferred));
  105. bytes_available = read_size_helper(b, max_size);
  106. }
  107. return total_transferred;
  108. }
  109. template <typename SyncRandomAccessReadDevice, typename Allocator>
  110. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  111. uint64_t offset, asio::basic_streambuf<Allocator>& b)
  112. {
  113. asio::error_code ec;
  114. std::size_t bytes_transferred = read_at(
  115. d, offset, b, transfer_all(), ec);
  116. asio::detail::throw_error(ec, "read_at");
  117. return bytes_transferred;
  118. }
  119. template <typename SyncRandomAccessReadDevice, typename Allocator>
  120. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  121. uint64_t offset, asio::basic_streambuf<Allocator>& b,
  122. asio::error_code& ec)
  123. {
  124. return read_at(d, offset, b, transfer_all(), ec);
  125. }
  126. template <typename SyncRandomAccessReadDevice, typename Allocator,
  127. typename CompletionCondition>
  128. inline std::size_t read_at(SyncRandomAccessReadDevice& d,
  129. uint64_t offset, asio::basic_streambuf<Allocator>& b,
  130. CompletionCondition completion_condition)
  131. {
  132. asio::error_code ec;
  133. std::size_t bytes_transferred = read_at(
  134. d, offset, b, completion_condition, ec);
  135. asio::detail::throw_error(ec, "read_at");
  136. return bytes_transferred;
  137. }
  138. #endif // !defined(ASIO_NO_IOSTREAM)
  139. namespace detail
  140. {
  141. template <typename AsyncRandomAccessReadDevice,
  142. typename MutableBufferSequence, typename CompletionCondition,
  143. typename ReadHandler>
  144. class read_at_op
  145. : detail::base_from_completion_cond<CompletionCondition>
  146. {
  147. public:
  148. read_at_op(AsyncRandomAccessReadDevice& device,
  149. uint64_t offset, const MutableBufferSequence& buffers,
  150. CompletionCondition completion_condition, ReadHandler& handler)
  151. : detail::base_from_completion_cond<
  152. CompletionCondition>(completion_condition),
  153. device_(device),
  154. offset_(offset),
  155. buffers_(buffers),
  156. start_(0),
  157. total_transferred_(0),
  158. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  159. {
  160. }
  161. #if defined(ASIO_HAS_MOVE)
  162. read_at_op(const read_at_op& other)
  163. : detail::base_from_completion_cond<CompletionCondition>(other),
  164. device_(other.device_),
  165. offset_(other.offset_),
  166. buffers_(other.buffers_),
  167. start_(other.start_),
  168. total_transferred_(other.total_transferred_),
  169. handler_(other.handler_)
  170. {
  171. }
  172. read_at_op(read_at_op&& other)
  173. : detail::base_from_completion_cond<CompletionCondition>(other),
  174. device_(other.device_),
  175. offset_(other.offset_),
  176. buffers_(other.buffers_),
  177. start_(other.start_),
  178. total_transferred_(other.total_transferred_),
  179. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  180. {
  181. }
  182. #endif // defined(ASIO_HAS_MOVE)
  183. void operator()(const asio::error_code& ec,
  184. std::size_t bytes_transferred, int start = 0)
  185. {
  186. switch (start_ = start)
  187. {
  188. case 1:
  189. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  190. for (;;)
  191. {
  192. device_.async_read_some_at(offset_ + total_transferred_,
  193. buffers_, ASIO_MOVE_CAST(read_at_op)(*this));
  194. return; default:
  195. total_transferred_ += bytes_transferred;
  196. buffers_.consume(bytes_transferred);
  197. buffers_.prepare(this->check_for_completion(ec, total_transferred_));
  198. if ((!ec && bytes_transferred == 0)
  199. || buffers_.begin() == buffers_.end())
  200. break;
  201. }
  202. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  203. }
  204. }
  205. //private:
  206. AsyncRandomAccessReadDevice& device_;
  207. uint64_t offset_;
  208. asio::detail::consuming_buffers<
  209. mutable_buffer, MutableBufferSequence> buffers_;
  210. int start_;
  211. std::size_t total_transferred_;
  212. ReadHandler handler_;
  213. };
  214. template <typename AsyncRandomAccessReadDevice,
  215. typename CompletionCondition, typename ReadHandler>
  216. class read_at_op<AsyncRandomAccessReadDevice,
  217. asio::mutable_buffers_1, CompletionCondition, ReadHandler>
  218. : detail::base_from_completion_cond<CompletionCondition>
  219. {
  220. public:
  221. read_at_op(AsyncRandomAccessReadDevice& device,
  222. uint64_t offset, const asio::mutable_buffers_1& buffers,
  223. CompletionCondition completion_condition, ReadHandler& handler)
  224. : detail::base_from_completion_cond<
  225. CompletionCondition>(completion_condition),
  226. device_(device),
  227. offset_(offset),
  228. buffer_(buffers),
  229. start_(0),
  230. total_transferred_(0),
  231. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  232. {
  233. }
  234. #if defined(ASIO_HAS_MOVE)
  235. read_at_op(const read_at_op& other)
  236. : detail::base_from_completion_cond<CompletionCondition>(other),
  237. device_(other.device_),
  238. offset_(other.offset_),
  239. buffer_(other.buffer_),
  240. start_(other.start_),
  241. total_transferred_(other.total_transferred_),
  242. handler_(other.handler_)
  243. {
  244. }
  245. read_at_op(read_at_op&& other)
  246. : detail::base_from_completion_cond<CompletionCondition>(other),
  247. device_(other.device_),
  248. offset_(other.offset_),
  249. buffer_(other.buffer_),
  250. start_(other.start_),
  251. total_transferred_(other.total_transferred_),
  252. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  253. {
  254. }
  255. #endif // defined(ASIO_HAS_MOVE)
  256. void operator()(const asio::error_code& ec,
  257. std::size_t bytes_transferred, int start = 0)
  258. {
  259. std::size_t n = 0;
  260. switch (start_ = start)
  261. {
  262. case 1:
  263. n = this->check_for_completion(ec, total_transferred_);
  264. for (;;)
  265. {
  266. device_.async_read_some_at(offset_ + total_transferred_,
  267. asio::buffer(buffer_ + total_transferred_, n),
  268. ASIO_MOVE_CAST(read_at_op)(*this));
  269. return; default:
  270. total_transferred_ += bytes_transferred;
  271. if ((!ec && bytes_transferred == 0)
  272. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  273. || total_transferred_ == buffer_.size())
  274. break;
  275. }
  276. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  277. }
  278. }
  279. //private:
  280. AsyncRandomAccessReadDevice& device_;
  281. uint64_t offset_;
  282. asio::mutable_buffer buffer_;
  283. int start_;
  284. std::size_t total_transferred_;
  285. ReadHandler handler_;
  286. };
  287. template <typename AsyncRandomAccessReadDevice, typename Elem,
  288. typename CompletionCondition, typename ReadHandler>
  289. class read_at_op<AsyncRandomAccessReadDevice, boost::array<Elem, 2>,
  290. CompletionCondition, ReadHandler>
  291. : detail::base_from_completion_cond<CompletionCondition>
  292. {
  293. public:
  294. read_at_op(AsyncRandomAccessReadDevice& device,
  295. uint64_t offset, const boost::array<Elem, 2>& buffers,
  296. CompletionCondition completion_condition, ReadHandler& handler)
  297. : detail::base_from_completion_cond<
  298. CompletionCondition>(completion_condition),
  299. device_(device),
  300. offset_(offset),
  301. buffers_(buffers),
  302. start_(0),
  303. total_transferred_(0),
  304. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  305. {
  306. }
  307. #if defined(ASIO_HAS_MOVE)
  308. read_at_op(const read_at_op& other)
  309. : detail::base_from_completion_cond<CompletionCondition>(other),
  310. device_(other.device_),
  311. offset_(other.offset_),
  312. buffers_(other.buffers_),
  313. start_(other.start_),
  314. total_transferred_(other.total_transferred_),
  315. handler_(other.handler_)
  316. {
  317. }
  318. read_at_op(read_at_op&& other)
  319. : detail::base_from_completion_cond<CompletionCondition>(other),
  320. device_(other.device_),
  321. offset_(other.offset_),
  322. buffers_(other.buffers_),
  323. start_(other.start_),
  324. total_transferred_(other.total_transferred_),
  325. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  326. {
  327. }
  328. #endif // defined(ASIO_HAS_MOVE)
  329. void operator()(const asio::error_code& ec,
  330. std::size_t bytes_transferred, int start = 0)
  331. {
  332. typename asio::detail::dependent_type<Elem,
  333. boost::array<asio::mutable_buffer, 2> >::type bufs = {{
  334. asio::mutable_buffer(buffers_[0]),
  335. asio::mutable_buffer(buffers_[1]) }};
  336. std::size_t buffer_size0 = bufs[0].size();
  337. std::size_t buffer_size1 = bufs[1].size();
  338. std::size_t n = 0;
  339. switch (start_ = start)
  340. {
  341. case 1:
  342. n = this->check_for_completion(ec, total_transferred_);
  343. for (;;)
  344. {
  345. bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
  346. bufs[1] = asio::buffer(
  347. bufs[1] + (total_transferred_ < buffer_size0
  348. ? 0 : total_transferred_ - buffer_size0),
  349. n - bufs[0].size());
  350. device_.async_read_some_at(offset_ + total_transferred_,
  351. bufs, ASIO_MOVE_CAST(read_at_op)(*this));
  352. return; default:
  353. total_transferred_ += bytes_transferred;
  354. if ((!ec && bytes_transferred == 0)
  355. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  356. || total_transferred_ == buffer_size0 + buffer_size1)
  357. break;
  358. }
  359. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  360. }
  361. }
  362. //private:
  363. AsyncRandomAccessReadDevice& device_;
  364. uint64_t offset_;
  365. boost::array<Elem, 2> buffers_;
  366. int start_;
  367. std::size_t total_transferred_;
  368. ReadHandler handler_;
  369. };
  370. #if defined(ASIO_HAS_STD_ARRAY)
  371. template <typename AsyncRandomAccessReadDevice, typename Elem,
  372. typename CompletionCondition, typename ReadHandler>
  373. class read_at_op<AsyncRandomAccessReadDevice, std::array<Elem, 2>,
  374. CompletionCondition, ReadHandler>
  375. : detail::base_from_completion_cond<CompletionCondition>
  376. {
  377. public:
  378. read_at_op(AsyncRandomAccessReadDevice& device,
  379. uint64_t offset, const std::array<Elem, 2>& buffers,
  380. CompletionCondition completion_condition, ReadHandler& handler)
  381. : detail::base_from_completion_cond<
  382. CompletionCondition>(completion_condition),
  383. device_(device),
  384. offset_(offset),
  385. buffers_(buffers),
  386. start_(0),
  387. total_transferred_(0),
  388. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  389. {
  390. }
  391. #if defined(ASIO_HAS_MOVE)
  392. read_at_op(const read_at_op& other)
  393. : detail::base_from_completion_cond<CompletionCondition>(other),
  394. device_(other.device_),
  395. offset_(other.offset_),
  396. buffers_(other.buffers_),
  397. start_(other.start_),
  398. total_transferred_(other.total_transferred_),
  399. handler_(other.handler_)
  400. {
  401. }
  402. read_at_op(read_at_op&& other)
  403. : detail::base_from_completion_cond<CompletionCondition>(other),
  404. device_(other.device_),
  405. offset_(other.offset_),
  406. buffers_(other.buffers_),
  407. start_(other.start_),
  408. total_transferred_(other.total_transferred_),
  409. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  410. {
  411. }
  412. #endif // defined(ASIO_HAS_MOVE)
  413. void operator()(const asio::error_code& ec,
  414. std::size_t bytes_transferred, int start = 0)
  415. {
  416. typename asio::detail::dependent_type<Elem,
  417. std::array<asio::mutable_buffer, 2> >::type bufs = {{
  418. asio::mutable_buffer(buffers_[0]),
  419. asio::mutable_buffer(buffers_[1]) }};
  420. std::size_t buffer_size0 = bufs[0].size();
  421. std::size_t buffer_size1 = bufs[1].size();
  422. std::size_t n = 0;
  423. switch (start_ = start)
  424. {
  425. case 1:
  426. n = this->check_for_completion(ec, total_transferred_);
  427. for (;;)
  428. {
  429. bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
  430. bufs[1] = asio::buffer(
  431. bufs[1] + (total_transferred_ < buffer_size0
  432. ? 0 : total_transferred_ - buffer_size0),
  433. n - bufs[0].size());
  434. device_.async_read_some_at(offset_ + total_transferred_,
  435. bufs, ASIO_MOVE_CAST(read_at_op)(*this));
  436. return; default:
  437. total_transferred_ += bytes_transferred;
  438. if ((!ec && bytes_transferred == 0)
  439. || (n = this->check_for_completion(ec, total_transferred_)) == 0
  440. || total_transferred_ == buffer_size0 + buffer_size1)
  441. break;
  442. }
  443. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  444. }
  445. }
  446. //private:
  447. AsyncRandomAccessReadDevice& device_;
  448. uint64_t offset_;
  449. std::array<Elem, 2> buffers_;
  450. int start_;
  451. std::size_t total_transferred_;
  452. ReadHandler handler_;
  453. };
  454. #endif // defined(ASIO_HAS_STD_ARRAY)
  455. template <typename AsyncRandomAccessReadDevice,
  456. typename MutableBufferSequence, typename CompletionCondition,
  457. typename ReadHandler>
  458. inline void* asio_handler_allocate(std::size_t size,
  459. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  460. CompletionCondition, ReadHandler>* this_handler)
  461. {
  462. return asio_handler_alloc_helpers::allocate(
  463. size, this_handler->handler_);
  464. }
  465. template <typename AsyncRandomAccessReadDevice,
  466. typename MutableBufferSequence, typename CompletionCondition,
  467. typename ReadHandler>
  468. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  469. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  470. CompletionCondition, ReadHandler>* this_handler)
  471. {
  472. asio_handler_alloc_helpers::deallocate(
  473. pointer, size, this_handler->handler_);
  474. }
  475. template <typename AsyncRandomAccessReadDevice,
  476. typename MutableBufferSequence, typename CompletionCondition,
  477. typename ReadHandler>
  478. inline bool asio_handler_is_continuation(
  479. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  480. CompletionCondition, ReadHandler>* this_handler)
  481. {
  482. return this_handler->start_ == 0 ? true
  483. : asio_handler_cont_helpers::is_continuation(
  484. this_handler->handler_);
  485. }
  486. template <typename Function, typename AsyncRandomAccessReadDevice,
  487. typename MutableBufferSequence, typename CompletionCondition,
  488. typename ReadHandler>
  489. inline void asio_handler_invoke(Function& function,
  490. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  491. CompletionCondition, ReadHandler>* this_handler)
  492. {
  493. asio_handler_invoke_helpers::invoke(
  494. function, this_handler->handler_);
  495. }
  496. template <typename Function, typename AsyncRandomAccessReadDevice,
  497. typename MutableBufferSequence, typename CompletionCondition,
  498. typename ReadHandler>
  499. inline void asio_handler_invoke(const Function& function,
  500. read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  501. CompletionCondition, ReadHandler>* this_handler)
  502. {
  503. asio_handler_invoke_helpers::invoke(
  504. function, this_handler->handler_);
  505. }
  506. template <typename AsyncRandomAccessReadDevice,
  507. typename MutableBufferSequence, typename CompletionCondition,
  508. typename ReadHandler>
  509. inline read_at_op<AsyncRandomAccessReadDevice,
  510. MutableBufferSequence, CompletionCondition, ReadHandler>
  511. make_read_at_op(AsyncRandomAccessReadDevice& d,
  512. uint64_t offset, const MutableBufferSequence& buffers,
  513. CompletionCondition completion_condition, ReadHandler handler)
  514. {
  515. return read_at_op<AsyncRandomAccessReadDevice,
  516. MutableBufferSequence, CompletionCondition, ReadHandler>(
  517. d, offset, buffers, completion_condition, handler);
  518. }
  519. } // namespace detail
  520. #if !defined(GENERATING_DOCUMENTATION)
  521. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  522. typename CompletionCondition, typename ReadHandler, typename Allocator>
  523. struct associated_allocator<
  524. detail::read_at_op<AsyncRandomAccessReadDevice,
  525. MutableBufferSequence, CompletionCondition, ReadHandler>,
  526. Allocator>
  527. {
  528. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  529. static type get(
  530. const detail::read_at_op<AsyncRandomAccessReadDevice,
  531. MutableBufferSequence, CompletionCondition, ReadHandler>& h,
  532. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  533. {
  534. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  535. }
  536. };
  537. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  538. typename CompletionCondition, typename ReadHandler, typename Executor>
  539. struct associated_executor<
  540. detail::read_at_op<AsyncRandomAccessReadDevice,
  541. MutableBufferSequence, CompletionCondition, ReadHandler>,
  542. Executor>
  543. {
  544. typedef typename associated_executor<ReadHandler, Executor>::type type;
  545. static type get(
  546. const detail::read_at_op<AsyncRandomAccessReadDevice,
  547. MutableBufferSequence, CompletionCondition, ReadHandler>& h,
  548. const Executor& ex = Executor()) ASIO_NOEXCEPT
  549. {
  550. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  551. }
  552. };
  553. #endif // !defined(GENERATING_DOCUMENTATION)
  554. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  555. typename CompletionCondition, typename ReadHandler>
  556. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  557. void (asio::error_code, std::size_t))
  558. async_read_at(AsyncRandomAccessReadDevice& d,
  559. uint64_t offset, const MutableBufferSequence& buffers,
  560. CompletionCondition completion_condition,
  561. ASIO_MOVE_ARG(ReadHandler) handler)
  562. {
  563. // If you get an error on the following line it means that your handler does
  564. // not meet the documented type requirements for a ReadHandler.
  565. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  566. async_completion<ReadHandler,
  567. void (asio::error_code, std::size_t)> init(handler);
  568. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  569. CompletionCondition, ASIO_HANDLER_TYPE(ReadHandler,
  570. void (asio::error_code, std::size_t))>(
  571. d, offset, buffers, completion_condition, init.handler)(
  572. asio::error_code(), 0, 1);
  573. return init.result.get();
  574. }
  575. template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
  576. typename ReadHandler>
  577. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  578. void (asio::error_code, std::size_t))
  579. async_read_at(AsyncRandomAccessReadDevice& d,
  580. uint64_t offset, const MutableBufferSequence& buffers,
  581. ASIO_MOVE_ARG(ReadHandler) handler)
  582. {
  583. // If you get an error on the following line it means that your handler does
  584. // not meet the documented type requirements for a ReadHandler.
  585. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  586. async_completion<ReadHandler,
  587. void (asio::error_code, std::size_t)> init(handler);
  588. detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
  589. detail::transfer_all_t, ASIO_HANDLER_TYPE(ReadHandler,
  590. void (asio::error_code, std::size_t))>(
  591. d, offset, buffers, transfer_all(), init.handler)(
  592. asio::error_code(), 0, 1);
  593. return init.result.get();
  594. }
  595. #if !defined(ASIO_NO_IOSTREAM)
  596. namespace detail
  597. {
  598. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  599. typename CompletionCondition, typename ReadHandler>
  600. class read_at_streambuf_op
  601. : detail::base_from_completion_cond<CompletionCondition>
  602. {
  603. public:
  604. read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
  605. uint64_t offset, basic_streambuf<Allocator>& streambuf,
  606. CompletionCondition completion_condition, ReadHandler& handler)
  607. : detail::base_from_completion_cond<
  608. CompletionCondition>(completion_condition),
  609. device_(device),
  610. offset_(offset),
  611. streambuf_(streambuf),
  612. start_(0),
  613. total_transferred_(0),
  614. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  615. {
  616. }
  617. #if defined(ASIO_HAS_MOVE)
  618. read_at_streambuf_op(const read_at_streambuf_op& other)
  619. : detail::base_from_completion_cond<CompletionCondition>(other),
  620. device_(other.device_),
  621. offset_(other.offset_),
  622. streambuf_(other.streambuf_),
  623. start_(other.start_),
  624. total_transferred_(other.total_transferred_),
  625. handler_(other.handler_)
  626. {
  627. }
  628. read_at_streambuf_op(read_at_streambuf_op&& other)
  629. : detail::base_from_completion_cond<CompletionCondition>(other),
  630. device_(other.device_),
  631. offset_(other.offset_),
  632. streambuf_(other.streambuf_),
  633. start_(other.start_),
  634. total_transferred_(other.total_transferred_),
  635. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  636. {
  637. }
  638. #endif // defined(ASIO_HAS_MOVE)
  639. void operator()(const asio::error_code& ec,
  640. std::size_t bytes_transferred, int start = 0)
  641. {
  642. std::size_t max_size, bytes_available;
  643. switch (start_ = start)
  644. {
  645. case 1:
  646. max_size = this->check_for_completion(ec, total_transferred_);
  647. bytes_available = read_size_helper(streambuf_, max_size);
  648. for (;;)
  649. {
  650. device_.async_read_some_at(offset_ + total_transferred_,
  651. streambuf_.prepare(bytes_available),
  652. ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
  653. return; default:
  654. total_transferred_ += bytes_transferred;
  655. streambuf_.commit(bytes_transferred);
  656. max_size = this->check_for_completion(ec, total_transferred_);
  657. bytes_available = read_size_helper(streambuf_, max_size);
  658. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  659. break;
  660. }
  661. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  662. }
  663. }
  664. //private:
  665. AsyncRandomAccessReadDevice& device_;
  666. uint64_t offset_;
  667. asio::basic_streambuf<Allocator>& streambuf_;
  668. int start_;
  669. std::size_t total_transferred_;
  670. ReadHandler handler_;
  671. };
  672. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  673. typename CompletionCondition, typename ReadHandler>
  674. inline void* asio_handler_allocate(std::size_t size,
  675. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  676. CompletionCondition, ReadHandler>* this_handler)
  677. {
  678. return asio_handler_alloc_helpers::allocate(
  679. size, this_handler->handler_);
  680. }
  681. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  682. typename CompletionCondition, typename ReadHandler>
  683. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  684. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  685. CompletionCondition, ReadHandler>* this_handler)
  686. {
  687. asio_handler_alloc_helpers::deallocate(
  688. pointer, size, this_handler->handler_);
  689. }
  690. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  691. typename CompletionCondition, typename ReadHandler>
  692. inline bool asio_handler_is_continuation(
  693. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  694. CompletionCondition, ReadHandler>* this_handler)
  695. {
  696. return this_handler->start_ == 0 ? true
  697. : asio_handler_cont_helpers::is_continuation(
  698. this_handler->handler_);
  699. }
  700. template <typename Function, typename AsyncRandomAccessReadDevice,
  701. typename Allocator, typename CompletionCondition, typename ReadHandler>
  702. inline void asio_handler_invoke(Function& function,
  703. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  704. CompletionCondition, ReadHandler>* this_handler)
  705. {
  706. asio_handler_invoke_helpers::invoke(
  707. function, this_handler->handler_);
  708. }
  709. template <typename Function, typename AsyncRandomAccessReadDevice,
  710. typename Allocator, typename CompletionCondition, typename ReadHandler>
  711. inline void asio_handler_invoke(const Function& function,
  712. read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  713. CompletionCondition, ReadHandler>* this_handler)
  714. {
  715. asio_handler_invoke_helpers::invoke(
  716. function, this_handler->handler_);
  717. }
  718. } // namespace detail
  719. #if !defined(GENERATING_DOCUMENTATION)
  720. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  721. typename CompletionCondition, typename ReadHandler, typename Allocator1>
  722. struct associated_allocator<
  723. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  724. Allocator, CompletionCondition, ReadHandler>,
  725. Allocator1>
  726. {
  727. typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
  728. static type get(
  729. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  730. Allocator, CompletionCondition, ReadHandler>& h,
  731. const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
  732. {
  733. return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
  734. }
  735. };
  736. template <typename AsyncRandomAccessReadDevice, typename Executor,
  737. typename CompletionCondition, typename ReadHandler, typename Executor1>
  738. struct associated_executor<
  739. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  740. Executor, CompletionCondition, ReadHandler>,
  741. Executor1>
  742. {
  743. typedef typename associated_executor<ReadHandler, Executor1>::type type;
  744. static type get(
  745. const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
  746. Executor, CompletionCondition, ReadHandler>& h,
  747. const Executor1& ex = Executor1()) ASIO_NOEXCEPT
  748. {
  749. return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
  750. }
  751. };
  752. #endif // !defined(GENERATING_DOCUMENTATION)
  753. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  754. typename CompletionCondition, typename ReadHandler>
  755. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  756. void (asio::error_code, std::size_t))
  757. async_read_at(AsyncRandomAccessReadDevice& d,
  758. uint64_t offset, asio::basic_streambuf<Allocator>& b,
  759. CompletionCondition completion_condition,
  760. ASIO_MOVE_ARG(ReadHandler) handler)
  761. {
  762. // If you get an error on the following line it means that your handler does
  763. // not meet the documented type requirements for a ReadHandler.
  764. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  765. async_completion<ReadHandler,
  766. void (asio::error_code, std::size_t)> init(handler);
  767. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  768. CompletionCondition, ASIO_HANDLER_TYPE(ReadHandler,
  769. void (asio::error_code, std::size_t))>(
  770. d, offset, b, completion_condition, init.handler)(
  771. asio::error_code(), 0, 1);
  772. return init.result.get();
  773. }
  774. template <typename AsyncRandomAccessReadDevice, typename Allocator,
  775. typename ReadHandler>
  776. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  777. void (asio::error_code, std::size_t))
  778. async_read_at(AsyncRandomAccessReadDevice& d,
  779. uint64_t offset, asio::basic_streambuf<Allocator>& b,
  780. ASIO_MOVE_ARG(ReadHandler) handler)
  781. {
  782. // If you get an error on the following line it means that your handler does
  783. // not meet the documented type requirements for a ReadHandler.
  784. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  785. async_completion<ReadHandler,
  786. void (asio::error_code, std::size_t)> init(handler);
  787. detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
  788. detail::transfer_all_t, ASIO_HANDLER_TYPE(ReadHandler,
  789. void (asio::error_code, std::size_t))>(
  790. d, offset, b, transfer_all(), init.handler)(
  791. asio::error_code(), 0, 1);
  792. return init.result.get();
  793. }
  794. #endif // !defined(ASIO_NO_IOSTREAM)
  795. } // namespace asio
  796. #include "asio/detail/pop_options.hpp"
  797. #endif // ASIO_IMPL_READ_AT_HPP