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.

656 lines
24KB

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