|
- //
- // detail/consuming_buffers.hpp
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2015 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 ASIO_DETAIL_CONSUMING_BUFFERS_HPP
- #define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
-
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
- #include "asio/detail/config.hpp"
- #include <cstddef>
- #include <iterator>
- #include "asio/buffer.hpp"
- #include "asio/detail/limits.hpp"
-
- #include "asio/detail/push_options.hpp"
-
- namespace asio {
- namespace detail {
-
- // A proxy iterator for a sub-range in a list of buffers.
- template <typename Buffer, typename Buffer_Iterator>
- class consuming_buffers_iterator
- {
- public:
- /// The type used for the distance between two iterators.
- typedef std::ptrdiff_t difference_type;
-
- /// The type of the value pointed to by the iterator.
- typedef Buffer value_type;
-
- /// The type of the result of applying operator->() to the iterator.
- typedef const Buffer* pointer;
-
- /// The type of the result of applying operator*() to the iterator.
- typedef const Buffer& reference;
-
- /// The iterator category.
- typedef std::forward_iterator_tag iterator_category;
-
- // Default constructor creates an end iterator.
- consuming_buffers_iterator()
- : at_end_(true)
- {
- }
-
- // Construct with a buffer for the first entry and an iterator
- // range for the remaining entries.
- consuming_buffers_iterator(bool at_end, const Buffer& first,
- Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
- std::size_t max_size)
- : at_end_(max_size > 0 ? at_end : true),
- first_(buffer(first, max_size)),
- begin_remainder_(begin_remainder),
- end_remainder_(end_remainder),
- offset_(0),
- max_size_(max_size)
- {
- }
-
- // Dereference an iterator.
- const Buffer& operator*() const
- {
- return dereference();
- }
-
- // Dereference an iterator.
- const Buffer* operator->() const
- {
- return &dereference();
- }
-
- // Increment operator (prefix).
- consuming_buffers_iterator& operator++()
- {
- increment();
- return *this;
- }
-
- // Increment operator (postfix).
- consuming_buffers_iterator operator++(int)
- {
- consuming_buffers_iterator tmp(*this);
- ++*this;
- return tmp;
- }
-
- // Test two iterators for equality.
- friend bool operator==(const consuming_buffers_iterator& a,
- const consuming_buffers_iterator& b)
- {
- return a.equal(b);
- }
-
- // Test two iterators for inequality.
- friend bool operator!=(const consuming_buffers_iterator& a,
- const consuming_buffers_iterator& b)
- {
- return !a.equal(b);
- }
-
- private:
- void increment()
- {
- if (!at_end_)
- {
- if (begin_remainder_ == end_remainder_
- || offset_ + first_.size() >= max_size_)
- {
- at_end_ = true;
- }
- else
- {
- offset_ += first_.size();
- first_ = buffer(*begin_remainder_++, max_size_ - offset_);
- }
- }
- }
-
- bool equal(const consuming_buffers_iterator& other) const
- {
- if (at_end_ && other.at_end_)
- return true;
- return !at_end_ && !other.at_end_
- && first_.data() == other.first_.data()
- && first_.size() == other.first_.size()
- && begin_remainder_ == other.begin_remainder_
- && end_remainder_ == other.end_remainder_;
- }
-
- const Buffer& dereference() const
- {
- return first_;
- }
-
- bool at_end_;
- Buffer first_;
- Buffer_Iterator begin_remainder_;
- Buffer_Iterator end_remainder_;
- std::size_t offset_;
- std::size_t max_size_;
- };
-
- // A proxy for a sub-range in a list of buffers.
- template <typename Buffer, typename Buffers>
- class consuming_buffers
- {
- public:
- // The type for each element in the list of buffers.
- typedef Buffer value_type;
-
- // A forward-only iterator type that may be used to read elements.
- typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
- const_iterator;
-
- // Construct to represent the entire list of buffers.
- consuming_buffers(const Buffers& buffers)
- : buffers_(buffers),
- at_end_(buffers_.begin() == buffers_.end()),
- begin_remainder_(buffers_.begin()),
- max_size_((std::numeric_limits<std::size_t>::max)())
- {
- if (!at_end_)
- {
- first_ = *buffers_.begin();
- ++begin_remainder_;
- }
- }
-
- // Copy constructor.
- consuming_buffers(const consuming_buffers& other)
- : buffers_(other.buffers_),
- at_end_(other.at_end_),
- first_(other.first_),
- begin_remainder_(buffers_.begin()),
- max_size_(other.max_size_)
- {
- typename Buffers::const_iterator first = other.buffers_.begin();
- typename Buffers::const_iterator second = other.begin_remainder_;
- std::advance(begin_remainder_, std::distance(first, second));
- }
-
- // Assignment operator.
- consuming_buffers& operator=(const consuming_buffers& other)
- {
- buffers_ = other.buffers_;
- at_end_ = other.at_end_;
- first_ = other.first_;
- begin_remainder_ = buffers_.begin();
- typename Buffers::const_iterator first = other.buffers_.begin();
- typename Buffers::const_iterator second = other.begin_remainder_;
- std::advance(begin_remainder_, std::distance(first, second));
- max_size_ = other.max_size_;
- return *this;
- }
-
- // Get a forward-only iterator to the first element.
- const_iterator begin() const
- {
- return const_iterator(at_end_, first_,
- begin_remainder_, buffers_.end(), max_size_);
- }
-
- // Get a forward-only iterator for one past the last element.
- const_iterator end() const
- {
- return const_iterator();
- }
-
- // Set the maximum size for a single transfer.
- void prepare(std::size_t max_size)
- {
- max_size_ = max_size;
- }
-
- // Consume the specified number of bytes from the buffers.
- void consume(std::size_t size)
- {
- // Remove buffers from the start until the specified size is reached.
- while (size > 0 && !at_end_)
- {
- if (first_.size() <= size)
- {
- size -= first_.size();
- if (begin_remainder_ == buffers_.end())
- at_end_ = true;
- else
- first_ = *begin_remainder_++;
- }
- else
- {
- first_ = first_ + size;
- size = 0;
- }
- }
-
- // Remove any more empty buffers at the start.
- while (!at_end_ && first_.size() == 0)
- {
- if (begin_remainder_ == buffers_.end())
- at_end_ = true;
- else
- first_ = *begin_remainder_++;
- }
- }
-
- private:
- Buffers buffers_;
- bool at_end_;
- Buffer first_;
- typename Buffers::const_iterator begin_remainder_;
- std::size_t max_size_;
- };
-
- // Specialisation for null_buffers to ensure that the null_buffers type is
- // always passed through to the underlying read or write operation.
- template <typename Buffer>
- class consuming_buffers<Buffer, asio::null_buffers>
- : public asio::null_buffers
- {
- public:
- consuming_buffers(const asio::null_buffers&)
- {
- // No-op.
- }
-
- void prepare(std::size_t)
- {
- // No-op.
- }
-
- void consume(std::size_t)
- {
- // No-op.
- }
- };
-
- } // namespace detail
- } // namespace asio
-
- #include "asio/detail/pop_options.hpp"
-
- #endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP
|