Shrink buffer_prefix_view

This commit is contained in:
Vinnie Falco
2017-07-12 09:02:55 -07:00
parent 9ffb8e0f0f
commit 9bfb5374f1
4 changed files with 87 additions and 130 deletions

View File

@ -2,6 +2,7 @@ Version 80:
* Javadoc tidying * Javadoc tidying
* Add basic_dynamic_body.hpp * Add basic_dynamic_body.hpp
* Shrink buffer_prefix_view
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -31,25 +31,24 @@ class buffer_prefix_view
using buffers_type = typename using buffers_type = typename
std::decay<BufferSequence>::type; std::decay<BufferSequence>::type;
using iter_type = typename buffers_type::const_iterator; using iter_type =
typename buffers_type::const_iterator;
BufferSequence bs_; BufferSequence bs_;
iter_type back_;
iter_type end_;
std::size_t size_; std::size_t size_;
iter_type end_;
template<class Deduced> template<class Deduced>
buffer_prefix_view(Deduced&& other, buffer_prefix_view(
std::size_t nback, std::size_t nend) Deduced&& other, std::size_t dist)
: bs_(std::forward<Deduced>(other).bs_) : bs_(std::forward<Deduced>(other).bs_)
, back_(std::next(bs_.begin(), nback))
, end_(std::next(bs_.begin(), nend))
, size_(other.size_) , size_(other.size_)
, end_(std::next(bs_.begin(), dist))
{ {
} }
void void
setup(std::size_t n); setup(std::size_t size);
public: public:
/// The type for each element in the list of buffers. /// The type for each element in the list of buffers.
@ -92,11 +91,13 @@ public:
the sequence will be made, but ownership of the underlying the sequence will be made, but ownership of the underlying
memory is not transferred. memory is not transferred.
*/ */
buffer_prefix_view(std::size_t n, BufferSequence const& buffers); buffer_prefix_view(
std::size_t size,
BufferSequence const& buffers);
/** Construct a buffer sequence prefix in-place. /** Construct a buffer sequence prefix in-place.
@param n The maximum number of bytes in the prefix. @param size The maximum number of bytes in the prefix.
If this is larger than the size of passed, buffers, If this is larger than the size of passed, buffers,
the resulting sequence will represent the entire the resulting sequence will represent the entire
input sequence. input sequence.
@ -104,8 +105,10 @@ public:
@param args Arguments forwarded to the contained buffers constructor. @param args Arguments forwarded to the contained buffers constructor.
*/ */
template<class... Args> template<class... Args>
buffer_prefix_view(std::size_t n, buffer_prefix_view(
boost::in_place_init_t, Args&&... args); std::size_t size,
boost::in_place_init_t,
Args&&... args);
/// Get a bidirectional iterator to the first element. /// Get a bidirectional iterator to the first element.
const_iterator const_iterator
@ -122,23 +125,23 @@ public:
passed buffer, but with a size that is equal to or less passed buffer, but with a size that is equal to or less
than the size of the original buffer. than the size of the original buffer.
@param n The size of the returned buffer. @param size The size of the returned buffer.
@param buffer The buffer to shorten. The underlying @param buffer The buffer to shorten. The underlying
memory is not modified. memory is not modified.
@return A new buffer that points to the first `n` bytes @return A new buffer that points to the first `size`
of the original buffer. bytes of the original buffer.
*/ */
inline inline
boost::asio::const_buffer boost::asio::const_buffer
buffer_prefix(std::size_t n, buffer_prefix(std::size_t size,
boost::asio::const_buffer buffer) boost::asio::const_buffer buffer)
{ {
using boost::asio::buffer_cast; using boost::asio::buffer_cast;
using boost::asio::buffer_size; using boost::asio::buffer_size;
return { buffer_cast<void const*>(buffer), return { buffer_cast<void const*>(buffer),
(std::min)(n, buffer_size(buffer)) }; (std::min)(size, buffer_size(buffer)) };
} }
/** Returns a prefix of a mutable buffer. /** Returns a prefix of a mutable buffer.
@ -147,23 +150,23 @@ buffer_prefix(std::size_t n,
passed buffer, but with a size that is equal to or less passed buffer, but with a size that is equal to or less
than the size of the original buffer. than the size of the original buffer.
@param n The size of the returned buffer. @param size The size of the returned buffer.
@param buffer The buffer to shorten. The underlying @param buffer The buffer to shorten. The underlying
memory is not modified. memory is not modified.
@return A new buffer that points to the first `n` bytes @return A new buffer that points to the first `size` bytes
of the original buffer. of the original buffer.
*/ */
inline inline
boost::asio::mutable_buffer boost::asio::mutable_buffer
buffer_prefix(std::size_t n, buffer_prefix(std::size_t size,
boost::asio::mutable_buffer buffer) boost::asio::mutable_buffer buffer)
{ {
using boost::asio::buffer_cast; using boost::asio::buffer_cast;
using boost::asio::buffer_size; using boost::asio::buffer_size;
return { buffer_cast<void*>(buffer), return {buffer_cast<void*>(buffer),
(std::min)(n, buffer_size(buffer)) }; (std::min)(size, buffer_size(buffer))};
} }
/** Returns a prefix of a buffer sequence. /** Returns a prefix of a buffer sequence.
@ -172,7 +175,7 @@ buffer_prefix(std::size_t n,
presents a shorter subset of the original list of buffers starting presents a shorter subset of the original list of buffers starting
with the first byte of the original sequence. with the first byte of the original sequence.
@param n The maximum number of bytes in the wrapped @param size The maximum number of bytes in the wrapped
sequence. If this is larger than the size of passed, sequence. If this is larger than the size of passed,
buffers, the resulting sequence will represent the buffers, the resulting sequence will represent the
entire input sequence. entire input sequence.
@ -188,17 +191,19 @@ buffer_prefix_view<BufferSequence>
#else #else
inline inline
typename std::enable_if< typename std::enable_if<
! std::is_same<BufferSequence, boost::asio::const_buffer>::value && ! std::is_same<BufferSequence,
! std::is_same<BufferSequence, boost::asio::mutable_buffer>::value, boost::asio::const_buffer>::value &&
buffer_prefix_view<BufferSequence>>::type ! std::is_same<BufferSequence,
boost::asio::mutable_buffer>::value,
buffer_prefix_view<BufferSequence>>::type
#endif #endif
buffer_prefix(std::size_t n, BufferSequence const& buffers) buffer_prefix(std::size_t size, BufferSequence const& buffers)
{ {
static_assert( static_assert(
is_const_buffer_sequence<BufferSequence>::value || is_const_buffer_sequence<BufferSequence>::value ||
is_mutable_buffer_sequence<BufferSequence>::value, is_mutable_buffer_sequence<BufferSequence>::value,
"BufferSequence requirements not met"); "BufferSequence requirements not met");
return buffer_prefix_view<BufferSequence>(n, buffers); return buffer_prefix_view<BufferSequence>(size, buffers);
} }
} // beast } // beast

View File

@ -21,24 +21,24 @@ namespace detail {
inline inline
boost::asio::const_buffer boost::asio::const_buffer
buffer_prefix(std::size_t n, buffer_prefix(std::size_t size,
boost::asio::const_buffer buffer) boost::asio::const_buffer buffer)
{ {
using boost::asio::buffer_cast; using boost::asio::buffer_cast;
using boost::asio::buffer_size; using boost::asio::buffer_size;
return { buffer_cast<void const*>(buffer), return {buffer_cast<void const*>(buffer),
(std::min)(n, buffer_size(buffer)) }; (std::min)(size, buffer_size(buffer))};
} }
inline inline
boost::asio::mutable_buffer boost::asio::mutable_buffer
buffer_prefix(std::size_t n, buffer_prefix(std::size_t size,
boost::asio::mutable_buffer buffer) boost::asio::mutable_buffer buffer)
{ {
using boost::asio::buffer_cast; using boost::asio::buffer_cast;
using boost::asio::buffer_size; using boost::asio::buffer_size;
return { buffer_cast<void*>(buffer), return {buffer_cast<void*>(buffer),
(std::min)(n, buffer_size(buffer)) }; (std::min)(size, buffer_size(buffer))};
} }
} // detail } // detail
@ -49,6 +49,7 @@ class buffer_prefix_view<BufferSequence>::const_iterator
friend class buffer_prefix_view<BufferSequence>; friend class buffer_prefix_view<BufferSequence>;
buffer_prefix_view const* b_ = nullptr; buffer_prefix_view const* b_ = nullptr;
std::size_t remain_;
iter_type it_; iter_type it_;
public: public:
@ -65,10 +66,10 @@ public:
std::bidirectional_iterator_tag; std::bidirectional_iterator_tag;
const_iterator() = default; const_iterator() = default;
const_iterator(const_iterator&& other); const_iterator(const_iterator&& other) = default;
const_iterator(const_iterator const& other); const_iterator(const_iterator const& other) = default;
const_iterator& operator=(const_iterator&& other); const_iterator& operator=(const_iterator&& other) = default;
const_iterator& operator=(const_iterator const& other); const_iterator& operator=(const_iterator const& other) = default;
bool bool
operator==(const_iterator const& other) const operator==(const_iterator const& other) const
@ -85,9 +86,7 @@ public:
reference reference
operator*() const operator*() const
{ {
if(it_ == b_->back_) return detail::buffer_prefix(remain_, *it_);
return detail::buffer_prefix(b_->size_, *it_);
return *it_;
} }
pointer pointer
@ -96,7 +95,7 @@ public:
const_iterator& const_iterator&
operator++() operator++()
{ {
++it_; remain_ -= boost::asio::buffer_size(*it_++);
return *this; return *this;
} }
@ -104,14 +103,14 @@ public:
operator++(int) operator++(int)
{ {
auto temp = *this; auto temp = *this;
++(*this); remain_ -= boost::asio::buffer_size(*it_++);
return temp; return temp;
} }
const_iterator& const_iterator&
operator--() operator--()
{ {
--it_; remain_ += boost::asio::buffer_size(*--it_);
return *this; return *this;
} }
@ -119,15 +118,24 @@ public:
operator--(int) operator--(int)
{ {
auto temp = *this; auto temp = *this;
--(*this); remain_ += boost::asio::buffer_size(*--it_);
return temp; return temp;
} }
private: private:
const_iterator(buffer_prefix_view const& b, const_iterator(buffer_prefix_view const& b,
bool at_end) std::true_type)
: b_(&b) : b_(&b)
, it_(at_end ? b.end_ : b.bs_.begin()) , remain_(0)
, it_(b_->end_)
{
}
const_iterator(buffer_prefix_view const& b,
std::false_type)
: b_(&b)
, remain_(b_->size_)
, it_(b_->bs_.begin())
{ {
} }
}; };
@ -135,74 +143,31 @@ private:
template<class BufferSequence> template<class BufferSequence>
void void
buffer_prefix_view<BufferSequence>:: buffer_prefix_view<BufferSequence>::
setup(std::size_t n) setup(std::size_t size)
{ {
for(end_ = bs_.begin(); end_ != bs_.end(); ++end_) size_ = 0;
end_ = bs_.begin();
auto const last = bs_.end();
while(end_ != last)
{ {
auto const len = auto const len =
boost::asio::buffer_size(*end_); boost::asio::buffer_size(*end_++);
if(n <= len) if(len >= size)
{ {
size_ = n; size_ += size;
back_ = end_++; break;
return;
} }
n -= len; size -= len;
size_ += len;
} }
size_ = 0;
back_ = end_;
}
template<class BufferSequence>
buffer_prefix_view<BufferSequence>::
const_iterator::
const_iterator(const_iterator&& other)
: b_(other.b_)
, it_(std::move(other.it_))
{
}
template<class BufferSequence>
buffer_prefix_view<BufferSequence>::
const_iterator::
const_iterator(const_iterator const& other)
: b_(other.b_)
, it_(other.it_)
{
}
template<class BufferSequence>
auto
buffer_prefix_view<BufferSequence>::
const_iterator::
operator=(const_iterator&& other) ->
const_iterator&
{
b_ = other.b_;
it_ = std::move(other.it_);
return *this;
}
template<class BufferSequence>
auto
buffer_prefix_view<BufferSequence>::
const_iterator::
operator=(const_iterator const& other) ->
const_iterator&
{
if(&other == this)
return *this;
b_ = other.b_;
it_ = other.it_;
return *this;
} }
template<class BufferSequence> template<class BufferSequence>
buffer_prefix_view<BufferSequence>:: buffer_prefix_view<BufferSequence>::
buffer_prefix_view(buffer_prefix_view&& other) buffer_prefix_view(buffer_prefix_view&& other)
: buffer_prefix_view(std::move(other), : buffer_prefix_view(std::move(other),
std::distance<iter_type>(other.bs_.begin(), other.back_), std::distance<iter_type>(
std::distance<iter_type>(other.bs_.begin(), other.end_)) other.bs_.begin(), other.end_))
{ {
} }
@ -210,8 +175,8 @@ template<class BufferSequence>
buffer_prefix_view<BufferSequence>:: buffer_prefix_view<BufferSequence>::
buffer_prefix_view(buffer_prefix_view const& other) buffer_prefix_view(buffer_prefix_view const& other)
: buffer_prefix_view(other, : buffer_prefix_view(other,
std::distance<iter_type>(other.bs_.begin(), other.back_), std::distance<iter_type>(
std::distance<iter_type>(other.bs_.begin(), other.end_)) other.bs_.begin(), other.end_))
{ {
} }
@ -221,14 +186,11 @@ buffer_prefix_view<BufferSequence>::
operator=(buffer_prefix_view&& other) -> operator=(buffer_prefix_view&& other) ->
buffer_prefix_view& buffer_prefix_view&
{ {
auto const nback = std::distance<iter_type>( auto const dist = std::distance<iter_type>(
other.bs_.begin(), other.back_);
auto const nend = std::distance<iter_type>(
other.bs_.begin(), other.end_); other.bs_.begin(), other.end_);
bs_ = std::move(other.bs_); bs_ = std::move(other.bs_);
back_ = std::next(bs_.begin(), nback);
end_ = std::next(bs_.begin(), nend);
size_ = other.size_; size_ = other.size_;
end_ = std::next(bs_.begin(), dist);
return *this; return *this;
} }
@ -238,33 +200,31 @@ buffer_prefix_view<BufferSequence>::
operator=(buffer_prefix_view const& other) -> operator=(buffer_prefix_view const& other) ->
buffer_prefix_view& buffer_prefix_view&
{ {
auto const nback = std::distance<iter_type>( auto const dist = std::distance<iter_type>(
other.bs_.begin(), other.back_);
auto const nend = std::distance<iter_type>(
other.bs_.begin(), other.end_); other.bs_.begin(), other.end_);
bs_ = other.bs_; bs_ = other.bs_;
back_ = std::next(bs_.begin(), nback);
end_ = std::next(bs_.begin(), nend);
size_ = other.size_; size_ = other.size_;
end_ = std::next(bs_.begin(), dist);
return *this; return *this;
} }
template<class BufferSequence> template<class BufferSequence>
buffer_prefix_view<BufferSequence>:: buffer_prefix_view<BufferSequence>::
buffer_prefix_view(std::size_t n, BufferSequence const& bs) buffer_prefix_view(std::size_t size,
BufferSequence const& bs)
: bs_(bs) : bs_(bs)
{ {
setup(n); setup(size);
} }
template<class BufferSequence> template<class BufferSequence>
template<class... Args> template<class... Args>
buffer_prefix_view<BufferSequence>:: buffer_prefix_view<BufferSequence>::
buffer_prefix_view(std::size_t n, buffer_prefix_view(std::size_t size,
boost::in_place_init_t, Args&&... args) boost::in_place_init_t, Args&&... args)
: bs_(std::forward<Args>(args)...) : bs_(std::forward<Args>(args)...)
{ {
setup(n); setup(size);
} }
template<class BufferSequence> template<class BufferSequence>
@ -273,7 +233,7 @@ auto
buffer_prefix_view<BufferSequence>::begin() const -> buffer_prefix_view<BufferSequence>::begin() const ->
const_iterator const_iterator
{ {
return const_iterator{*this, false}; return const_iterator{*this, std::false_type{}};
} }
template<class BufferSequence> template<class BufferSequence>
@ -282,7 +242,7 @@ auto
buffer_prefix_view<BufferSequence>::end() const -> buffer_prefix_view<BufferSequence>::end() const ->
const_iterator const_iterator
{ {
return const_iterator{*this, true}; return const_iterator{*this, std::true_type{}};
} }
} // beast } // beast

View File

@ -172,15 +172,6 @@ public:
BEAST_EXPECT(bsize2(pb) == 2); BEAST_EXPECT(bsize2(pb) == 2);
BEAST_EXPECT(bsize3(pb) == 2); BEAST_EXPECT(bsize3(pb) == 2);
BEAST_EXPECT(bsize4(pb) == 2); BEAST_EXPECT(bsize4(pb) == 2);
std::size_t n = 0;
for(auto it = pb.end(); it != pb.begin(); --it)
{
decltype(pb)::const_iterator it2(std::move(it));
BEAST_EXPECT(buffer_size(*it2) == 1);
it = std::move(it2);
++n;
}
BEAST_EXPECT(n == 2);
} }
void run() override void run() override