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.

buffered_read_stream.hpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. //
  2. // impl/buffered_read_stream.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_BUFFERED_READ_STREAM_HPP
  11. #define ASIO_IMPL_BUFFERED_READ_STREAM_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/associated_allocator.hpp"
  16. #include "asio/associated_executor.hpp"
  17. #include "asio/detail/handler_alloc_helpers.hpp"
  18. #include "asio/detail/handler_cont_helpers.hpp"
  19. #include "asio/detail/handler_invoke_helpers.hpp"
  20. #include "asio/detail/handler_type_requirements.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. namespace asio {
  23. template <typename Stream>
  24. std::size_t buffered_read_stream<Stream>::fill()
  25. {
  26. detail::buffer_resize_guard<detail::buffered_stream_storage>
  27. resize_guard(storage_);
  28. std::size_t previous_size = storage_.size();
  29. storage_.resize(storage_.capacity());
  30. storage_.resize(previous_size + next_layer_.read_some(buffer(
  31. storage_.data() + previous_size,
  32. storage_.size() - previous_size)));
  33. resize_guard.commit();
  34. return storage_.size() - previous_size;
  35. }
  36. template <typename Stream>
  37. std::size_t buffered_read_stream<Stream>::fill(asio::error_code& ec)
  38. {
  39. detail::buffer_resize_guard<detail::buffered_stream_storage>
  40. resize_guard(storage_);
  41. std::size_t previous_size = storage_.size();
  42. storage_.resize(storage_.capacity());
  43. storage_.resize(previous_size + next_layer_.read_some(buffer(
  44. storage_.data() + previous_size,
  45. storage_.size() - previous_size),
  46. ec));
  47. resize_guard.commit();
  48. return storage_.size() - previous_size;
  49. }
  50. namespace detail
  51. {
  52. template <typename ReadHandler>
  53. class buffered_fill_handler
  54. {
  55. public:
  56. buffered_fill_handler(detail::buffered_stream_storage& storage,
  57. std::size_t previous_size, ReadHandler& handler)
  58. : storage_(storage),
  59. previous_size_(previous_size),
  60. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  61. {
  62. }
  63. #if defined(ASIO_HAS_MOVE)
  64. buffered_fill_handler(const buffered_fill_handler& other)
  65. : storage_(other.storage_),
  66. previous_size_(other.previous_size_),
  67. handler_(other.handler_)
  68. {
  69. }
  70. buffered_fill_handler(buffered_fill_handler&& other)
  71. : storage_(other.storage_),
  72. previous_size_(other.previous_size_),
  73. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  74. {
  75. }
  76. #endif // defined(ASIO_HAS_MOVE)
  77. void operator()(const asio::error_code& ec,
  78. const std::size_t bytes_transferred)
  79. {
  80. storage_.resize(previous_size_ + bytes_transferred);
  81. handler_(ec, bytes_transferred);
  82. }
  83. //private:
  84. detail::buffered_stream_storage& storage_;
  85. std::size_t previous_size_;
  86. ReadHandler handler_;
  87. };
  88. template <typename ReadHandler>
  89. inline void* asio_handler_allocate(std::size_t size,
  90. buffered_fill_handler<ReadHandler>* this_handler)
  91. {
  92. return asio_handler_alloc_helpers::allocate(
  93. size, this_handler->handler_);
  94. }
  95. template <typename ReadHandler>
  96. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  97. buffered_fill_handler<ReadHandler>* this_handler)
  98. {
  99. asio_handler_alloc_helpers::deallocate(
  100. pointer, size, this_handler->handler_);
  101. }
  102. template <typename ReadHandler>
  103. inline bool asio_handler_is_continuation(
  104. buffered_fill_handler<ReadHandler>* this_handler)
  105. {
  106. return asio_handler_cont_helpers::is_continuation(
  107. this_handler->handler_);
  108. }
  109. template <typename Function, typename ReadHandler>
  110. inline void asio_handler_invoke(Function& function,
  111. buffered_fill_handler<ReadHandler>* this_handler)
  112. {
  113. asio_handler_invoke_helpers::invoke(
  114. function, this_handler->handler_);
  115. }
  116. template <typename Function, typename ReadHandler>
  117. inline void asio_handler_invoke(const Function& function,
  118. buffered_fill_handler<ReadHandler>* this_handler)
  119. {
  120. asio_handler_invoke_helpers::invoke(
  121. function, this_handler->handler_);
  122. }
  123. } // namespace detail
  124. #if !defined(GENERATING_DOCUMENTATION)
  125. template <typename ReadHandler, typename Allocator>
  126. struct associated_allocator<
  127. detail::buffered_fill_handler<ReadHandler>, Allocator>
  128. {
  129. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  130. static type get(const detail::buffered_fill_handler<ReadHandler>& h,
  131. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  132. {
  133. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  134. }
  135. };
  136. template <typename ReadHandler, typename Executor>
  137. struct associated_executor<
  138. detail::buffered_fill_handler<ReadHandler>, Executor>
  139. {
  140. typedef typename associated_executor<ReadHandler, Executor>::type type;
  141. static type get(const detail::buffered_fill_handler<ReadHandler>& h,
  142. const Executor& ex = Executor()) ASIO_NOEXCEPT
  143. {
  144. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  145. }
  146. };
  147. #endif // !defined(GENERATING_DOCUMENTATION)
  148. template <typename Stream>
  149. template <typename ReadHandler>
  150. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  151. void (asio::error_code, std::size_t))
  152. buffered_read_stream<Stream>::async_fill(
  153. ASIO_MOVE_ARG(ReadHandler) handler)
  154. {
  155. // If you get an error on the following line it means that your handler does
  156. // not meet the documented type requirements for a ReadHandler.
  157. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  158. async_completion<ReadHandler,
  159. void (asio::error_code, std::size_t)> init(handler);
  160. std::size_t previous_size = storage_.size();
  161. storage_.resize(storage_.capacity());
  162. next_layer_.async_read_some(
  163. buffer(
  164. storage_.data() + previous_size,
  165. storage_.size() - previous_size),
  166. detail::buffered_fill_handler<ASIO_HANDLER_TYPE(
  167. ReadHandler, void (asio::error_code, std::size_t))>(
  168. storage_, previous_size, init.handler));
  169. return init.result.get();
  170. }
  171. template <typename Stream>
  172. template <typename MutableBufferSequence>
  173. std::size_t buffered_read_stream<Stream>::read_some(
  174. const MutableBufferSequence& buffers)
  175. {
  176. if (asio::buffer_size(buffers) == 0)
  177. return 0;
  178. if (storage_.empty())
  179. this->fill();
  180. return this->copy(buffers);
  181. }
  182. template <typename Stream>
  183. template <typename MutableBufferSequence>
  184. std::size_t buffered_read_stream<Stream>::read_some(
  185. const MutableBufferSequence& buffers, asio::error_code& ec)
  186. {
  187. ec = asio::error_code();
  188. if (asio::buffer_size(buffers) == 0)
  189. return 0;
  190. if (storage_.empty() && !this->fill(ec))
  191. return 0;
  192. return this->copy(buffers);
  193. }
  194. namespace detail
  195. {
  196. template <typename MutableBufferSequence, typename ReadHandler>
  197. class buffered_read_some_handler
  198. {
  199. public:
  200. buffered_read_some_handler(detail::buffered_stream_storage& storage,
  201. const MutableBufferSequence& buffers, ReadHandler& handler)
  202. : storage_(storage),
  203. buffers_(buffers),
  204. handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
  205. {
  206. }
  207. #if defined(ASIO_HAS_MOVE)
  208. buffered_read_some_handler(const buffered_read_some_handler& other)
  209. : storage_(other.storage_),
  210. buffers_(other.buffers_),
  211. handler_(other.handler_)
  212. {
  213. }
  214. buffered_read_some_handler(buffered_read_some_handler&& other)
  215. : storage_(other.storage_),
  216. buffers_(other.buffers_),
  217. handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
  218. {
  219. }
  220. #endif // defined(ASIO_HAS_MOVE)
  221. void operator()(const asio::error_code& ec, std::size_t)
  222. {
  223. if (ec || storage_.empty())
  224. {
  225. const std::size_t length = 0;
  226. handler_(ec, length);
  227. }
  228. else
  229. {
  230. const std::size_t bytes_copied = asio::buffer_copy(
  231. buffers_, storage_.data(), storage_.size());
  232. storage_.consume(bytes_copied);
  233. handler_(ec, bytes_copied);
  234. }
  235. }
  236. //private:
  237. detail::buffered_stream_storage& storage_;
  238. MutableBufferSequence buffers_;
  239. ReadHandler handler_;
  240. };
  241. template <typename MutableBufferSequence, typename ReadHandler>
  242. inline void* asio_handler_allocate(std::size_t size,
  243. buffered_read_some_handler<
  244. MutableBufferSequence, ReadHandler>* this_handler)
  245. {
  246. return asio_handler_alloc_helpers::allocate(
  247. size, this_handler->handler_);
  248. }
  249. template <typename MutableBufferSequence, typename ReadHandler>
  250. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  251. buffered_read_some_handler<
  252. MutableBufferSequence, ReadHandler>* this_handler)
  253. {
  254. asio_handler_alloc_helpers::deallocate(
  255. pointer, size, this_handler->handler_);
  256. }
  257. template <typename MutableBufferSequence, typename ReadHandler>
  258. inline bool asio_handler_is_continuation(
  259. buffered_read_some_handler<
  260. MutableBufferSequence, ReadHandler>* this_handler)
  261. {
  262. return asio_handler_cont_helpers::is_continuation(
  263. this_handler->handler_);
  264. }
  265. template <typename Function, typename MutableBufferSequence,
  266. typename ReadHandler>
  267. inline void asio_handler_invoke(Function& function,
  268. buffered_read_some_handler<
  269. MutableBufferSequence, ReadHandler>* this_handler)
  270. {
  271. asio_handler_invoke_helpers::invoke(
  272. function, this_handler->handler_);
  273. }
  274. template <typename Function, typename MutableBufferSequence,
  275. typename ReadHandler>
  276. inline void asio_handler_invoke(const Function& function,
  277. buffered_read_some_handler<
  278. MutableBufferSequence, ReadHandler>* this_handler)
  279. {
  280. asio_handler_invoke_helpers::invoke(
  281. function, this_handler->handler_);
  282. }
  283. } // namespace detail
  284. #if !defined(GENERATING_DOCUMENTATION)
  285. template <typename MutableBufferSequence,
  286. typename ReadHandler, typename Allocator>
  287. struct associated_allocator<
  288. detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
  289. Allocator>
  290. {
  291. typedef typename associated_allocator<ReadHandler, Allocator>::type type;
  292. static type get(
  293. const detail::buffered_read_some_handler<
  294. MutableBufferSequence, ReadHandler>& h,
  295. const Allocator& a = Allocator()) ASIO_NOEXCEPT
  296. {
  297. return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
  298. }
  299. };
  300. template <typename MutableBufferSequence,
  301. typename ReadHandler, typename Executor>
  302. struct associated_executor<
  303. detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
  304. Executor>
  305. {
  306. typedef typename associated_executor<ReadHandler, Executor>::type type;
  307. static type get(
  308. const detail::buffered_read_some_handler<
  309. MutableBufferSequence, ReadHandler>& h,
  310. const Executor& ex = Executor()) ASIO_NOEXCEPT
  311. {
  312. return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
  313. }
  314. };
  315. #endif // !defined(GENERATING_DOCUMENTATION)
  316. template <typename Stream>
  317. template <typename MutableBufferSequence, typename ReadHandler>
  318. ASIO_INITFN_RESULT_TYPE(ReadHandler,
  319. void (asio::error_code, std::size_t))
  320. buffered_read_stream<Stream>::async_read_some(
  321. const MutableBufferSequence& buffers,
  322. ASIO_MOVE_ARG(ReadHandler) handler)
  323. {
  324. // If you get an error on the following line it means that your handler does
  325. // not meet the documented type requirements for a ReadHandler.
  326. ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  327. async_completion<ReadHandler,
  328. void (asio::error_code, std::size_t)> init(handler);
  329. if (asio::buffer_size(buffers) == 0 || !storage_.empty())
  330. {
  331. next_layer_.async_read_some(asio::mutable_buffers_1(0, 0),
  332. detail::buffered_read_some_handler<
  333. MutableBufferSequence, ASIO_HANDLER_TYPE(
  334. ReadHandler, void (asio::error_code, std::size_t))>(
  335. storage_, buffers, init.handler));
  336. }
  337. else
  338. {
  339. this->async_fill(detail::buffered_read_some_handler<
  340. MutableBufferSequence, ASIO_HANDLER_TYPE(
  341. ReadHandler, void (asio::error_code, std::size_t))>(
  342. storage_, buffers, init.handler));
  343. }
  344. return init.result.get();
  345. }
  346. template <typename Stream>
  347. template <typename MutableBufferSequence>
  348. std::size_t buffered_read_stream<Stream>::peek(
  349. const MutableBufferSequence& buffers)
  350. {
  351. if (storage_.empty())
  352. this->fill();
  353. return this->peek_copy(buffers);
  354. }
  355. template <typename Stream>
  356. template <typename MutableBufferSequence>
  357. std::size_t buffered_read_stream<Stream>::peek(
  358. const MutableBufferSequence& buffers, asio::error_code& ec)
  359. {
  360. ec = asio::error_code();
  361. if (storage_.empty() && !this->fill(ec))
  362. return 0;
  363. return this->peek_copy(buffers);
  364. }
  365. } // namespace asio
  366. #include "asio/detail/pop_options.hpp"
  367. #endif // ASIO_IMPL_BUFFERED_READ_STREAM_HPP