From c4f4087888ece9dd1ab9758c5ac27dd55663e4c7 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Wed, 19 Dec 2018 19:15:04 -0800 Subject: [PATCH] Add buffers_range_ref (replaces reference_wrapper parameter) --- CHANGELOG.md | 1 + doc/qbk/03_core/3_buffers.qbk | 9 ++ doc/qbk/quickref.xml | 1 + include/boost/beast/core/buffers_range.hpp | 100 ++++++++++++------ .../boost/beast/core/buffers_to_string.hpp | 2 +- .../boost/beast/http/impl/file_body_win32.ipp | 2 +- include/boost/beast/http/impl/write.ipp | 2 +- include/boost/beast/http/string_body.hpp | 2 +- include/boost/beast/websocket/detail/mask.hpp | 10 +- .../beast/websocket/detail/utf8_checker.hpp | 7 +- include/boost/beast/websocket/impl/write.ipp | 2 +- test/beast/core/buffers_range.cpp | 41 +++++++ test/bench/buffers/bench_buffers.cpp | 2 +- test/bench/parser/nodejs_parser.hpp | 2 +- 14 files changed, 139 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aad90f5..d74e6bfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Version 200 * HTTP tidying * Adjust static_asio lib options in Jamfile * Add type_traits tests +* Add buffers_range_ref (replaces reference_wrapper parameter) API Changes: diff --git a/doc/qbk/03_core/3_buffers.qbk b/doc/qbk/03_core/3_buffers.qbk index cf61e471..aa954b8e 100644 --- a/doc/qbk/03_core/3_buffers.qbk +++ b/doc/qbk/03_core/3_buffers.qbk @@ -57,6 +57,7 @@ transferred. ]] [[ [link beast.ref.boost__beast__buffers_range `buffers_range`] + [link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`] ][ This function returns an iterable range representing the passed buffer sequence. The values obtained when iterating the range @@ -64,6 +65,14 @@ transferred. sequence is mutable, in which case the value obtained when iterating will be a mutable buffer. It is intended as a notational convenience when writing a ['range-for] statement over a buffer sequence. + + The function + [link beast.ref.boost__beast__buffers_range_ref `buffers_range`] + maintains a copy of the buffer sequence, while + [link beast.ref.boost__beast__buffers_range_ref `buffers_range_ref`] + maintains a reference (in this case, the caller must ensure that + the lifetime of the referenced buffer sequence extends until the + range object is destroyed). ]] [[ [link beast.ref.boost__beast__buffers_suffix `buffers_suffix`] diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index 220d2bba..83e6105d 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -219,6 +219,7 @@ buffers_front buffers_prefix buffers_range + buffers_range_ref buffers_to_string generic_category iequals diff --git a/include/boost/beast/core/buffers_range.hpp b/include/boost/beast/core/buffers_range.hpp index 1d0c882e..cdc40768 100644 --- a/include/boost/beast/core/buffers_range.hpp +++ b/include/boost/beast/core/buffers_range.hpp @@ -11,9 +11,8 @@ #define BOOST_BEAST_BUFFERS_RANGE_HPP #include +#include #include -#include -#include namespace boost { namespace beast { @@ -22,65 +21,104 @@ namespace beast { This function returns an iterable range representing the passed buffer sequence. The values obtained when iterating - the range will always be `const_buffer`, unless the underlying - buffer sequence is a @em MutableBufferSequence, in which case - the value obtained when iterating will be a `mutable_buffer`. + the range will be `net::const_buffer`, unless the underlying + buffer sequence is a MutableBufferSequence, in which case + the value obtained when iterating will be a `net::mutable_buffer`. @par Example The following function returns the total number of bytes in - the specified buffer sequence: + the specified buffer sequence. A copy of the buffer sequence + is maintained for the lifetime of the range object: @code - template - std::size_t buffer_sequence_size(ConstBufferSequence const& buffers) + template + std::size_t buffer_sequence_size (BufferSequence const& buffers) { std::size_t size = 0; - for(auto const buffer : buffers_range(std::ref(buffers))) + for (auto const buffer : buffers_range (buffers)) size += buffer.size(); return size; } @endcode @param buffers The buffer sequence to adapt into a range. The - range returned from this function will contain a copy of the - passed buffer sequence. If `buffers` is a `std::reference_wrapper`, - the range returned from this function will contain a reference to the - passed buffer sequence. In this case, the caller is responsible - for ensuring that the lifetime of the buffer sequence is valid for - the lifetime of the returned range. + range object returned from this function will contain a copy + of the passed buffer sequence. - @return An object of unspecified type, meeting the requirements of - ConstBufferSequence, and also @em MutableBufferSequence if `buffers` - is a mutable buffer sequence. + @return An object of unspecified type which meets the requirements + of ConstBufferSequence. If `buffers` is a mutable buffer + sequence, the returned object will also meet the requirements of + MutableBufferSequence. + + @see @ref buffers_range_ref */ -/** @{ */ -template +template #if BOOST_BEAST_DOXYGEN __implementation_defined__ #else -detail::buffers_range_adaptor +detail::buffers_range_adaptor #endif -buffers_range(ConstBufferSequence const& buffers) +buffers_range(BufferSequence const& buffers) { static_assert( - net::is_const_buffer_sequence::value, - "ConstBufferSequence requirements not met"); - return detail::buffers_range_adaptor(buffers); + is_const_buffer_sequence::value, + "BufferSequence requirements not met"); + return detail::buffers_range_adaptor< + BufferSequence>(buffers); } -template +/** Returns an iterable range representing a buffer sequence. + + This function returns an iterable range representing the + passed buffer sequence. The values obtained when iterating + the range will be `net::const_buffer`, unless the underlying + buffer sequence is a MutableBufferSequence, in which case + the value obtained when iterating will be a `net::mutable_buffer`. + + @par Example + + The following function returns the total number of bytes in + the specified buffer sequence. A reference to the original + buffers is maintained for the lifetime of the range object: + + @code + template + std::size_t buffer_sequence_size_ref (BufferSequence const& buffers) + { + std::size_t size = 0; + for (auto const buffer : buffers_range_ref (buffers)) + size += buffer.size(); + return size; + } + @endcode + + @param buffers The buffer sequence to adapt into a range. The + range returned from this function will maintain a reference to + these buffers. The application is responsible for ensuring that + the lifetime of the referenced buffers extends until the range + object is destroyed. + + @return An object of unspecified type which meets the requirements + of ConstBufferSequence. If `buffers` is a mutable buffer + sequence, the returned object will also meet the requirements of + MutableBufferSequence. + + @see @ref buffers_range +*/ +template #if BOOST_BEAST_DOXYGEN __implementation_defined__ #else -detail::buffers_range_adaptor +detail::buffers_range_adaptor #endif -buffers_range(std::reference_wrapper buffers) +buffers_range_ref(BufferSequence const& buffers) { static_assert( - net::is_const_buffer_sequence::value, - "ConstBufferSequence requirements not met"); - return detail::buffers_range_adaptor(buffers.get()); + is_const_buffer_sequence::value, + "BufferSequence requirements not met"); + return detail::buffers_range_adaptor< + BufferSequence const&>(buffers); } /** @} */ diff --git a/include/boost/beast/core/buffers_to_string.hpp b/include/boost/beast/core/buffers_to_string.hpp index 8aed006c..a36ced58 100644 --- a/include/boost/beast/core/buffers_to_string.hpp +++ b/include/boost/beast/core/buffers_to_string.hpp @@ -50,7 +50,7 @@ buffers_to_string(ConstBufferSequence const& buffers) std::string result; using net::buffer_size; result.reserve(buffer_size(buffers)); - for(auto const buffer : beast::buffers_range(std::ref(buffers))) + for(auto const buffer : beast::buffers_range_ref(buffers)) result.append(static_cast( buffer.data()), buffer.size()); return result; diff --git a/include/boost/beast/http/impl/file_body_win32.ipp b/include/boost/beast/http/impl/file_body_win32.ipp index 279e01a8..2d96ee9e 100644 --- a/include/boost/beast/http/impl/file_body_win32.ipp +++ b/include/boost/beast/http/impl/file_body_win32.ipp @@ -192,7 +192,7 @@ struct basic_file_body error_code& ec) { std::size_t nwritten = 0; - for(auto buffer : beast::buffers_range(std::ref(buffers))) + for(auto buffer : beast::buffers_range_ref(buffers)) { nwritten += body_.file_.write( buffer.data(), buffer.size(), ec); diff --git a/include/boost/beast/http/impl/write.ipp b/include/boost/beast/http/impl/write.ipp index 180a029d..a08be699 100644 --- a/include/boost/beast/http/impl/write.ipp +++ b/include/boost/beast/http/impl/write.ipp @@ -936,7 +936,7 @@ public: if(os_.fail()) return; std::size_t bytes_transferred = 0; - for(auto b : beast::buffers_range(std::ref(buffers))) + for(auto b : beast::buffers_range_ref(buffers)) { os_.write(static_cast( b.data()), b.size()); diff --git a/include/boost/beast/http/string_body.hpp b/include/boost/beast/http/string_body.hpp index bc324b6f..95b69622 100644 --- a/include/boost/beast/http/string_body.hpp +++ b/include/boost/beast/http/string_body.hpp @@ -132,7 +132,7 @@ public: } ec.assign(0, ec.category()); CharT* dest = &body_[size]; - for(auto b : beast::buffers_range(std::ref(buffers))) + for(auto b : beast::buffers_range_ref(buffers)) { Traits::copy(dest, static_cast< CharT const*>(b.data()), b.size()); diff --git a/include/boost/beast/websocket/detail/mask.hpp b/include/boost/beast/websocket/detail/mask.hpp index cf3ecab1..bbb544e7 100644 --- a/include/boost/beast/websocket/detail/mask.hpp +++ b/include/boost/beast/websocket/detail/mask.hpp @@ -71,12 +71,16 @@ mask_inplace(net::mutable_buffer& b, prepared_key& key) // Apply mask in place // -template +template< + class MutableBufferSequence, + class KeyType> void -mask_inplace(MutableBuffers const& bs, KeyType& key) +mask_inplace( + MutableBufferSequence const& buffers, + KeyType& key) { for(net::mutable_buffer b : - beast::buffers_range(std::ref(bs))) + beast::buffers_range_ref(buffers)) mask_inplace(b, key); } diff --git a/include/boost/beast/websocket/detail/utf8_checker.hpp b/include/boost/beast/websocket/detail/utf8_checker.hpp index 7b09b337..ae37441e 100644 --- a/include/boost/beast/websocket/detail/utf8_checker.hpp +++ b/include/boost/beast/websocket/detail/utf8_checker.hpp @@ -84,11 +84,12 @@ template template bool utf8_checker_t<_>:: -write(ConstBufferSequence const& bs) +write(ConstBufferSequence const& buffers) { - static_assert(net::is_const_buffer_sequence::value, + static_assert( + net::is_const_buffer_sequence::value, "ConstBufferSequence requirements not met"); - for(auto b : beast::buffers_range(std::ref(bs))) + for(auto b : beast::buffers_range_ref(buffers)) if(! write(static_cast< std::uint8_t const*>(b.data()), b.size())) diff --git a/include/boost/beast/websocket/impl/write.ipp b/include/boost/beast/websocket/impl/write.ipp index 12f10bbd..08dce136 100644 --- a/include/boost/beast/websocket/impl/write.ipp +++ b/include/boost/beast/websocket/impl/write.ipp @@ -60,7 +60,7 @@ deflate( zs.next_in = nullptr; zs.avail_out = out.size(); zs.next_out = out.data(); - for(auto in : beast::buffers_range(std::ref(cb))) + for(auto in : beast::buffers_range_ref(cb)) { zs.avail_in = in.size(); if(zs.avail_in == 0) diff --git a/test/beast/core/buffers_range.cpp b/test/beast/core/buffers_range.cpp index d0e62ac8..d441492c 100644 --- a/test/beast/core/buffers_range.cpp +++ b/test/beast/core/buffers_range.cpp @@ -20,11 +20,51 @@ namespace beast { class buffers_range_test : public beast::unit_test::suite { public: + BOOST_STATIC_ASSERT( + is_const_buffer_sequence< + decltype(beast::buffers_range( + std::declval()))>::value); + + BOOST_STATIC_ASSERT( + is_const_buffer_sequence< + decltype(beast::buffers_range( + std::declval()))>::value); + + BOOST_STATIC_ASSERT( + ! net::is_mutable_buffer_sequence< + decltype(beast::buffers_range( + std::declval()))>::value); + BOOST_STATIC_ASSERT( net::is_mutable_buffer_sequence< decltype(beast::buffers_range( std::declval()))>::value); + template + std::size_t buffer_sequence_size (BufferSequence const& buffers) + { + std::size_t size = 0; + for (auto const buffer : buffers_range (buffers)) + size += buffer.size(); + return size; + } + + template + std::size_t buffer_sequence_size_ref (BufferSequence const& buffers) + { + std::size_t size = 0; + for (auto const buffer : buffers_range_ref (buffers)) + size += buffer.size(); + return size; + } + + void + testJavadocs() + { + BEAST_EXPECT(&buffers_range_test::buffer_sequence_size); + BEAST_EXPECT(&buffers_range_test::buffer_sequence_size_ref); + } + void testBufferSequence() { @@ -44,6 +84,7 @@ public: void run() override { + testJavadocs(); testBufferSequence(); } }; diff --git a/test/bench/buffers/bench_buffers.cpp b/test/bench/buffers/bench_buffers.cpp index 1548923e..bedf6b0b 100644 --- a/test/bench/buffers/bench_buffers.cpp +++ b/test/bench/buffers/bench_buffers.cpp @@ -68,7 +68,7 @@ public: fill(MutableBufferSequence const& buffers) { std::size_t n = 0; - for(auto b : beast::buffers_range(std::ref(buffers))) + for(auto b : beast::buffers_range_ref(buffers)) { std::fill( static_cast(b.data()), diff --git a/test/bench/parser/nodejs_parser.hpp b/test/bench/parser/nodejs_parser.hpp index 818734bf..951a926b 100644 --- a/test/bench/parser/nodejs_parser.hpp +++ b/test/bench/parser/nodejs_parser.hpp @@ -269,7 +269,7 @@ nodejs_basic_parser::write( ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); std::size_t bytes_used = 0; - for(auto buffer : beast::buffers_range(std::ref(buffers))) + for(auto buffer : beast::buffers_range_ref(buffers)) { auto const n = write( static_cast(buffer.data()),