00001 // 00002 // const_buffers_iterator.hpp 00003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 00011 #ifndef ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP 00012 #define ASIO_DETAIL_CONST_BUFFERS_ITERATOR_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 <cstddef> 00022 #include <boost/config.hpp> 00023 #include <boost/iterator/iterator_facade.hpp> 00024 #include "asio/detail/pop_options.hpp" 00025 00026 #include "asio/buffer.hpp" 00027 00028 namespace asio { 00029 namespace detail { 00030 00031 // A proxy iterator for a sub-range in a list of buffers. 00032 template <typename ConstBufferSequence> 00033 class const_buffers_iterator 00034 : public boost::iterator_facade<const_buffers_iterator<ConstBufferSequence>, 00035 const char, boost::bidirectional_traversal_tag> 00036 { 00037 public: 00038 // Default constructor creates an iterator in an undefined state. 00039 const_buffers_iterator() 00040 { 00041 } 00042 00043 // Create an iterator for the specified position. 00044 const_buffers_iterator(const ConstBufferSequence& buffers, 00045 std::size_t position) 00046 : begin_(buffers.begin()), 00047 current_(buffers.begin()), 00048 end_(buffers.end()), 00049 position_(0) 00050 { 00051 while (current_ != end_) 00052 { 00053 current_buffer_ = *current_; 00054 std::size_t buffer_size = asio::buffer_size(current_buffer_); 00055 if (position - position_ < buffer_size) 00056 { 00057 current_buffer_position_ = position - position_; 00058 position_ = position; 00059 return; 00060 } 00061 position_ += buffer_size; 00062 ++current_; 00063 } 00064 current_buffer_ = asio::const_buffer(); 00065 current_buffer_position_ = 0; 00066 } 00067 00068 std::size_t position() const 00069 { 00070 return position_; 00071 } 00072 00073 private: 00074 friend class boost::iterator_core_access; 00075 00076 void increment() 00077 { 00078 if (current_ == end_) 00079 return; 00080 00081 ++position_; 00082 00083 ++current_buffer_position_; 00084 if (current_buffer_position_ != asio::buffer_size(current_buffer_)) 00085 return; 00086 00087 ++current_; 00088 current_buffer_position_ = 0; 00089 while (current_ != end_) 00090 { 00091 current_buffer_ = *current_; 00092 if (asio::buffer_size(current_buffer_) > 0) 00093 return; 00094 ++current_; 00095 } 00096 } 00097 00098 void decrement() 00099 { 00100 if (position_ == 0) 00101 return; 00102 00103 --position_; 00104 00105 if (current_buffer_position_ != 0) 00106 { 00107 --current_buffer_position_; 00108 return; 00109 } 00110 00111 typename ConstBufferSequence::const_iterator iter = current_; 00112 while (iter != begin_) 00113 { 00114 --iter; 00115 asio::const_buffer buffer = *iter; 00116 std::size_t buffer_size = asio::buffer_size(buffer); 00117 if (buffer_size > 0) 00118 { 00119 current_ = iter; 00120 current_buffer_ = buffer; 00121 current_buffer_position_ = buffer_size - 1; 00122 return; 00123 } 00124 } 00125 } 00126 00127 bool equal(const const_buffers_iterator& other) const 00128 { 00129 return position_ == other.position_; 00130 } 00131 00132 const char& dereference() const 00133 { 00134 return asio::buffer_cast<const char*>( 00135 current_buffer_)[current_buffer_position_]; 00136 } 00137 00138 asio::const_buffer current_buffer_; 00139 std::size_t current_buffer_position_; 00140 typename ConstBufferSequence::const_iterator begin_; 00141 typename ConstBufferSequence::const_iterator current_; 00142 typename ConstBufferSequence::const_iterator end_; 00143 std::size_t position_; 00144 }; 00145 00146 } // namespace detail 00147 } // namespace asio 00148 00149 #include "asio/detail/pop_options.hpp" 00150 00151 #endif // ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP