blob: 72b18f43cb8ef7ba0082d29b1f249d01a7370b63 [file] [log] [blame]
//
// const_buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#define BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/push_options.hpp>
#include <boost/asio/detail/push_options.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/asio/detail/pop_options.hpp>
#include <boost/asio/buffer.hpp>
namespace boost {
namespace asio {
namespace detail {
// A proxy iterator for a sub-range in a list of buffers.
template <typename ConstBufferSequence>
class const_buffers_iterator
: public boost::iterator_facade<const_buffers_iterator<ConstBufferSequence>,
const char, boost::bidirectional_traversal_tag>
{
public:
// Default constructor creates an iterator in an undefined state.
const_buffers_iterator()
{
}
// Create an iterator for the specified position.
const_buffers_iterator(const ConstBufferSequence& buffers,
std::size_t position)
: begin_(buffers.begin()),
current_(buffers.begin()),
end_(buffers.end()),
position_(0)
{
while (current_ != end_)
{
current_buffer_ = *current_;
std::size_t buffer_size = boost::asio::buffer_size(current_buffer_);
if (position - position_ < buffer_size)
{
current_buffer_position_ = position - position_;
position_ = position;
return;
}
position_ += buffer_size;
++current_;
}
current_buffer_ = boost::asio::const_buffer();
current_buffer_position_ = 0;
}
std::size_t position() const
{
return position_;
}
private:
friend class boost::iterator_core_access;
void increment()
{
if (current_ == end_)
return;
++position_;
++current_buffer_position_;
if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
return;
++current_;
current_buffer_position_ = 0;
while (current_ != end_)
{
current_buffer_ = *current_;
if (boost::asio::buffer_size(current_buffer_) > 0)
return;
++current_;
}
}
void decrement()
{
if (position_ == 0)
return;
--position_;
if (current_buffer_position_ != 0)
{
--current_buffer_position_;
return;
}
typename ConstBufferSequence::const_iterator iter = current_;
while (iter != begin_)
{
--iter;
boost::asio::const_buffer buffer = *iter;
std::size_t buffer_size = boost::asio::buffer_size(buffer);
if (buffer_size > 0)
{
current_ = iter;
current_buffer_ = buffer;
current_buffer_position_ = buffer_size - 1;
return;
}
}
}
bool equal(const const_buffers_iterator& other) const
{
return position_ == other.position_;
}
const char& dereference() const
{
return boost::asio::buffer_cast<const char*>(
current_buffer_)[current_buffer_position_];
}
boost::asio::const_buffer current_buffer_;
std::size_t current_buffer_position_;
typename ConstBufferSequence::const_iterator begin_;
typename ConstBufferSequence::const_iterator current_;
typename ConstBufferSequence::const_iterator end_;
std::size_t position_;
};
} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP