From b59d0a5cd5219375cf77850a449639f5a3e35a9f Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sun, 26 Nov 2017 09:55:31 -0800 Subject: [PATCH] Use variant in buffers_cat_view --- CHANGELOG.md | 1 + include/boost/beast/core/detail/variant.hpp | 141 +++++-- include/boost/beast/core/impl/buffers_cat.ipp | 383 ++++++------------ 3 files changed, 237 insertions(+), 288 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a12b0719..c59fd08a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Version 146: * Documentation tidying * Fix typo in examples documentation * Add detail::aligned_union and tidy up +* Use variant in buffers_cat_view API Changes: diff --git a/include/boost/beast/core/detail/variant.hpp b/include/boost/beast/core/detail/variant.hpp index 064ebf1c..536cb759 100644 --- a/include/boost/beast/core/detail/variant.hpp +++ b/include/boost/beast/core/detail/variant.hpp @@ -36,7 +36,7 @@ class variant template using type = typename std::tuple_element< - I , std::tuple>::type; + I, std::tuple>::type; template using C = std::integral_constant; @@ -46,8 +46,15 @@ public: ~variant() { - if(i_) - destroy(C<0>{}); + destroy(C<0>{}); + } + + bool + operator==(variant const& other) const + { + if(i_ != other.i_) + return false; + return equal(other, C<0>{}); } // 0 = empty @@ -61,6 +68,7 @@ public: variant(variant&& other) { i_ = other.move(&buf_, C<0>{}); + other.i_ = 0; } variant(variant const& other) @@ -71,17 +79,22 @@ public: // moved-from object becomes empty variant& operator=(variant&& other) { - if(i_ != 0) + if(this != &other) + { destroy(C<0>{}); - i_ = other.move(&buf_, C<0>{}); + i_ = other.move(&buf_, C<0>{}); + other.i_ = 0; + } return *this; } variant& operator=(variant const& other) { - if(i_ != 0) + if(this != &other) + { destroy(C<0>{}); - i_ = other.copy(&buf_, C<0>{}); + i_ = other.copy(&buf_, C<0>{}); + } return *this; } @@ -89,8 +102,7 @@ public: void emplace(Args&&... args) { - if(i_ != 0) - destroy(C<0>{}); + destroy(C<0>{}); new(&buf_) type( std::forward(args)...); i_ = I; @@ -117,72 +129,135 @@ public: void reset() { - if(i_ == 0) - return; destroy(C<0>{}); } private: void - destroy(C) + destroy(C<0>) { - return; + auto const I = 0; + if(i_ == I) + return; + destroy(C{}); + i_ = 0; } template void destroy(C) { - if(i_ == I+1) + if(i_ == I) { - using T = type; - get().~T(); - i_ = 0; + using T = type; + get().~T(); return; } destroy(C{}); } - unsigned char - move(void*, C) + void + destroy(C) { - return 0; + auto const I = sizeof...(TN); + BOOST_ASSERT(i_ == I); + using T = type; + get().~T(); + } + + unsigned char + move(void* dest, C<0>) + { + auto const I = 0; + if(i_ == I) + return I; + return move(dest, C{}); } template unsigned char move(void* dest, C) { - if(i_ == I+1) + if(i_ == I) { - using T = type; - new(dest) T{std::move(get())}; - get().~T(); - i_ = 0; - return I+1; + using T = type; + new(dest) T(std::move(get())); + get().~T(); + return I; } return move(dest, C{}); } unsigned char - copy(void*, C) const + move(void* dest, C) { - return 0; + auto const I = sizeof...(TN); + BOOST_ASSERT(i_ == I); + using T = type; + new(dest) T(std::move(get())); + get().~T(); + return I; + } + + unsigned char + copy(void* dest, C<0>) const + { + auto const I = 0; + if(i_ == I) + return I; + return copy(dest, C{}); } template unsigned char copy(void* dest, C) const { - if(i_ == I+1) + if(i_ == I) { - using T = type; - auto const& t = get(); - new(dest) T{t}; - return I+1; + using T = type; + auto const& t = get(); + new(dest) T(t); + return I; } return copy(dest, C{}); } + + unsigned char + copy(void* dest, C) const + { + auto const I = sizeof...(TN); + BOOST_ASSERT(i_ == I); + using T = type; + auto const& t = get(); + new(dest) T(t); + return I; + } + + bool + equal(variant const& other, C<0>) const + { + auto constexpr I = 0; + if(i_ == I) + return true; + return equal(other, C{}); + } + + template + bool + equal(variant const& other, C) const + { + if(i_ == I) + return get() == other.get(); + return equal(other, C{}); + } + + bool + equal(variant const& other, C) const + { + auto constexpr I = sizeof...(TN); + BOOST_ASSERT(i_ == I); + return get() == other.get(); + } }; } // detail diff --git a/include/boost/beast/core/impl/buffers_cat.ipp b/include/boost/beast/core/impl/buffers_cat.ipp index d92d5523..2e82e887 100644 --- a/include/boost/beast/core/impl/buffers_cat.ipp +++ b/include/boost/beast/core/impl/buffers_cat.ipp @@ -11,9 +11,9 @@ #define BOOST_BEAST_IMPL_BUFFERS_CAT_IPP #include +#include #include #include -#include #include #include #include @@ -27,39 +27,29 @@ namespace beast { template class buffers_cat_view::const_iterator { - std::size_t n_; - std::tuple const* bn_; - std::array::type...>()> buf_; + // VFALCO The logic to skip empty sequences fails + // if there is just one buffer in the list. + static_assert(sizeof...(Bn) >= 2, + "A minimum of two sequences are required"); + + struct past_end + { + operator bool() const noexcept + { + return true; + } + }; + + std::tuple const* bn_ = nullptr; + detail::variant::type..., + past_end> it_; friend class buffers_cat_view; template using C = std::integral_constant; - template - using iter_t = typename detail::buffer_sequence_iterator< - typename std::tuple_element>::type>::type; - - template - iter_t& - iter() - { - // type-pun - return *reinterpret_cast< - iter_t*>(static_cast(buf_.data())); - } - - template - iter_t const& - iter() const - { - // type-pun - return *reinterpret_cast< - iter_t const*>(static_cast< - void const*>(buf_.data())); - } - public: using value_type = typename detail::common_buffers_type::type; @@ -69,12 +59,11 @@ public: using iterator_category = std::bidirectional_iterator_tag; - ~const_iterator(); - const_iterator(); - const_iterator(const_iterator&& other); - const_iterator(const_iterator const& other); - const_iterator& operator=(const_iterator&& other); - const_iterator& operator=(const_iterator const& other); + const_iterator() = default; + const_iterator(const_iterator&& other) = default; + const_iterator(const_iterator const& other) = default; + const_iterator& operator=(const_iterator&& other) = default; + const_iterator& operator=(const_iterator const& other) = default; bool operator==(const_iterator const& other) const; @@ -97,9 +86,11 @@ public: const_iterator operator++(int); + // deprecated const_iterator& operator--(); + // deprecated const_iterator operator--(int); @@ -107,13 +98,6 @@ private: const_iterator( std::tuple const& bn, bool at_end); - void - construct(C const&) - { - auto constexpr I = sizeof...(Bn); - n_ = I; - } - template void construct(C const&) @@ -121,122 +105,85 @@ private: if(boost::asio::buffer_size( std::get(*bn_)) != 0) { - n_ = I; - new(&buf_[0]) iter_t{ + it_.template emplace( boost::asio::buffer_sequence_begin( - std::get(*bn_))}; + std::get(*bn_))); return; } construct(C{}); } void - rconstruct(C<0> const&) + construct(C const&) + { + auto constexpr I = sizeof...(Bn)-1; + it_.template emplace( + boost::asio::buffer_sequence_begin( + std::get(*bn_))); + } + + void + construct(C const&) + { + // end + auto constexpr I = sizeof...(Bn); + it_.template emplace(); + } + + template + void + next(C const&) + { + if(boost::asio::buffer_size( + std::get(*bn_)) != 0) + { + it_.template emplace( + boost::asio::buffer_sequence_begin( + std::get(*bn_))); + return; + } + next(C{}); + } + + void + next(C const&) + { + // end + auto constexpr I = sizeof...(Bn); + it_.template emplace(); + } + + template + void + prev(C const&) + { + if(boost::asio::buffer_size( + std::get(*bn_)) != 0) + { + it_.template emplace( + boost::asio::buffer_sequence_end( + std::get(*bn_))); + return; + } + prev(C{}); + } + + void + prev(C<0> const&) { auto constexpr I = 0; - if(boost::asio::buffer_size( - std::get(*bn_)) != 0) - { - n_ = I; - new(&buf_[0]) iter_t{ - boost::asio::buffer_sequence_end( - std::get(*bn_))}; - return; - } - BOOST_THROW_EXCEPTION(std::logic_error{ - "invalid iterator"}); + it_.template emplace( + boost::asio::buffer_sequence_end( + std::get(*bn_))); } template - void - rconstruct(C const&) + reference + dereference(C const&) const { - if(boost::asio::buffer_size( - std::get(*bn_)) != 0) - { - n_ = I; - new(&buf_[0]) iter_t{ - boost::asio::buffer_sequence_end( - std::get(*bn_))}; - return; - } - rconstruct(C{}); - } - - void - destroy(C const&) - { - return; - } - - template - void - destroy(C const&) - { - if(n_ == I) - { - using Iter = iter_t; - iter().~Iter(); - return; - } - destroy(C{}); - } - - void - move(const_iterator&&, - C const&) - { - } - - template - void - move(const_iterator&& other, - C const&) - { - if(n_ == I) - { - new(&buf_[0]) iter_t{ - std::move(other.iter())}; - return; - } - move(std::move(other), C{}); - } - - void - copy(const_iterator const&, - C const&) - { - } - - template - void - copy(const_iterator const& other, - C const&) - { - if(n_ == I) - { - new(&buf_[0]) iter_t{ - other.iter()}; - return; - } - copy(other, C{}); - } - - bool - equal(const_iterator const&, - C const&) const - { - return true; - } - - template - bool - equal(const_iterator const& other, - C const&) const - { - if(n_ == I) - return iter() == other.iter(); - return equal(other, C{}); + if(it_.index() == I+1) + return *it_.template get(); + return dereference(C{}); } [[noreturn]] @@ -248,12 +195,18 @@ private: } template - reference - dereference(C const&) const + void + increment(C const&) { - if(n_ == I) - return *iter(); - return dereference(C{}); + if(it_.index() == I+1) + { + if(++it_.template get() != + boost::asio::buffer_sequence_end( + std::get(*bn_))) + return; + return next(C{}); + } + increment(C{}); } [[noreturn]] @@ -264,29 +217,12 @@ private: "invalid iterator"}); } - template - void - increment(C const&) - { - if(n_ == I) - { - if(++iter() != - boost::asio::buffer_sequence_end( - std::get(*bn_))) - return; - using Iter = iter_t; - iter().~Iter(); - return construct(C{}); - } - increment(C{}); - } - void decrement(C const&) { auto constexpr I = sizeof...(Bn); - if(n_ == I) - rconstruct(C{}); + if(it_.index() == I+1) + prev(C{}); decrement(C{}); } @@ -294,19 +230,16 @@ private: void decrement(C const&) { - if(n_ == I) + if(it_.index() == I+1) { - if(iter() != + if(it_.template get() != boost::asio::buffer_sequence_begin( std::get(*bn_))) { - --iter(); + --it_.template get(); return; } - --n_; - using Iter = iter_t; - iter().~Iter(); - rconstruct(C{}); + prev(C{}); } decrement(C{}); } @@ -315,11 +248,11 @@ private: decrement(C<0> const&) { auto constexpr I = 0; - if(iter() != + if(it_.template get() != boost::asio::buffer_sequence_begin( std::get(*bn_))) { - --iter(); + --it_.template get(); return; } BOOST_THROW_EXCEPTION(std::logic_error{ @@ -331,97 +264,33 @@ private: template buffers_cat_view:: -const_iterator::~const_iterator() -{ - destroy(C<0>{}); -} - -template -buffers_cat_view:: -const_iterator::const_iterator() - : n_(sizeof...(Bn)) - , bn_(nullptr) -{ -} - -template -buffers_cat_view:: -const_iterator::const_iterator( +const_iterator:: +const_iterator( std::tuple const& bn, bool at_end) : bn_(&bn) { - if(at_end) - n_ = sizeof...(Bn); - else + if(! at_end) construct(C<0>{}); -} - -template -buffers_cat_view:: -const_iterator::const_iterator(const_iterator&& other) - : n_(other.n_) - , bn_(other.bn_) -{ - move(std::move(other), C<0>{}); -} - -template -buffers_cat_view:: -const_iterator::const_iterator(const_iterator const& other) - : n_(other.n_) - , bn_(other.bn_) -{ - copy(other, C<0>{}); -} - -template -auto -buffers_cat_view:: -const_iterator::operator=(const_iterator&& other) -> - const_iterator& -{ - if(&other == this) - return *this; - destroy(C<0>{}); - n_ = other.n_; - bn_ = other.bn_; - // VFALCO What about exceptions? - move(std::move(other), C<0>{}); - return *this; -} - -template -auto -buffers_cat_view:: -const_iterator::operator=(const_iterator const& other) -> -const_iterator& -{ - if(&other == this) - return *this; - destroy(C<0>{}); - n_ = other.n_; - bn_ = other.bn_; - // VFALCO What about exceptions? - copy(other, C<0>{}); - return *this; + else + construct(C{}); } template bool buffers_cat_view:: -const_iterator::operator==(const_iterator const& other) const +const_iterator:: +operator==(const_iterator const& other) const { if(bn_ != other.bn_) return false; - if(n_ != other.n_) - return false; - return equal(other, C<0>{}); + return it_ == other.it_; } template auto buffers_cat_view:: -const_iterator::operator*() const -> +const_iterator:: +operator*() const -> reference { return dereference(C<0>{}); @@ -430,7 +299,8 @@ const_iterator::operator*() const -> template auto buffers_cat_view:: -const_iterator::operator++() -> +const_iterator:: +operator++() -> const_iterator& { increment(C<0>{}); @@ -440,7 +310,8 @@ const_iterator::operator++() -> template auto buffers_cat_view:: -const_iterator::operator++(int) -> +const_iterator:: +operator++(int) -> const_iterator { auto temp = *this; @@ -451,7 +322,8 @@ const_iterator::operator++(int) -> template auto buffers_cat_view:: -const_iterator::operator--() -> +const_iterator:: +operator--() -> const_iterator& { decrement(C{}); @@ -461,7 +333,8 @@ const_iterator::operator--() -> template auto buffers_cat_view:: -const_iterator::operator--(int) -> +const_iterator:: +operator--(int) -> const_iterator { auto temp = *this;