/Src/Dependencies/Boost/boost/asio/detail/consuming_buffers.hpp

http://hadesmem.googlecode.com/ · C++ Header · 280 lines · 210 code · 34 blank · 36 comment · 28 complexity · af101938fd4512500041e4b315fdcbbb MD5 · raw file

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