00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP
00012 #define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <algorithm>
00022 #include <cstddef>
00023 #include <boost/config.hpp>
00024 #include <boost/iterator/iterator_facade.hpp>
00025 #include "asio/detail/pop_options.hpp"
00026
00027 namespace asio {
00028 namespace detail {
00029
00030
00031 template <typename Buffer, typename Buffer_Iterator>
00032 class consuming_buffers_iterator
00033 : public boost::iterator_facade<
00034 consuming_buffers_iterator<Buffer, Buffer_Iterator>,
00035 const Buffer, boost::forward_traversal_tag>
00036 {
00037 public:
00038
00039 consuming_buffers_iterator()
00040 : at_end_(true)
00041 {
00042 }
00043
00044
00045
00046 consuming_buffers_iterator(bool at_end, const Buffer& first,
00047 Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder)
00048 : at_end_(at_end),
00049 first_(buffer(first, max_size)),
00050 begin_remainder_(begin_remainder),
00051 end_remainder_(end_remainder),
00052 offset_(0)
00053 {
00054 }
00055
00056 private:
00057 friend class boost::iterator_core_access;
00058
00059 enum { max_size = 65536 };
00060
00061 void increment()
00062 {
00063 if (!at_end_)
00064 {
00065 if (begin_remainder_ == end_remainder_
00066 || offset_ + buffer_size(first_) >= max_size)
00067 {
00068 at_end_ = true;
00069 }
00070 else
00071 {
00072 offset_ += buffer_size(first_);
00073 first_ = buffer(*begin_remainder_++, max_size - offset_);
00074 }
00075 }
00076 }
00077
00078 bool equal(const consuming_buffers_iterator& other) const
00079 {
00080 if (at_end_ && other.at_end_)
00081 return true;
00082 return !at_end_ && !other.at_end_
00083 && buffer_cast<const void*>(first_)
00084 == buffer_cast<const void*>(other.first_)
00085 && buffer_size(first_) == buffer_size(other.first_)
00086 && begin_remainder_ == other.begin_remainder_
00087 && end_remainder_ == other.end_remainder_;
00088 }
00089
00090 const Buffer& dereference() const
00091 {
00092 return first_;
00093 }
00094
00095 bool at_end_;
00096 Buffer first_;
00097 Buffer_Iterator begin_remainder_;
00098 Buffer_Iterator end_remainder_;
00099 std::size_t offset_;
00100 };
00101
00102
00103 template <typename Buffer, typename Buffers>
00104 class consuming_buffers
00105 {
00106 public:
00107
00108 typedef Buffer value_type;
00109
00110
00111 typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
00112 const_iterator;
00113
00114
00115 consuming_buffers(const Buffers& buffers)
00116 : buffers_(buffers),
00117 at_end_(buffers_.begin() == buffers_.end()),
00118 first_(*buffers_.begin()),
00119 begin_remainder_(buffers_.begin())
00120 {
00121 if (!at_end_)
00122 ++begin_remainder_;
00123 }
00124
00125
00126 consuming_buffers(const consuming_buffers& other)
00127 : buffers_(other.buffers_),
00128 at_end_(other.at_end_),
00129 first_(other.first_),
00130 begin_remainder_(buffers_.begin())
00131 {
00132 typename Buffers::const_iterator first = other.buffers_.begin();
00133 typename Buffers::const_iterator second = other.begin_remainder_;
00134 std::advance(begin_remainder_, std::distance(first, second));
00135 }
00136
00137
00138 consuming_buffers& operator=(const consuming_buffers& other)
00139 {
00140 buffers_ = other.buffers_;
00141 at_end_ = other.at_end_;
00142 first_ = other.first_;
00143 begin_remainder_ = buffers_.begin();
00144 typename Buffers::const_iterator first = other.buffers_.begin();
00145 typename Buffers::const_iterator second = other.begin_remainder_;
00146 std::advance(begin_remainder_, std::distance(first, second));
00147 return *this;
00148 }
00149
00150
00151 const_iterator begin() const
00152 {
00153 return const_iterator(at_end_, first_, begin_remainder_, buffers_.end());
00154 }
00155
00156
00157 const_iterator end() const
00158 {
00159 return const_iterator();
00160 }
00161
00162
00163 void consume(std::size_t size)
00164 {
00165
00166 while (size > 0 && !at_end_)
00167 {
00168 if (buffer_size(first_) <= size)
00169 {
00170 size -= buffer_size(first_);
00171 if (begin_remainder_ == buffers_.end())
00172 at_end_ = true;
00173 else
00174 first_ = *begin_remainder_++;
00175 }
00176 else
00177 {
00178 first_ = first_ + size;
00179 size = 0;
00180 }
00181 }
00182
00183
00184 while (!at_end_ && buffer_size(first_) == 0)
00185 {
00186 if (begin_remainder_ == buffers_.end())
00187 at_end_ = true;
00188 else
00189 first_ = *begin_remainder_++;
00190 }
00191 }
00192
00193 private:
00194 Buffers buffers_;
00195 bool at_end_;
00196 Buffer first_;
00197 typename Buffers::const_iterator begin_remainder_;
00198 };
00199
00200 }
00201 }
00202
00203 #include "asio/detail/pop_options.hpp"
00204
00205 #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP