/src/contrib/boost/asio/detail/consuming_buffers.hpp

http://pythonocc.googlecode.com/ · C++ Header · 282 lines · 211 code · 35 blank · 36 comment · 28 complexity · 4b3b741a1577975919347779842f6df0 MD5 · raw file

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