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.

1080 lines
39KB

  1. //
  2. // impl/read.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_HPP
  11. #define ASIO_IMPL_READ_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 SyncReadStream, typename MutableBufferSequence,
  37. typename MutableBufferIterator, typename CompletionCondition>
  38. std::size_t read_buffer_sequence(SyncReadStream& s,
  39. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  40. CompletionCondition completion_condition, asio::error_code& ec)
  41. {
  42. ec = asio::error_code();
  43. asio::detail::consuming_buffers<mutable_buffer,
  44. MutableBufferSequence, MutableBufferIterator> tmp(buffers);
  45. while (!tmp.empty())
  46. {
  47. if (std::size_t max_size = detail::adapt_completion_condition_result(
  48. completion_condition(ec, tmp.total_consumed())))
  49. tmp.consume(s.read_some(tmp.prepare(max_size), ec));
  50. else
  51. break;
  52. }
  53. return tmp.total_consumed();;
  54. }
  55. } // namespace detail
  56. template <typename SyncReadStream, typename MutableBufferSequence,
  57. typename CompletionCondition>
  58. std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  59. CompletionCondition completion_condition, asio::error_code& ec,
  60. typename enable_if<
  61. is_mutable_buffer_sequence<MutableBufferSequence>::value
  62. >::type*)
  63. {
  64. return detail::read_buffer_sequence(s, buffers,
  65. asio::buffer_sequence_begin(buffers),
  66. ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  67. }
  68. template <typename SyncReadStream, typename MutableBufferSequence>
  69. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  70. typename enable_if<
  71. is_mutable_buffer_sequence<MutableBufferSequence>::value
  72. >::type*)
  73. {
  74. asio::error_code ec;
  75. std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
  76. asio::detail::throw_error(ec, "read");
  77. return bytes_transferred;
  78. }
  79. template <typename SyncReadStream, typename MutableBufferSequence>
  80. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  81. asio::error_code& ec,
  82. typename enable_if<
  83. is_mutable_buffer_sequence<MutableBufferSequence>::value
  84. >::type*)
  85. {
  86. return read(s, buffers, transfer_all(), ec);
  87. }
  88. template <typename SyncReadStream, typename MutableBufferSequence,
  89. typename CompletionCondition>
  90. inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
  91. CompletionCondition completion_condition,
  92. typename enable_if<
  93. is_mutable_buffer_sequence<MutableBufferSequence>::value
  94. >::type*)
  95. {
  96. asio::error_code ec;
  97. std::size_t bytes_transferred = read(s, buffers,
  98. ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  99. asio::detail::throw_error(ec, "read");
  100. return bytes_transferred;
  101. }
  102. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  103. template <typename SyncReadStream, typename DynamicBuffer_v1,
  104. typename CompletionCondition>
  105. std::size_t read(SyncReadStream& s,
  106. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  107. CompletionCondition completion_condition, asio::error_code& ec,
  108. typename enable_if<
  109. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  110. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  111. >::type*)
  112. {
  113. typename decay<DynamicBuffer_v1>::type b(
  114. ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));
  115. ec = asio::error_code();
  116. std::size_t total_transferred = 0;
  117. std::size_t max_size = detail::adapt_completion_condition_result(
  118. completion_condition(ec, total_transferred));
  119. std::size_t bytes_available = std::min<std::size_t>(
  120. std::max<std::size_t>(512, b.capacity() - b.size()),
  121. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  122. while (bytes_available > 0)
  123. {
  124. std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
  125. b.commit(bytes_transferred);
  126. total_transferred += bytes_transferred;
  127. max_size = detail::adapt_completion_condition_result(
  128. completion_condition(ec, total_transferred));
  129. bytes_available = std::min<std::size_t>(
  130. std::max<std::size_t>(512, b.capacity() - b.size()),
  131. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  132. }
  133. return total_transferred;
  134. }
  135. template <typename SyncReadStream, typename DynamicBuffer_v1>
  136. inline std::size_t read(SyncReadStream& s,
  137. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  138. typename enable_if<
  139. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  140. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  141. >::type*)
  142. {
  143. asio::error_code ec;
  144. std::size_t bytes_transferred = read(s,
  145. ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);
  146. asio::detail::throw_error(ec, "read");
  147. return bytes_transferred;
  148. }
  149. template <typename SyncReadStream, typename DynamicBuffer_v1>
  150. inline std::size_t read(SyncReadStream& s,
  151. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  152. asio::error_code& ec,
  153. typename enable_if<
  154. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  155. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  156. >::type*)
  157. {
  158. return read(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  159. transfer_all(), ec);
  160. }
  161. template <typename SyncReadStream, typename DynamicBuffer_v1,
  162. typename CompletionCondition>
  163. inline std::size_t read(SyncReadStream& s,
  164. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  165. CompletionCondition completion_condition,
  166. typename enable_if<
  167. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  168. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  169. >::type*)
  170. {
  171. asio::error_code ec;
  172. std::size_t bytes_transferred = read(s,
  173. ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  174. ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  175. asio::detail::throw_error(ec, "read");
  176. return bytes_transferred;
  177. }
  178. #if !defined(ASIO_NO_EXTENSIONS)
  179. #if !defined(ASIO_NO_IOSTREAM)
  180. template <typename SyncReadStream, typename Allocator,
  181. typename CompletionCondition>
  182. inline std::size_t read(SyncReadStream& s,
  183. asio::basic_streambuf<Allocator>& b,
  184. CompletionCondition completion_condition, asio::error_code& ec)
  185. {
  186. return read(s, basic_streambuf_ref<Allocator>(b),
  187. ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  188. }
  189. template <typename SyncReadStream, typename Allocator>
  190. inline std::size_t read(SyncReadStream& s,
  191. asio::basic_streambuf<Allocator>& b)
  192. {
  193. return read(s, basic_streambuf_ref<Allocator>(b));
  194. }
  195. template <typename SyncReadStream, typename Allocator>
  196. inline std::size_t read(SyncReadStream& s,
  197. asio::basic_streambuf<Allocator>& b,
  198. asio::error_code& ec)
  199. {
  200. return read(s, basic_streambuf_ref<Allocator>(b), ec);
  201. }
  202. template <typename SyncReadStream, typename Allocator,
  203. typename CompletionCondition>
  204. inline std::size_t read(SyncReadStream& s,
  205. asio::basic_streambuf<Allocator>& b,
  206. CompletionCondition completion_condition)
  207. {
  208. return read(s, basic_streambuf_ref<Allocator>(b),
  209. ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  210. }
  211. #endif // !defined(ASIO_NO_IOSTREAM)
  212. #endif // !defined(ASIO_NO_EXTENSIONS)
  213. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  214. template <typename SyncReadStream, typename DynamicBuffer_v2,
  215. typename CompletionCondition>
  216. std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  217. CompletionCondition completion_condition, asio::error_code& ec,
  218. typename enable_if<
  219. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  220. >::type*)
  221. {
  222. DynamicBuffer_v2& b = buffers;
  223. ec = asio::error_code();
  224. std::size_t total_transferred = 0;
  225. std::size_t max_size = detail::adapt_completion_condition_result(
  226. completion_condition(ec, total_transferred));
  227. std::size_t bytes_available = std::min<std::size_t>(
  228. std::max<std::size_t>(512, b.capacity() - b.size()),
  229. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  230. while (bytes_available > 0)
  231. {
  232. std::size_t pos = b.size();
  233. b.grow(bytes_available);
  234. std::size_t bytes_transferred = s.read_some(
  235. b.data(pos, bytes_available), ec);
  236. b.shrink(bytes_available - bytes_transferred);
  237. total_transferred += bytes_transferred;
  238. max_size = detail::adapt_completion_condition_result(
  239. completion_condition(ec, total_transferred));
  240. bytes_available = std::min<std::size_t>(
  241. std::max<std::size_t>(512, b.capacity() - b.size()),
  242. std::min<std::size_t>(max_size, b.max_size() - b.size()));
  243. }
  244. return total_transferred;
  245. }
  246. template <typename SyncReadStream, typename DynamicBuffer_v2>
  247. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  248. typename enable_if<
  249. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  250. >::type*)
  251. {
  252. asio::error_code ec;
  253. std::size_t bytes_transferred = read(s,
  254. ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);
  255. asio::detail::throw_error(ec, "read");
  256. return bytes_transferred;
  257. }
  258. template <typename SyncReadStream, typename DynamicBuffer_v2>
  259. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  260. asio::error_code& ec,
  261. typename enable_if<
  262. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  263. >::type*)
  264. {
  265. return read(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  266. transfer_all(), ec);
  267. }
  268. template <typename SyncReadStream, typename DynamicBuffer_v2,
  269. typename CompletionCondition>
  270. inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,
  271. CompletionCondition completion_condition,
  272. typename enable_if<
  273. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  274. >::type*)
  275. {
  276. asio::error_code ec;
  277. std::size_t bytes_transferred = read(s,
  278. ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  279. ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
  280. asio::detail::throw_error(ec, "read");
  281. return bytes_transferred;
  282. }
  283. namespace detail
  284. {
  285. template <typename AsyncReadStream, typename MutableBufferSequence,
  286. typename MutableBufferIterator, typename CompletionCondition,
  287. typename ReadHandler>
  288. class read_op
  289. : detail::base_from_completion_cond<CompletionCondition>
  290. {
  291. public:
  292. read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
  293. CompletionCondition& completion_condition, ReadHandler& handler)
  294. : detail::base_from_completion_cond<
  295. CompletionCondition>(completion_condition),
  296. stream_(stream),
  297. buffers_(buffers),
  298. start_(0),
  299. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  300. {
  301. }
  302. #if defined(ASIO_HAS_MOVE)
  303. read_op(const read_op& other)
  304. : detail::base_from_completion_cond<CompletionCondition>(other),
  305. stream_(other.stream_),
  306. buffers_(other.buffers_),
  307. start_(other.start_),
  308. handler_(other.handler_)
  309. {
  310. }
  311. read_op(read_op&& other)
  312. : detail::base_from_completion_cond<CompletionCondition>(
  313. ASIO_MOVE_CAST(detail::base_from_completion_cond<
  314. CompletionCondition>)(other)),
  315. stream_(other.stream_),
  316. buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
  317. start_(other.start_),
  318. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  319. {
  320. }
  321. #endif // defined(ASIO_HAS_MOVE)
  322. void operator()(const asio::error_code& ec,
  323. std::size_t bytes_transferred, int start = 0)
  324. {
  325. std::size_t max_size;
  326. switch (start_ = start)
  327. {
  328. case 1:
  329. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  330. do
  331. {
  332. stream_.async_read_some(buffers_.prepare(max_size),
  333. ASIO_MOVE_CAST(read_op)(*this));
  334. return; default:
  335. buffers_.consume(bytes_transferred);
  336. if ((!ec && bytes_transferred == 0) || buffers_.empty())
  337. break;
  338. max_size = this->check_for_completion(ec, buffers_.total_consumed());
  339. } while (max_size > 0);
  340. handler_(ec, buffers_.total_consumed());
  341. }
  342. }
  343. //private:
  344. typedef asio::detail::consuming_buffers<mutable_buffer,
  345. MutableBufferSequence, MutableBufferIterator> buffers_type;
  346. AsyncReadStream& stream_;
  347. buffers_type buffers_;
  348. int start_;
  349. ReadHandler handler_;
  350. };
  351. template <typename AsyncReadStream, typename MutableBufferSequence,
  352. typename MutableBufferIterator, typename CompletionCondition,
  353. typename ReadHandler>
  354. inline void* asio_handler_allocate(std::size_t size,
  355. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  356. CompletionCondition, ReadHandler>* this_handler)
  357. {
  358. return asio_handler_alloc_helpers::allocate(
  359. size, this_handler->handler_);
  360. }
  361. template <typename AsyncReadStream, typename MutableBufferSequence,
  362. typename MutableBufferIterator, typename CompletionCondition,
  363. typename ReadHandler>
  364. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  365. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  366. CompletionCondition, ReadHandler>* this_handler)
  367. {
  368. asio_handler_alloc_helpers::deallocate(
  369. pointer, size, this_handler->handler_);
  370. }
  371. template <typename AsyncReadStream, typename MutableBufferSequence,
  372. typename MutableBufferIterator, typename CompletionCondition,
  373. typename ReadHandler>
  374. inline bool asio_handler_is_continuation(
  375. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  376. CompletionCondition, ReadHandler>* this_handler)
  377. {
  378. return this_handler->start_ == 0 ? true
  379. : asio_handler_cont_helpers::is_continuation(
  380. this_handler->handler_);
  381. }
  382. template <typename Function, typename AsyncReadStream,
  383. typename MutableBufferSequence, typename MutableBufferIterator,
  384. typename CompletionCondition, typename ReadHandler>
  385. inline void asio_handler_invoke(Function& function,
  386. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  387. CompletionCondition, ReadHandler>* this_handler)
  388. {
  389. asio_handler_invoke_helpers::invoke(
  390. function, this_handler->handler_);
  391. }
  392. template <typename Function, typename AsyncReadStream,
  393. typename MutableBufferSequence, typename MutableBufferIterator,
  394. typename CompletionCondition, typename ReadHandler>
  395. inline void asio_handler_invoke(const Function& function,
  396. read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
  397. CompletionCondition, ReadHandler>* this_handler)
  398. {
  399. asio_handler_invoke_helpers::invoke(
  400. function, this_handler->handler_);
  401. }
  402. template <typename AsyncReadStream, typename MutableBufferSequence,
  403. typename MutableBufferIterator, typename CompletionCondition,
  404. typename ReadHandler>
  405. inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
  406. const MutableBufferSequence& buffers, const MutableBufferIterator&,
  407. CompletionCondition& completion_condition, ReadHandler& handler)
  408. {
  409. detail::read_op<AsyncReadStream, MutableBufferSequence,
  410. MutableBufferIterator, CompletionCondition, ReadHandler>(
  411. stream, buffers, completion_condition, handler)(
  412. asio::error_code(), 0, 1);
  413. }
  414. struct initiate_async_read_buffer_sequence
  415. {
  416. template <typename ReadHandler, typename AsyncReadStream,
  417. typename MutableBufferSequence, typename CompletionCondition>
  418. void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
  419. AsyncReadStream* s, const MutableBufferSequence& buffers,
  420. ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  421. {
  422. // If you get an error on the following line it means that your handler
  423. // does not meet the documented type requirements for a ReadHandler.
  424. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  425. non_const_lvalue<ReadHandler> handler2(handler);
  426. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  427. start_read_buffer_sequence_op(*s, buffers,
  428. asio::buffer_sequence_begin(buffers),
  429. completion_cond2.value, handler2.value);
  430. }
  431. };
  432. } // namespace detail
  433. #if !defined(GENERATING_DOCUMENTATION)
  434. template <typename AsyncReadStream, typename MutableBufferSequence,
  435. typename MutableBufferIterator, typename CompletionCondition,
  436. typename ReadHandler, typename Allocator>
  437. struct associated_allocator<
  438. detail::read_op<AsyncReadStream, MutableBufferSequence,
  439. MutableBufferIterator, CompletionCondition, ReadHandler>,
  440. Allocator>
  441. {
  442. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  443. static type get(
  444. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  445. MutableBufferIterator, CompletionCondition, ReadHandler>& h,
  446. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  447. {
  448. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  449. }
  450. };
  451. template <typename AsyncReadStream, typename MutableBufferSequence,
  452. typename MutableBufferIterator, typename CompletionCondition,
  453. typename ReadHandler, typename Executor>
  454. struct associated_executor<
  455. detail::read_op<AsyncReadStream, MutableBufferSequence,
  456. MutableBufferIterator, CompletionCondition, ReadHandler>,
  457. Executor>
  458. {
  459. typedef typename associated_executor<ReadHandler, Executor>::type type;
  460. static type get(
  461. const detail::read_op<AsyncReadStream, MutableBufferSequence,
  462. MutableBufferIterator, CompletionCondition, ReadHandler>& h,
  463. const Executor& ex = Executor()) ASIO_NOEXCEPT
  464. {
  465. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  466. }
  467. };
  468. #endif // !defined(GENERATING_DOCUMENTATION)
  469. template <typename AsyncReadStream, typename MutableBufferSequence,
  470. typename CompletionCondition, typename ReadHandler>
  471. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  472. void (asio::error_code, std::size_t))
  473. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  474. CompletionCondition completion_condition,
  475. ASIO_MOVE_ARG(ReadHandler) handler,
  476. typename enable_if<
  477. is_mutable_buffer_sequence<MutableBufferSequence>::value
  478. >::type*)
  479. {
  480. return async_initiate<ReadHandler,
  481. void (asio::error_code, std::size_t)>(
  482. detail::initiate_async_read_buffer_sequence(), handler, &s, buffers,
  483. ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  484. }
  485. template <typename AsyncReadStream, typename MutableBufferSequence,
  486. typename ReadHandler>
  487. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  488. void (asio::error_code, std::size_t))
  489. async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
  490. ASIO_MOVE_ARG(ReadHandler) handler,
  491. typename enable_if<
  492. is_mutable_buffer_sequence<MutableBufferSequence>::value
  493. >::type*)
  494. {
  495. return async_initiate<ReadHandler,
  496. void (asio::error_code, std::size_t)>(
  497. detail::initiate_async_read_buffer_sequence(),
  498. handler, &s, buffers, transfer_all());
  499. }
  500. #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  501. namespace detail
  502. {
  503. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  504. typename CompletionCondition, typename ReadHandler>
  505. class read_dynbuf_v1_op
  506. : detail::base_from_completion_cond<CompletionCondition>
  507. {
  508. public:
  509. template <typename BufferSequence>
  510. read_dynbuf_v1_op(AsyncReadStream& stream,
  511. ASIO_MOVE_ARG(BufferSequence) buffers,
  512. CompletionCondition& completion_condition, ReadHandler& handler)
  513. : detail::base_from_completion_cond<
  514. CompletionCondition>(completion_condition),
  515. stream_(stream),
  516. buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
  517. start_(0),
  518. total_transferred_(0),
  519. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  520. {
  521. }
  522. #if defined(ASIO_HAS_MOVE)
  523. read_dynbuf_v1_op(const read_dynbuf_v1_op& other)
  524. : detail::base_from_completion_cond<CompletionCondition>(other),
  525. stream_(other.stream_),
  526. buffers_(other.buffers_),
  527. start_(other.start_),
  528. total_transferred_(other.total_transferred_),
  529. handler_(other.handler_)
  530. {
  531. }
  532. read_dynbuf_v1_op(read_dynbuf_v1_op&& other)
  533. : detail::base_from_completion_cond<CompletionCondition>(
  534. ASIO_MOVE_CAST(detail::base_from_completion_cond<
  535. CompletionCondition>)(other)),
  536. stream_(other.stream_),
  537. buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),
  538. start_(other.start_),
  539. total_transferred_(other.total_transferred_),
  540. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  541. {
  542. }
  543. #endif // defined(ASIO_HAS_MOVE)
  544. void operator()(const asio::error_code& ec,
  545. std::size_t bytes_transferred, int start = 0)
  546. {
  547. std::size_t max_size, bytes_available;
  548. switch (start_ = start)
  549. {
  550. case 1:
  551. max_size = this->check_for_completion(ec, total_transferred_);
  552. bytes_available = std::min<std::size_t>(
  553. std::max<std::size_t>(512,
  554. buffers_.capacity() - buffers_.size()),
  555. std::min<std::size_t>(max_size,
  556. buffers_.max_size() - buffers_.size()));
  557. for (;;)
  558. {
  559. stream_.async_read_some(buffers_.prepare(bytes_available),
  560. ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));
  561. return; default:
  562. total_transferred_ += bytes_transferred;
  563. buffers_.commit(bytes_transferred);
  564. max_size = this->check_for_completion(ec, total_transferred_);
  565. bytes_available = std::min<std::size_t>(
  566. std::max<std::size_t>(512,
  567. buffers_.capacity() - buffers_.size()),
  568. std::min<std::size_t>(max_size,
  569. buffers_.max_size() - buffers_.size()));
  570. if ((!ec && bytes_transferred == 0) || bytes_available == 0)
  571. break;
  572. }
  573. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  574. }
  575. }
  576. //private:
  577. AsyncReadStream& stream_;
  578. DynamicBuffer_v1 buffers_;
  579. int start_;
  580. std::size_t total_transferred_;
  581. ReadHandler handler_;
  582. };
  583. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  584. typename CompletionCondition, typename ReadHandler>
  585. inline void* asio_handler_allocate(std::size_t size,
  586. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  587. CompletionCondition, ReadHandler>* this_handler)
  588. {
  589. return asio_handler_alloc_helpers::allocate(
  590. size, this_handler->handler_);
  591. }
  592. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  593. typename CompletionCondition, typename ReadHandler>
  594. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  595. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  596. CompletionCondition, ReadHandler>* this_handler)
  597. {
  598. asio_handler_alloc_helpers::deallocate(
  599. pointer, size, this_handler->handler_);
  600. }
  601. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  602. typename CompletionCondition, typename ReadHandler>
  603. inline bool asio_handler_is_continuation(
  604. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  605. CompletionCondition, ReadHandler>* this_handler)
  606. {
  607. return this_handler->start_ == 0 ? true
  608. : asio_handler_cont_helpers::is_continuation(
  609. this_handler->handler_);
  610. }
  611. template <typename Function, typename AsyncReadStream,
  612. typename DynamicBuffer_v1, typename CompletionCondition,
  613. typename ReadHandler>
  614. inline void asio_handler_invoke(Function& function,
  615. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  616. CompletionCondition, ReadHandler>* this_handler)
  617. {
  618. asio_handler_invoke_helpers::invoke(
  619. function, this_handler->handler_);
  620. }
  621. template <typename Function, typename AsyncReadStream,
  622. typename DynamicBuffer_v1, typename CompletionCondition,
  623. typename ReadHandler>
  624. inline void asio_handler_invoke(const Function& function,
  625. read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,
  626. CompletionCondition, ReadHandler>* this_handler)
  627. {
  628. asio_handler_invoke_helpers::invoke(
  629. function, this_handler->handler_);
  630. }
  631. struct initiate_async_read_dynbuf_v1
  632. {
  633. template <typename ReadHandler, typename AsyncReadStream,
  634. typename DynamicBuffer_v1, typename CompletionCondition>
  635. void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
  636. AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  637. ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  638. {
  639. // If you get an error on the following line it means that your handler
  640. // does not meet the documented type requirements for a ReadHandler.
  641. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  642. non_const_lvalue<ReadHandler> handler2(handler);
  643. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  644. read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,
  645. CompletionCondition, typename decay<ReadHandler>::type>(
  646. *s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  647. completion_cond2.value, handler2.value)(
  648. asio::error_code(), 0, 1);
  649. }
  650. };
  651. } // namespace detail
  652. #if !defined(GENERATING_DOCUMENTATION)
  653. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  654. typename CompletionCondition, typename ReadHandler, typename Allocator>
  655. struct associated_allocator<
  656. detail::read_dynbuf_v1_op<AsyncReadStream,
  657. DynamicBuffer_v1, CompletionCondition, ReadHandler>,
  658. Allocator>
  659. {
  660. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  661. static type get(
  662. const detail::read_dynbuf_v1_op<AsyncReadStream,
  663. DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
  664. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  665. {
  666. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  667. }
  668. };
  669. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  670. typename CompletionCondition, typename ReadHandler, typename Executor>
  671. struct associated_executor<
  672. detail::read_dynbuf_v1_op<AsyncReadStream,
  673. DynamicBuffer_v1, CompletionCondition, ReadHandler>,
  674. Executor>
  675. {
  676. typedef typename associated_executor<ReadHandler, Executor>::type type;
  677. static type get(
  678. const detail::read_dynbuf_v1_op<AsyncReadStream,
  679. DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,
  680. const Executor& ex = Executor()) ASIO_NOEXCEPT
  681. {
  682. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  683. }
  684. };
  685. #endif // !defined(GENERATING_DOCUMENTATION)
  686. template <typename AsyncReadStream,
  687. typename DynamicBuffer_v1, typename ReadHandler>
  688. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  689. void (asio::error_code, std::size_t))
  690. async_read(AsyncReadStream& s,
  691. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  692. ASIO_MOVE_ARG(ReadHandler) handler,
  693. typename enable_if<
  694. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  695. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  696. >::type*)
  697. {
  698. return async_read(s,
  699. ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  700. transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));
  701. }
  702. template <typename AsyncReadStream, typename DynamicBuffer_v1,
  703. typename CompletionCondition, typename ReadHandler>
  704. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  705. void (asio::error_code, std::size_t))
  706. async_read(AsyncReadStream& s,
  707. ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,
  708. CompletionCondition completion_condition,
  709. ASIO_MOVE_ARG(ReadHandler) handler,
  710. typename enable_if<
  711. is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value
  712. && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value
  713. >::type*)
  714. {
  715. // If you get an error on the following line it means that your handler does
  716. // not meet the documented type requirements for a ReadHandler.
  717. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  718. return async_initiate<ReadHandler,
  719. void (asio::error_code, std::size_t)>(
  720. detail::initiate_async_read_dynbuf_v1(), handler, &s,
  721. ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),
  722. ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  723. }
  724. #if !defined(ASIO_NO_EXTENSIONS)
  725. #if !defined(ASIO_NO_IOSTREAM)
  726. template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
  727. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  728. void (asio::error_code, std::size_t))
  729. async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
  730. ASIO_MOVE_ARG(ReadHandler) handler)
  731. {
  732. return async_read(s, basic_streambuf_ref<Allocator>(b),
  733. ASIO_MOVE_CAST(ReadHandler)(handler));
  734. }
  735. template <typename AsyncReadStream, typename Allocator,
  736. typename CompletionCondition, typename ReadHandler>
  737. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  738. void (asio::error_code, std::size_t))
  739. async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
  740. CompletionCondition completion_condition,
  741. ASIO_MOVE_ARG(ReadHandler) handler)
  742. {
  743. return async_read(s, basic_streambuf_ref<Allocator>(b),
  744. ASIO_MOVE_CAST(CompletionCondition)(completion_condition),
  745. ASIO_MOVE_CAST(ReadHandler)(handler));
  746. }
  747. #endif // !defined(ASIO_NO_IOSTREAM)
  748. #endif // !defined(ASIO_NO_EXTENSIONS)
  749. #endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)
  750. namespace detail
  751. {
  752. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  753. typename CompletionCondition, typename ReadHandler>
  754. class read_dynbuf_v2_op
  755. : detail::base_from_completion_cond<CompletionCondition>
  756. {
  757. public:
  758. template <typename BufferSequence>
  759. read_dynbuf_v2_op(AsyncReadStream& stream,
  760. ASIO_MOVE_ARG(BufferSequence) buffers,
  761. CompletionCondition& completion_condition, ReadHandler& handler)
  762. : detail::base_from_completion_cond<
  763. CompletionCondition>(completion_condition),
  764. stream_(stream),
  765. buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
  766. start_(0),
  767. total_transferred_(0),
  768. bytes_available_(0),
  769. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  770. {
  771. }
  772. #if defined(ASIO_HAS_MOVE)
  773. read_dynbuf_v2_op(const read_dynbuf_v2_op& other)
  774. : detail::base_from_completion_cond<CompletionCondition>(other),
  775. stream_(other.stream_),
  776. buffers_(other.buffers_),
  777. start_(other.start_),
  778. total_transferred_(other.total_transferred_),
  779. bytes_available_(other.bytes_available_),
  780. handler_(other.handler_)
  781. {
  782. }
  783. read_dynbuf_v2_op(read_dynbuf_v2_op&& other)
  784. : detail::base_from_completion_cond<CompletionCondition>(
  785. ASIO_MOVE_CAST(detail::base_from_completion_cond<
  786. CompletionCondition>)(other)),
  787. stream_(other.stream_),
  788. buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),
  789. start_(other.start_),
  790. total_transferred_(other.total_transferred_),
  791. bytes_available_(other.bytes_available_),
  792. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  793. {
  794. }
  795. #endif // defined(ASIO_HAS_MOVE)
  796. void operator()(const asio::error_code& ec,
  797. std::size_t bytes_transferred, int start = 0)
  798. {
  799. std::size_t max_size, pos;
  800. switch (start_ = start)
  801. {
  802. case 1:
  803. max_size = this->check_for_completion(ec, total_transferred_);
  804. bytes_available_ = std::min<std::size_t>(
  805. std::max<std::size_t>(512,
  806. buffers_.capacity() - buffers_.size()),
  807. std::min<std::size_t>(max_size,
  808. buffers_.max_size() - buffers_.size()));
  809. for (;;)
  810. {
  811. pos = buffers_.size();
  812. buffers_.grow(bytes_available_);
  813. stream_.async_read_some(buffers_.data(pos, bytes_available_),
  814. ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));
  815. return; default:
  816. total_transferred_ += bytes_transferred;
  817. buffers_.shrink(bytes_available_ - bytes_transferred);
  818. max_size = this->check_for_completion(ec, total_transferred_);
  819. bytes_available_ = std::min<std::size_t>(
  820. std::max<std::size_t>(512,
  821. buffers_.capacity() - buffers_.size()),
  822. std::min<std::size_t>(max_size,
  823. buffers_.max_size() - buffers_.size()));
  824. if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)
  825. break;
  826. }
  827. handler_(ec, static_cast<const std::size_t&>(total_transferred_));
  828. }
  829. }
  830. //private:
  831. AsyncReadStream& stream_;
  832. DynamicBuffer_v2 buffers_;
  833. int start_;
  834. std::size_t total_transferred_;
  835. std::size_t bytes_available_;
  836. ReadHandler handler_;
  837. };
  838. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  839. typename CompletionCondition, typename ReadHandler>
  840. inline void* asio_handler_allocate(std::size_t size,
  841. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  842. CompletionCondition, ReadHandler>* this_handler)
  843. {
  844. return asio_handler_alloc_helpers::allocate(
  845. size, this_handler->handler_);
  846. }
  847. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  848. typename CompletionCondition, typename ReadHandler>
  849. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  850. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  851. CompletionCondition, ReadHandler>* this_handler)
  852. {
  853. asio_handler_alloc_helpers::deallocate(
  854. pointer, size, this_handler->handler_);
  855. }
  856. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  857. typename CompletionCondition, typename ReadHandler>
  858. inline bool asio_handler_is_continuation(
  859. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  860. CompletionCondition, ReadHandler>* this_handler)
  861. {
  862. return this_handler->start_ == 0 ? true
  863. : asio_handler_cont_helpers::is_continuation(
  864. this_handler->handler_);
  865. }
  866. template <typename Function, typename AsyncReadStream,
  867. typename DynamicBuffer_v2, typename CompletionCondition,
  868. typename ReadHandler>
  869. inline void asio_handler_invoke(Function& function,
  870. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  871. CompletionCondition, ReadHandler>* this_handler)
  872. {
  873. asio_handler_invoke_helpers::invoke(
  874. function, this_handler->handler_);
  875. }
  876. template <typename Function, typename AsyncReadStream,
  877. typename DynamicBuffer_v2, typename CompletionCondition,
  878. typename ReadHandler>
  879. inline void asio_handler_invoke(const Function& function,
  880. read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,
  881. CompletionCondition, ReadHandler>* this_handler)
  882. {
  883. asio_handler_invoke_helpers::invoke(
  884. function, this_handler->handler_);
  885. }
  886. struct initiate_async_read_dynbuf_v2
  887. {
  888. template <typename ReadHandler, typename AsyncReadStream,
  889. typename DynamicBuffer_v2, typename CompletionCondition>
  890. void operator()(ASIO_MOVE_ARG(ReadHandler) handler,
  891. AsyncReadStream* s, ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,
  892. ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
  893. {
  894. // If you get an error on the following line it means that your handler
  895. // does not meet the documented type requirements for a ReadHandler.
  896. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  897. non_const_lvalue<ReadHandler> handler2(handler);
  898. non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
  899. read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,
  900. CompletionCondition, typename decay<ReadHandler>::type>(
  901. *s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  902. completion_cond2.value, handler2.value)(
  903. asio::error_code(), 0, 1);
  904. }
  905. };
  906. } // namespace detail
  907. #if !defined(GENERATING_DOCUMENTATION)
  908. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  909. typename CompletionCondition, typename ReadHandler, typename Allocator>
  910. struct associated_allocator<
  911. detail::read_dynbuf_v2_op<AsyncReadStream,
  912. DynamicBuffer_v2, CompletionCondition, ReadHandler>,
  913. Allocator>
  914. {
  915. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  916. static type get(
  917. const detail::read_dynbuf_v2_op<AsyncReadStream,
  918. DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
  919. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  920. {
  921. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  922. }
  923. };
  924. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  925. typename CompletionCondition, typename ReadHandler, typename Executor>
  926. struct associated_executor<
  927. detail::read_dynbuf_v2_op<AsyncReadStream,
  928. DynamicBuffer_v2, CompletionCondition, ReadHandler>,
  929. Executor>
  930. {
  931. typedef typename associated_executor<ReadHandler, Executor>::type type;
  932. static type get(
  933. const detail::read_dynbuf_v2_op<AsyncReadStream,
  934. DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,
  935. const Executor& ex = Executor()) ASIO_NOEXCEPT
  936. {
  937. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  938. }
  939. };
  940. #endif // !defined(GENERATING_DOCUMENTATION)
  941. template <typename AsyncReadStream,
  942. typename DynamicBuffer_v2, typename ReadHandler>
  943. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  944. void (asio::error_code, std::size_t))
  945. async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  946. ASIO_MOVE_ARG(ReadHandler) handler,
  947. typename enable_if<
  948. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  949. >::type*)
  950. {
  951. return async_read(s,
  952. ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  953. transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));
  954. }
  955. template <typename AsyncReadStream, typename DynamicBuffer_v2,
  956. typename CompletionCondition, typename ReadHandler>
  957. inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
  958. void (asio::error_code, std::size_t))
  959. async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,
  960. CompletionCondition completion_condition,
  961. ASIO_MOVE_ARG(ReadHandler) handler,
  962. typename enable_if<
  963. is_dynamic_buffer_v2<DynamicBuffer_v2>::value
  964. >::type*)
  965. {
  966. // If you get an error on the following line it means that your handler does
  967. // not meet the documented type requirements for a ReadHandler.
  968. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  969. return async_initiate<ReadHandler,
  970. void (asio::error_code, std::size_t)>(
  971. detail::initiate_async_read_dynbuf_v2(), handler, &s,
  972. ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),
  973. ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
  974. }
  975. } // namespace asio
  976. #include "asio/detail/pop_options.hpp"
  977. #endif // ASIO_IMPL_READ_HPP