Go to the documentation of this file.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 #include "asio/buffer.hpp"
00028
00029 namespace asio {
00030 namespace detail {
00031
00032
00033 template <typename Buffer, typename Buffer_Iterator>
00034 class consuming_buffers_iterator
00035 : public boost::iterator_facade<
00036 consuming_buffers_iterator<Buffer, Buffer_Iterator>,
00037 const Buffer, boost::forward_traversal_tag>
00038 {
00039 public:
00040
00041 consuming_buffers_iterator()
00042 : at_end_(true)
00043 {
00044 }
00045
00046
00047
00048 consuming_buffers_iterator(bool at_end, const Buffer& first,
00049 Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder)
00050 : at_end_(at_end),
00051 first_(buffer(first, max_size)),
00052 begin_remainder_(begin_remainder),
00053 end_remainder_(end_remainder),
00054 offset_(0)
00055 {
00056 }
00057
00058 private:
00059 friend class boost::iterator_core_access;
00060
00061 enum { max_size = 65536 };
00062
00063 void increment()
00064 {
00065 if (!at_end_)
00066 {
00067 if (begin_remainder_ == end_remainder_
00068 || offset_ + buffer_size(first_) >= max_size)
00069 {
00070 at_end_ = true;
00071 }
00072 else
00073 {
00074 offset_ += buffer_size(first_);
00075 first_ = buffer(*begin_remainder_++, max_size - offset_);
00076 }
00077 }
00078 }
00079
00080 bool equal(const consuming_buffers_iterator& other) const
00081 {
00082 if (at_end_ && other.at_end_)
00083 return true;
00084 return !at_end_ && !other.at_end_
00085 && buffer_cast<const void*>(first_)
00086 == buffer_cast<const void*>(other.first_)
00087 && buffer_size(first_) == buffer_size(other.first_)
00088 && begin_remainder_ == other.begin_remainder_
00089 && end_remainder_ == other.end_remainder_;
00090 }
00091
00092 const Buffer& dereference() const
00093 {
00094 return first_;
00095 }
00096
00097 bool at_end_;
00098 Buffer first_;
00099 Buffer_Iterator begin_remainder_;
00100 Buffer_Iterator end_remainder_;
00101 std::size_t offset_;
00102 };
00103
00104
00105 template <typename Buffer, typename Buffers>
00106 class consuming_buffers
00107 {
00108 public:
00109
00110 typedef Buffer value_type;
00111
00112
00113 typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
00114 const_iterator;
00115
00116
00117 consuming_buffers(const Buffers& buffers)
00118 : buffers_(buffers),
00119 at_end_(buffers_.begin() == buffers_.end()),
00120 first_(*buffers_.begin()),
00121 begin_remainder_(buffers_.begin())
00122 {
00123 if (!at_end_)
00124 ++begin_remainder_;
00125 }
00126
00127
00128 consuming_buffers(const consuming_buffers& other)
00129 : buffers_(other.buffers_),
00130 at_end_(other.at_end_),
00131 first_(other.first_),
00132 begin_remainder_(buffers_.begin())
00133 {
00134 typename Buffers::const_iterator first = other.buffers_.begin();
00135 typename Buffers::const_iterator second = other.begin_remainder_;
00136 std::advance(begin_remainder_, std::distance(first, second));
00137 }
00138
00139
00140 consuming_buffers& operator=(const consuming_buffers& other)
00141 {
00142 buffers_ = other.buffers_;
00143 at_end_ = other.at_end_;
00144 first_ = other.first_;
00145 begin_remainder_ = buffers_.begin();
00146 typename Buffers::const_iterator first = other.buffers_.begin();
00147 typename Buffers::const_iterator second = other.begin_remainder_;
00148 std::advance(begin_remainder_, std::distance(first, second));
00149 return *this;
00150 }
00151
00152
00153 const_iterator begin() const
00154 {
00155 return const_iterator(at_end_, first_, begin_remainder_, buffers_.end());
00156 }
00157
00158
00159 const_iterator end() const
00160 {
00161 return const_iterator();
00162 }
00163
00164
00165 void consume(std::size_t size)
00166 {
00167
00168 while (size > 0 && !at_end_)
00169 {
00170 if (buffer_size(first_) <= size)
00171 {
00172 size -= buffer_size(first_);
00173 if (begin_remainder_ == buffers_.end())
00174 at_end_ = true;
00175 else
00176 first_ = *begin_remainder_++;
00177 }
00178 else
00179 {
00180 first_ = first_ + size;
00181 size = 0;
00182 }
00183 }
00184
00185
00186 while (!at_end_ && buffer_size(first_) == 0)
00187 {
00188 if (begin_remainder_ == buffers_.end())
00189 at_end_ = true;
00190 else
00191 first_ = *begin_remainder_++;
00192 }
00193 }
00194
00195 private:
00196 Buffers buffers_;
00197 bool at_end_;
00198 Buffer first_;
00199 typename Buffers::const_iterator begin_remainder_;
00200 };
00201
00202
00203
00204 template <typename Buffer>
00205 class consuming_buffers<Buffer, asio::null_buffers>
00206 : public asio::null_buffers
00207 {
00208 public:
00209 consuming_buffers(const asio::null_buffers&)
00210 {
00211
00212 }
00213
00214 void consume(std::size_t)
00215 {
00216
00217 }
00218 };
00219
00220 }
00221 }
00222
00223 #include "asio/detail/pop_options.hpp"
00224
00225 #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP