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.

292 lines
7.1KB

  1. //
  2. // detail/consuming_buffers.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_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 <iterator>
  18. #include "asio/buffer.hpp"
  19. #include "asio/detail/limits.hpp"
  20. #include "asio/detail/push_options.hpp"
  21. namespace asio {
  22. namespace detail {
  23. // A proxy iterator for a sub-range in a list of buffers.
  24. template <typename Buffer, typename Buffer_Iterator>
  25. class consuming_buffers_iterator
  26. {
  27. public:
  28. /// The type used for the distance between two iterators.
  29. typedef std::ptrdiff_t difference_type;
  30. /// The type of the value pointed to by the iterator.
  31. typedef Buffer value_type;
  32. /// The type of the result of applying operator->() to the iterator.
  33. typedef const Buffer* pointer;
  34. /// The type of the result of applying operator*() to the iterator.
  35. typedef const Buffer& reference;
  36. /// The iterator category.
  37. typedef std::forward_iterator_tag iterator_category;
  38. // Default constructor creates an end iterator.
  39. consuming_buffers_iterator()
  40. : at_end_(true)
  41. {
  42. }
  43. // Construct with a buffer for the first entry and an iterator
  44. // range for the remaining entries.
  45. consuming_buffers_iterator(bool at_end, const Buffer& first,
  46. Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
  47. std::size_t max_size)
  48. : at_end_(max_size > 0 ? at_end : true),
  49. first_(buffer(first, max_size)),
  50. begin_remainder_(begin_remainder),
  51. end_remainder_(end_remainder),
  52. offset_(0),
  53. max_size_(max_size)
  54. {
  55. }
  56. // Dereference an iterator.
  57. const Buffer& operator*() const
  58. {
  59. return dereference();
  60. }
  61. // Dereference an iterator.
  62. const Buffer* operator->() const
  63. {
  64. return &dereference();
  65. }
  66. // Increment operator (prefix).
  67. consuming_buffers_iterator& operator++()
  68. {
  69. increment();
  70. return *this;
  71. }
  72. // Increment operator (postfix).
  73. consuming_buffers_iterator operator++(int)
  74. {
  75. consuming_buffers_iterator tmp(*this);
  76. ++*this;
  77. return tmp;
  78. }
  79. // Test two iterators for equality.
  80. friend bool operator==(const consuming_buffers_iterator& a,
  81. const consuming_buffers_iterator& b)
  82. {
  83. return a.equal(b);
  84. }
  85. // Test two iterators for inequality.
  86. friend bool operator!=(const consuming_buffers_iterator& a,
  87. const consuming_buffers_iterator& b)
  88. {
  89. return !a.equal(b);
  90. }
  91. private:
  92. void increment()
  93. {
  94. if (!at_end_)
  95. {
  96. if (begin_remainder_ == end_remainder_
  97. || offset_ + first_.size() >= max_size_)
  98. {
  99. at_end_ = true;
  100. }
  101. else
  102. {
  103. offset_ += first_.size();
  104. first_ = buffer(*begin_remainder_++, max_size_ - offset_);
  105. }
  106. }
  107. }
  108. bool equal(const consuming_buffers_iterator& other) const
  109. {
  110. if (at_end_ && other.at_end_)
  111. return true;
  112. return !at_end_ && !other.at_end_
  113. && first_.data() == other.first_.data()
  114. && first_.size() == other.first_.size()
  115. && begin_remainder_ == other.begin_remainder_
  116. && end_remainder_ == other.end_remainder_;
  117. }
  118. const Buffer& dereference() const
  119. {
  120. return first_;
  121. }
  122. bool at_end_;
  123. Buffer first_;
  124. Buffer_Iterator begin_remainder_;
  125. Buffer_Iterator end_remainder_;
  126. std::size_t offset_;
  127. std::size_t max_size_;
  128. };
  129. // A proxy for a sub-range in a list of buffers.
  130. template <typename Buffer, typename Buffers>
  131. class consuming_buffers
  132. {
  133. public:
  134. // The type for each element in the list of buffers.
  135. typedef Buffer value_type;
  136. // A forward-only iterator type that may be used to read elements.
  137. typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
  138. const_iterator;
  139. // Construct to represent the entire list of buffers.
  140. consuming_buffers(const Buffers& buffers)
  141. : buffers_(buffers),
  142. at_end_(buffers_.begin() == buffers_.end()),
  143. begin_remainder_(buffers_.begin()),
  144. max_size_((std::numeric_limits<std::size_t>::max)())
  145. {
  146. if (!at_end_)
  147. {
  148. first_ = *buffers_.begin();
  149. ++begin_remainder_;
  150. }
  151. }
  152. // Copy constructor.
  153. consuming_buffers(const consuming_buffers& other)
  154. : buffers_(other.buffers_),
  155. at_end_(other.at_end_),
  156. first_(other.first_),
  157. begin_remainder_(buffers_.begin()),
  158. max_size_(other.max_size_)
  159. {
  160. typename Buffers::const_iterator first = other.buffers_.begin();
  161. typename Buffers::const_iterator second = other.begin_remainder_;
  162. std::advance(begin_remainder_, std::distance(first, second));
  163. }
  164. // Assignment operator.
  165. consuming_buffers& operator=(const consuming_buffers& other)
  166. {
  167. buffers_ = other.buffers_;
  168. at_end_ = other.at_end_;
  169. first_ = other.first_;
  170. begin_remainder_ = buffers_.begin();
  171. typename Buffers::const_iterator first = other.buffers_.begin();
  172. typename Buffers::const_iterator second = other.begin_remainder_;
  173. std::advance(begin_remainder_, std::distance(first, second));
  174. max_size_ = other.max_size_;
  175. return *this;
  176. }
  177. // Get a forward-only iterator to the first element.
  178. const_iterator begin() const
  179. {
  180. return const_iterator(at_end_, first_,
  181. begin_remainder_, buffers_.end(), max_size_);
  182. }
  183. // Get a forward-only iterator for one past the last element.
  184. const_iterator end() const
  185. {
  186. return const_iterator();
  187. }
  188. // Set the maximum size for a single transfer.
  189. void prepare(std::size_t max_size)
  190. {
  191. max_size_ = max_size;
  192. }
  193. // Consume the specified number of bytes from the buffers.
  194. void consume(std::size_t size)
  195. {
  196. // Remove buffers from the start until the specified size is reached.
  197. while (size > 0 && !at_end_)
  198. {
  199. if (first_.size() <= size)
  200. {
  201. size -= first_.size();
  202. if (begin_remainder_ == buffers_.end())
  203. at_end_ = true;
  204. else
  205. first_ = *begin_remainder_++;
  206. }
  207. else
  208. {
  209. first_ = first_ + size;
  210. size = 0;
  211. }
  212. }
  213. // Remove any more empty buffers at the start.
  214. while (!at_end_ && first_.size() == 0)
  215. {
  216. if (begin_remainder_ == buffers_.end())
  217. at_end_ = true;
  218. else
  219. first_ = *begin_remainder_++;
  220. }
  221. }
  222. private:
  223. Buffers buffers_;
  224. bool at_end_;
  225. Buffer first_;
  226. typename Buffers::const_iterator begin_remainder_;
  227. std::size_t max_size_;
  228. };
  229. // Specialisation for null_buffers to ensure that the null_buffers type is
  230. // always passed through to the underlying read or write operation.
  231. template <typename Buffer>
  232. class consuming_buffers<Buffer, asio::null_buffers>
  233. : public asio::null_buffers
  234. {
  235. public:
  236. consuming_buffers(const asio::null_buffers&)
  237. {
  238. // No-op.
  239. }
  240. void prepare(std::size_t)
  241. {
  242. // No-op.
  243. }
  244. void consume(std::size_t)
  245. {
  246. // No-op.
  247. }
  248. };
  249. } // namespace detail
  250. } // namespace asio
  251. #include "asio/detail/pop_options.hpp"
  252. #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP