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.

consuming_buffers.hpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. //
  2. // detail/consuming_buffers.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_DETAIL_CONSUMING_BUFFERS_HPP
  11. #define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include <cstddef>
  17. #include "asio/buffer.hpp"
  18. #include "asio/detail/buffer_sequence_adapter.hpp"
  19. #include "asio/detail/limits.hpp"
  20. #include "asio/detail/push_options.hpp"
  21. namespace asio {
  22. namespace detail {
  23. // Helper template to determine the maximum number of prepared buffers.
  24. template <typename Buffers>
  25. struct prepared_buffers_max
  26. {
  27. enum { value = buffer_sequence_adapter_base::max_buffers };
  28. };
  29. template <typename Elem, std::size_t N>
  30. struct prepared_buffers_max<boost::array<Elem, N> >
  31. {
  32. enum { value = N };
  33. };
  34. #if defined(ASIO_HAS_STD_ARRAY)
  35. template <typename Elem, std::size_t N>
  36. struct prepared_buffers_max<std::array<Elem, N> >
  37. {
  38. enum { value = N };
  39. };
  40. #endif // defined(ASIO_HAS_STD_ARRAY)
  41. // A buffer sequence used to represent a subsequence of the buffers.
  42. template <typename Buffer, std::size_t MaxBuffers>
  43. struct prepared_buffers
  44. {
  45. typedef Buffer value_type;
  46. typedef const Buffer* const_iterator;
  47. enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };
  48. prepared_buffers() : count(0) {}
  49. const_iterator begin() const { return elems; }
  50. const_iterator end() const { return elems + count; }
  51. Buffer elems[max_buffers];
  52. std::size_t count;
  53. };
  54. // A proxy for a sub-range in a list of buffers.
  55. template <typename Buffer, typename Buffers, typename Buffer_Iterator>
  56. class consuming_buffers
  57. {
  58. public:
  59. typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>
  60. prepared_buffers_type;
  61. // Construct to represent the entire list of buffers.
  62. explicit consuming_buffers(const Buffers& buffers)
  63. : buffers_(buffers),
  64. total_consumed_(0),
  65. next_elem_(0),
  66. next_elem_offset_(0)
  67. {
  68. using asio::buffer_size;
  69. total_size_ = buffer_size(buffers);
  70. }
  71. // Determine if we are at the end of the buffers.
  72. bool empty() const
  73. {
  74. return total_consumed_ >= total_size_;
  75. }
  76. // Get the buffer for a single transfer, with a size.
  77. prepared_buffers_type prepare(std::size_t max_size)
  78. {
  79. prepared_buffers_type result;
  80. Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);
  81. Buffer_Iterator end = asio::buffer_sequence_end(buffers_);
  82. std::advance(next, next_elem_);
  83. std::size_t elem_offset = next_elem_offset_;
  84. while (next != end && max_size > 0 && (result.count) < result.max_buffers)
  85. {
  86. Buffer next_buf = Buffer(*next) + elem_offset;
  87. result.elems[result.count] = asio::buffer(next_buf, max_size);
  88. max_size -= result.elems[result.count].size();
  89. elem_offset = 0;
  90. if (result.elems[result.count].size() > 0)
  91. ++result.count;
  92. ++next;
  93. }
  94. return result;
  95. }
  96. // Consume the specified number of bytes from the buffers.
  97. void consume(std::size_t size)
  98. {
  99. total_consumed_ += size;
  100. Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);
  101. Buffer_Iterator end = asio::buffer_sequence_end(buffers_);
  102. std::advance(next, next_elem_);
  103. while (next != end && size > 0)
  104. {
  105. Buffer next_buf = Buffer(*next) + next_elem_offset_;
  106. if (size < next_buf.size())
  107. {
  108. next_elem_offset_ += size;
  109. size = 0;
  110. }
  111. else
  112. {
  113. size -= next_buf.size();
  114. next_elem_offset_ = 0;
  115. ++next_elem_;
  116. ++next;
  117. }
  118. }
  119. }
  120. // Get the total number of bytes consumed from the buffers.
  121. std::size_t total_consumed() const
  122. {
  123. return total_consumed_;
  124. }
  125. private:
  126. Buffers buffers_;
  127. std::size_t total_size_;
  128. std::size_t total_consumed_;
  129. std::size_t next_elem_;
  130. std::size_t next_elem_offset_;
  131. };
  132. // Base class of all consuming_buffers specialisations for single buffers.
  133. template <typename Buffer>
  134. class consuming_single_buffer
  135. {
  136. public:
  137. // Construct to represent the entire list of buffers.
  138. template <typename Buffer1>
  139. explicit consuming_single_buffer(const Buffer1& buffer)
  140. : buffer_(buffer),
  141. total_consumed_(0)
  142. {
  143. }
  144. // Determine if we are at the end of the buffers.
  145. bool empty() const
  146. {
  147. return total_consumed_ >= buffer_.size();
  148. }
  149. // Get the buffer for a single transfer, with a size.
  150. Buffer prepare(std::size_t max_size)
  151. {
  152. return asio::buffer(buffer_ + total_consumed_, max_size);
  153. }
  154. // Consume the specified number of bytes from the buffers.
  155. void consume(std::size_t size)
  156. {
  157. total_consumed_ += size;
  158. }
  159. // Get the total number of bytes consumed from the buffers.
  160. std::size_t total_consumed() const
  161. {
  162. return total_consumed_;
  163. }
  164. private:
  165. Buffer buffer_;
  166. std::size_t total_consumed_;
  167. };
  168. template <>
  169. class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>
  170. : public consuming_single_buffer<ASIO_MUTABLE_BUFFER>
  171. {
  172. public:
  173. explicit consuming_buffers(const mutable_buffer& buffer)
  174. : consuming_single_buffer<ASIO_MUTABLE_BUFFER>(buffer)
  175. {
  176. }
  177. };
  178. template <>
  179. class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>
  180. : public consuming_single_buffer<ASIO_CONST_BUFFER>
  181. {
  182. public:
  183. explicit consuming_buffers(const mutable_buffer& buffer)
  184. : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)
  185. {
  186. }
  187. };
  188. template <>
  189. class consuming_buffers<const_buffer, const_buffer, const const_buffer*>
  190. : public consuming_single_buffer<ASIO_CONST_BUFFER>
  191. {
  192. public:
  193. explicit consuming_buffers(const const_buffer& buffer)
  194. : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)
  195. {
  196. }
  197. };
  198. #if !defined(ASIO_NO_DEPRECATED)
  199. template <>
  200. class consuming_buffers<mutable_buffer,
  201. mutable_buffers_1, const mutable_buffer*>
  202. : public consuming_single_buffer<ASIO_MUTABLE_BUFFER>
  203. {
  204. public:
  205. explicit consuming_buffers(const mutable_buffers_1& buffer)
  206. : consuming_single_buffer<ASIO_MUTABLE_BUFFER>(buffer)
  207. {
  208. }
  209. };
  210. template <>
  211. class consuming_buffers<const_buffer, mutable_buffers_1, const mutable_buffer*>
  212. : public consuming_single_buffer<ASIO_CONST_BUFFER>
  213. {
  214. public:
  215. explicit consuming_buffers(const mutable_buffers_1& buffer)
  216. : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)
  217. {
  218. }
  219. };
  220. template <>
  221. class consuming_buffers<const_buffer, const_buffers_1, const const_buffer*>
  222. : public consuming_single_buffer<ASIO_CONST_BUFFER>
  223. {
  224. public:
  225. explicit consuming_buffers(const const_buffers_1& buffer)
  226. : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)
  227. {
  228. }
  229. };
  230. #endif // !defined(ASIO_NO_DEPRECATED)
  231. template <typename Buffer, typename Elem>
  232. class consuming_buffers<Buffer, boost::array<Elem, 2>,
  233. typename boost::array<Elem, 2>::const_iterator>
  234. {
  235. public:
  236. // Construct to represent the entire list of buffers.
  237. explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
  238. : buffers_(buffers),
  239. total_consumed_(0)
  240. {
  241. }
  242. // Determine if we are at the end of the buffers.
  243. bool empty() const
  244. {
  245. return total_consumed_ >=
  246. Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
  247. }
  248. // Get the buffer for a single transfer, with a size.
  249. boost::array<Buffer, 2> prepare(std::size_t max_size)
  250. {
  251. boost::array<Buffer, 2> result = {{
  252. Buffer(buffers_[0]), Buffer(buffers_[1]) }};
  253. std::size_t buffer0_size = result[0].size();
  254. result[0] = asio::buffer(result[0] + total_consumed_, max_size);
  255. result[1] = asio::buffer(
  256. result[1] + (total_consumed_ < buffer0_size
  257. ? 0 : total_consumed_ - buffer0_size),
  258. max_size - result[0].size());
  259. return result;
  260. }
  261. // Consume the specified number of bytes from the buffers.
  262. void consume(std::size_t size)
  263. {
  264. total_consumed_ += size;
  265. }
  266. // Get the total number of bytes consumed from the buffers.
  267. std::size_t total_consumed() const
  268. {
  269. return total_consumed_;
  270. }
  271. private:
  272. boost::array<Elem, 2> buffers_;
  273. std::size_t total_consumed_;
  274. };
  275. #if defined(ASIO_HAS_STD_ARRAY)
  276. template <typename Buffer, typename Elem>
  277. class consuming_buffers<Buffer, std::array<Elem, 2>,
  278. typename std::array<Elem, 2>::const_iterator>
  279. {
  280. public:
  281. // Construct to represent the entire list of buffers.
  282. explicit consuming_buffers(const std::array<Elem, 2>& buffers)
  283. : buffers_(buffers),
  284. total_consumed_(0)
  285. {
  286. }
  287. // Determine if we are at the end of the buffers.
  288. bool empty() const
  289. {
  290. return total_consumed_ >=
  291. Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
  292. }
  293. // Get the buffer for a single transfer, with a size.
  294. std::array<Buffer, 2> prepare(std::size_t max_size)
  295. {
  296. std::array<Buffer, 2> result = {{
  297. Buffer(buffers_[0]), Buffer(buffers_[1]) }};
  298. std::size_t buffer0_size = result[0].size();
  299. result[0] = asio::buffer(result[0] + total_consumed_, max_size);
  300. result[1] = asio::buffer(
  301. result[1] + (total_consumed_ < buffer0_size
  302. ? 0 : total_consumed_ - buffer0_size),
  303. max_size - result[0].size());
  304. return result;
  305. }
  306. // Consume the specified number of bytes from the buffers.
  307. void consume(std::size_t size)
  308. {
  309. total_consumed_ += size;
  310. }
  311. // Get the total number of bytes consumed from the buffers.
  312. std::size_t total_consumed() const
  313. {
  314. return total_consumed_;
  315. }
  316. private:
  317. std::array<Elem, 2> buffers_;
  318. std::size_t total_consumed_;
  319. };
  320. #endif // defined(ASIO_HAS_STD_ARRAY)
  321. // Specialisation for null_buffers to ensure that the null_buffers type is
  322. // always passed through to the underlying read or write operation.
  323. template <typename Buffer>
  324. class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
  325. : public asio::null_buffers
  326. {
  327. public:
  328. consuming_buffers(const null_buffers&)
  329. {
  330. // No-op.
  331. }
  332. bool empty()
  333. {
  334. return false;
  335. }
  336. null_buffers prepare(std::size_t)
  337. {
  338. return null_buffers();
  339. }
  340. void consume(std::size_t)
  341. {
  342. // No-op.
  343. }
  344. std::size_t total_consumed() const
  345. {
  346. return 0;
  347. }
  348. };
  349. } // namespace detail
  350. } // namespace asio
  351. #include "asio/detail/pop_options.hpp"
  352. #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP