From d0183da6d0c6b09a053ce7f7d3fd15793bf597cc Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Wed, 12 Dec 2018 06:37:40 -0800 Subject: [PATCH] Tidy up buffers_prefix and tests --- include/boost/beast/core/buffers_prefix.hpp | 141 ++++-------- .../boost/beast/core/impl/buffers_prefix.hpp | 211 +++++++++++------- test/beast/core/buffers_prefix.cpp | 116 +++++++--- 3 files changed, 257 insertions(+), 211 deletions(-) diff --git a/include/boost/beast/core/buffers_prefix.hpp b/include/boost/beast/core/buffers_prefix.hpp index 003c0e79..0548005a 100644 --- a/include/boost/beast/core/buffers_prefix.hpp +++ b/include/boost/beast/core/buffers_prefix.hpp @@ -27,35 +27,27 @@ namespace beast { a shorter subset of the original list of buffers starting with the first byte of the original sequence. - @tparam BufferSequence The buffer sequence to adapt. + @tparam ConstBufferSequence The buffer sequence to adapt. */ -template +template class buffers_prefix_view { - using buffers_type = typename - std::decay::type; - using iter_type = typename - detail::buffer_sequence_iterator::type; + detail::buffer_sequence_iterator< + ConstBufferSequence>::type; - BufferSequence bs_; + ConstBufferSequence bs_; std::size_t size_; std::size_t remain_; iter_type end_; - template - buffers_prefix_view( - Deduced&& other, std::size_t dist) - : bs_(std::forward(other).bs_) - , size_(other.size_) - , remain_(other.remain_) - , end_(std::next(bs_.begin(), dist)) - { - } - void setup(std::size_t size); + buffers_prefix_view( + buffers_prefix_view const& other, + std::size_t dist); + public: /// The type for each element in the list of buffers. using value_type = typename std::conditional< @@ -74,22 +66,16 @@ public: #endif - /// Move Constructor - buffers_prefix_view(buffers_prefix_view&&); - /// Copy Constructor buffers_prefix_view(buffers_prefix_view const&); - /// Move Assignment - buffers_prefix_view& operator=(buffers_prefix_view&&); - /// Copy Assignment buffers_prefix_view& operator=(buffers_prefix_view const&); /** Construct a buffer sequence 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 input sequence. @@ -100,16 +86,16 @@ public: */ buffers_prefix_view( std::size_t size, - BufferSequence const& buffers); + ConstBufferSequence const& buffers); /** Construct a buffer sequence prefix in-place. @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 input sequence. - @param args Arguments forwarded to the contained buffers constructor. + @param args Arguments forwarded to the contained buffer's constructor. */ template buffers_prefix_view( @@ -124,64 +110,29 @@ public: /// Returns an iterator to one past the last buffer in the sequence const_iterator end() const; + +#if ! BOOST_BEAST_DOXYGEN + template + friend + std::size_t + buffer_size(buffers_prefix_view const& buffers); +#endif }; +#ifndef BOOST_BEAST_DOXYGEN +BOOST_BEAST_DECL +std::size_t +buffer_size(buffers_prefix_view< + net::const_buffer> const& buffers); + +BOOST_BEAST_DECL +std::size_t +buffer_size(buffers_prefix_view< + net::mutable_buffer> const& buffers); +#endif + //------------------------------------------------------------------------------ -/** Returns a prefix of a constant buffer. - - The returned buffer points to the same memory as the passed - buffer, but with a size that is equal to or smaller. - - @param size The maximum size of the returned buffer in bytes. If - this is greater than or equal to the size of the passed buffer, - the result will have the same size as the original buffer. - - @param buffer The buffer to return a prefix for. The - underlying memory is not modified, and ownership of the - memory is not transferred. - - @return A constant buffer that represents the prefix of - the original buffer. - - @par Exception Safety - - No-throw guarantee. -*/ -inline -net::const_buffer -buffers_prefix(std::size_t size, - net::const_buffer buffer) noexcept -{ - return {buffer.data(), std::min< - std::size_t>(size, buffer.size())}; -} - -/** Returns a prefix of a mutable buffer. - - The returned buffer points to the same memory as the passed - buffer, but with a size that is equal to or smaller. - - @param size The maximum size of the returned buffer in bytes. If - this is greater than or equal to the size of the passed buffer, - the result will have the same size as the original buffer. - - @param buffer The buffer to return a prefix for. The - underlying memory is not modified, and ownership of the - memory is not transferred. - - @return A mutable buffer that represents the prefix of - the original buffer. -*/ -inline -net::mutable_buffer -buffers_prefix(std::size_t size, - net::mutable_buffer buffer) noexcept -{ - return {buffer.data(), std::min< - std::size_t>(size, buffer.size())}; -} - /** Returns a prefix of a constant or mutable buffer sequence. The returned buffer sequence points to the same memory as the @@ -202,30 +153,16 @@ buffers_prefix(std::size_t size, @return A constant buffer sequence that represents the prefix of the original buffer sequence. If the original buffer sequence - also meets the requirements of MutableBufferSequence, + also meets the requirements of MutableConstBufferSequence, then the returned value will also be a mutable buffer sequence. - - @note This function does not participate in overload resolution - if `buffers` is convertible to either `net::const_buffer` or - `net::mutable_buffer`. */ template -#if BOOST_BEAST_DOXYGEN buffers_prefix_view -#else -inline -typename std::enable_if< - ! std::is_convertible::value && - ! std::is_convertible::value, - buffers_prefix_view>::type -#endif -buffers_prefix(std::size_t size, ConstBufferSequence const& buffers) +buffers_prefix( + std::size_t size, ConstBufferSequence const& buffers) { static_assert( - net::is_const_buffer_sequence::value || - net::is_mutable_buffer_sequence::value, + net::is_const_buffer_sequence::value, "ConstBufferSequence requirements not met"); return buffers_prefix_view(size, buffers); } @@ -240,12 +177,12 @@ buffers_prefix(std::size_t size, ConstBufferSequence const& buffers) mutable, the returned buffer sequence will also be mutable. Otherwise, the returned buffer sequence will be constant. */ -template +template typename std::conditional< - net::is_mutable_buffer_sequence::value, + net::is_mutable_buffer_sequence::value, net::mutable_buffer, net::const_buffer>::type -buffers_front(BufferSequence const& buffers) +buffers_front(ConstBufferSequence const& buffers) { auto const first = net::buffer_sequence_begin(buffers); diff --git a/include/boost/beast/core/impl/buffers_prefix.hpp b/include/boost/beast/core/impl/buffers_prefix.hpp index 051547a4..7db402dc 100644 --- a/include/boost/beast/core/impl/buffers_prefix.hpp +++ b/include/boost/beast/core/impl/buffers_prefix.hpp @@ -7,8 +7,8 @@ // Official repository: https://github.com/boostorg/beast // -#ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_IPP -#define BOOST_BEAST_IMPL_BUFFERS_PREFIX_IPP +#ifndef BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP +#define BOOST_BEAST_IMPL_BUFFERS_PREFIX_HPP #include #include @@ -20,32 +20,10 @@ namespace boost { namespace beast { -namespace detail { - -inline -net::const_buffer -buffers_prefix(std::size_t size, - net::const_buffer buffer) +template +class buffers_prefix_view::const_iterator { - return {buffer.data(), - (std::min)(size, buffer.size())}; -} - -inline -net::mutable_buffer -buffers_prefix(std::size_t size, - net::mutable_buffer buffer) -{ - return {buffer.data(), - (std::min)(size, buffer.size())}; -} - -} // detail - -template -class buffers_prefix_view::const_iterator -{ - friend class buffers_prefix_view; + friend class buffers_prefix_view; buffers_prefix_view const* b_ = nullptr; std::size_t remain_; @@ -65,9 +43,7 @@ public: std::bidirectional_iterator_tag; 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 @@ -98,7 +74,7 @@ public: reference operator*() const { - return detail::buffers_prefix(remain_, *it_); + return beast::buffers_prefix(remain_, *it_); } pointer @@ -154,9 +130,9 @@ private: //------------------------------------------------------------------------------ -template +template void -buffers_prefix_view:: +buffers_prefix_view:: setup(std::size_t size) { size_ = 0; @@ -166,10 +142,14 @@ setup(std::size_t size) while(end_ != last) { auto const len = - net::buffer_size(*end_++); + net::const_buffer(*end_++).size(); if(len >= size) { size_ += size; + + // by design, this subtraction can wrap + BOOST_STATIC_ASSERT(std::is_unsigned< + decltype(remain_)>::value); remain_ = size - len; break; } @@ -178,18 +158,20 @@ setup(std::size_t size) } } -template -buffers_prefix_view:: -buffers_prefix_view(buffers_prefix_view&& other) - : buffers_prefix_view(std::move(other), - std::distance( - net::buffer_sequence_begin(other.bs_), - other.end_)) +template +buffers_prefix_view:: +buffers_prefix_view( + buffers_prefix_view const& other, + std::size_t dist) + : bs_(other.bs_) + , size_(other.size_) + , remain_(other.remain_) + , end_(std::next(bs_.begin(), dist)) { } -template -buffers_prefix_view:: +template +buffers_prefix_view:: buffers_prefix_view(buffers_prefix_view const& other) : buffers_prefix_view(other, std::distance( @@ -198,27 +180,9 @@ buffers_prefix_view(buffers_prefix_view const& other) { } -template +template auto -buffers_prefix_view:: -operator=(buffers_prefix_view&& other) -> - buffers_prefix_view& -{ - auto const dist = std::distance( - net::buffer_sequence_begin(other.bs_), - other.end_); - bs_ = std::move(other.bs_); - size_ = other.size_; - remain_ = other.remain_; - end_ = std::next( - net::buffer_sequence_begin(bs_), - dist); - return *this; -} - -template -auto -buffers_prefix_view:: +buffers_prefix_view:: operator=(buffers_prefix_view const& other) -> buffers_prefix_view& { @@ -234,43 +198,138 @@ operator=(buffers_prefix_view const& other) -> return *this; } -template -buffers_prefix_view:: -buffers_prefix_view(std::size_t size, - BufferSequence const& bs) +template +buffers_prefix_view:: +buffers_prefix_view( + std::size_t size, + Buffers const& bs) : bs_(bs) { setup(size); } -template +template template -buffers_prefix_view:: -buffers_prefix_view(std::size_t size, - boost::in_place_init_t, Args&&... args) +buffers_prefix_view:: +buffers_prefix_view( + std::size_t size, + boost::in_place_init_t, + Args&&... args) : bs_(std::forward(args)...) { setup(size); } -template -inline +template auto -buffers_prefix_view::begin() const -> +buffers_prefix_view::begin() const -> const_iterator { return const_iterator{*this, std::false_type{}}; } -template -inline +template auto -buffers_prefix_view::end() const -> +buffers_prefix_view::end() const -> const_iterator { return const_iterator{*this, std::true_type{}}; } +template +std::size_t +buffer_size(buffers_prefix_view< + Buffers> const& buffers) +{ + return buffers.size_; +} + +//------------------------------------------------------------------------------ + +template<> +class buffers_prefix_view + : public net::const_buffer +{ +public: + using net::const_buffer::const_buffer; + buffers_prefix_view(buffers_prefix_view const&) = default; + buffers_prefix_view& operator=(buffers_prefix_view const&) = default; + + buffers_prefix_view( + std::size_t size, + net::const_buffer buffer) + : net::const_buffer( + buffer.data(), + std::min(size, buffer.size()) + #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , buffer.get_debug_check() + #endif + ) + { + } + + template + buffers_prefix_view( + std::size_t size, + boost::in_place_init_t, + Args&&... args) + : buffers_prefix_view(size, + net::const_buffer( + std::forward(args)...)) + { + } +}; + +std::size_t +buffer_size(buffers_prefix_view< + net::const_buffer> const& buffers) +{ + return buffers.size(); +} + +//------------------------------------------------------------------------------ + +template<> +class buffers_prefix_view + : public net::mutable_buffer +{ +public: + using net::mutable_buffer::mutable_buffer; + buffers_prefix_view(buffers_prefix_view const&) = default; + buffers_prefix_view& operator=(buffers_prefix_view const&) = default; + + buffers_prefix_view( + std::size_t size, + net::mutable_buffer buffer) + : net::mutable_buffer( + buffer.data(), + std::min(size, buffer.size()) + #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , buffer.get_debug_check() + #endif + ) + { + } + + template + buffers_prefix_view( + std::size_t size, + boost::in_place_init_t, + Args&&... args) + : buffers_prefix_view(size, + net::mutable_buffer( + std::forward(args)...)) + { + } +}; + +std::size_t +buffer_size(buffers_prefix_view< + net::mutable_buffer> const& buffers) +{ + return buffers.size(); +} + } // beast } // boost diff --git a/test/beast/core/buffers_prefix.cpp b/test/beast/core/buffers_prefix.cpp index 4614eb6d..9da26c04 100644 --- a/test/beast/core/buffers_prefix.cpp +++ b/test/beast/core/buffers_prefix.cpp @@ -20,21 +20,6 @@ namespace boost { namespace beast { -BOOST_STATIC_ASSERT( - std::is_same()))>::value); - -BOOST_STATIC_ASSERT( - net::is_const_buffer_sequence()))>::value); - -BOOST_STATIC_ASSERT( - std::is_same()))>::value); - class buffers_prefix_test : public beast::unit_test::suite { public: @@ -43,10 +28,9 @@ public: std::size_t bsize1(ConstBufferSequence const& bs) { - using net::buffer_size; std::size_t n = 0; for(auto it = bs.begin(); it != bs.end(); ++it) - n += buffer_size(*it); + n += net::buffer_size(*it); return n; } @@ -55,10 +39,9 @@ public: std::size_t bsize2(ConstBufferSequence const& bs) { - using net::buffer_size; std::size_t n = 0; for(auto it = bs.begin(); it != bs.end(); it++) - n += buffer_size(*it); + n += net::buffer_size(*it); return n; } @@ -67,10 +50,9 @@ public: std::size_t bsize3(ConstBufferSequence const& bs) { - using net::buffer_size; std::size_t n = 0; for(auto it = bs.end(); it != bs.begin();) - n += buffer_size(*--it); + n += net::buffer_size(*--it); return n; } @@ -79,12 +61,11 @@ public: std::size_t bsize4(ConstBufferSequence const& bs) { - using net::buffer_size; std::size_t n = 0; for(auto it = bs.end(); it != bs.begin();) { it--; - n += buffer_size(*it); + n += net::buffer_size(*it); } return n; } @@ -121,26 +102,27 @@ public: void testEmptyBuffers() { - using net::buffer_copy; using net::buffer_size; - using net::mutable_buffer; - auto pb0 = buffers_prefix(0, mutable_buffer{}); - BEAST_EXPECT(buffer_size(pb0) == 0); - auto pb1 = buffers_prefix(1, mutable_buffer{}); - BEAST_EXPECT(buffer_size(pb1) == 0); - BEAST_EXPECT(buffer_copy(pb0, pb1) == 0); + auto pb0 = buffers_prefix(0, net::mutable_buffer{}); + BEAST_EXPECT(buffer_size(pb0) == 0); + auto pb1 = buffers_prefix(1, net::mutable_buffer{}); + BEAST_EXPECT(buffer_size(pb1) == 0); + BEAST_EXPECT(net::buffer_copy(pb0, pb1) == 0); + +#if 0 using pb_type = decltype(pb0); buffers_suffix cb(pb0); BEAST_EXPECT(buffer_size(cb) == 0); - BEAST_EXPECT(buffer_copy(cb, pb1) == 0); + BEAST_EXPECT(net::buffer_copy(cb, pb1) == 0); cb.consume(1); BEAST_EXPECT(buffer_size(cb) == 0); - BEAST_EXPECT(buffer_copy(cb, pb1) == 0); + BEAST_EXPECT(net::buffer_copy(cb, pb1) == 0); auto pbc = buffers_prefix(2, cb); BEAST_EXPECT(buffer_size(pbc) == 0); - BEAST_EXPECT(buffer_copy(pbc, cb) == 0); + BEAST_EXPECT(net::buffer_copy(pbc, cb) == 0); +#endif } void testIterator() @@ -157,6 +139,73 @@ public: BEAST_EXPECT(bsize2(pb) == 2); BEAST_EXPECT(bsize3(pb) == 2); BEAST_EXPECT(bsize4(pb) == 2); + + // default ctor is one past the end + decltype(pb)::const_iterator it; + BEAST_EXPECT(pb.end() == it); + BEAST_EXPECT(it == pb.end()); + decltype(pb)::const_iterator it2; + BEAST_EXPECT(it == it2); + BEAST_EXPECT(it2 == it); + it = pb.end(); + it2 = pb.end(); + BEAST_EXPECT(it == it2); + BEAST_EXPECT(it2 == it); + decltype(pb)::const_iterator it3(it2); + BEAST_EXPECT(it3 == it2); + it = pb.begin(); + BEAST_EXPECT(it != it3); + it = it3; + BEAST_EXPECT(it == it3); + } + + void testInPlaceInit() + { + { + class test_buffers + { + net::const_buffer cb_; + + public: + using const_iterator = + net::const_buffer const*; + + explicit + test_buffers(std::true_type) + { + } + + const_iterator + begin() const + { + return &cb_; + } + + const_iterator + end() const + { + return begin() + 1; + } + }; + buffers_prefix_view v( + 2, boost::in_place_init, std::true_type{}); + BEAST_EXPECT(buffer_size(v) == 0); + } + + { + char c[2]; + c[0] = 0; + c[1] = 0; + buffers_prefix_view v( + 2, boost::in_place_init, c, sizeof(c)); + BEAST_EXPECT(buffer_size(v) == 2); + } + { + char c[2]; + buffers_prefix_view v( + 2, boost::in_place_init, c, sizeof(c)); + BEAST_EXPECT(buffer_size(v) == 2); + } } void run() override @@ -165,6 +214,7 @@ public: testMatrix(); testEmptyBuffers(); testIterator(); + testInPlaceInit(); } };