diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f45c14f..ccec073e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Version 209: * async_echo supports move-only handlers * test::stream maintains a handler work guard * Qualify buffer_copy, don't qualify buffer_size +* Add dynamic_buffer_ref -------------------------------------------------------------------------------- diff --git a/doc/qbk/03_core/4_buffers.qbk b/doc/qbk/03_core/4_buffers.qbk index aa954b8e..7d8a0637 100644 --- a/doc/qbk/03_core/4_buffers.qbk +++ b/doc/qbk/03_core/4_buffers.qbk @@ -125,6 +125,15 @@ set of additional implementations of the dynamic buffer concept: The basic container is an [@https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer [*AllocatorAwareContainer]]. ]] +[[ + [link beast.ref.boost__beast__dynamic_buffer_ref `dynamic_buffer_ref`] + [link beast.ref.boost__beast__dynamic_buffer_ref_wrapper `dynamic_buffer_ref_wrapper`] +][ + This function returns a wrapper containing a reference to the passed + dynamic buffer, permitting a Beast dynamic buffer type (which acts + like a true container type) to be used with Networking algorithms + which want to take ownership of the dynamic buffer in their interface. +]] [[ [link beast.ref.boost__beast__flat_static_buffer `flat_static_buffer`] [link beast.ref.boost__beast__flat_static_buffer_base `flat_static_buffer_base`] diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index b68d4016..6b4a759c 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -186,6 +186,7 @@ buffers_cat_view buffers_prefix_view buffers_suffix + dynamic_buffer_ref_wrapper file file_mode file_posix @@ -236,6 +237,7 @@ buffers_range_ref buffers_to_string close_socket + dynamic_buffer_ref generic_category get_lowest_layer iequals diff --git a/include/boost/beast/_experimental/core/detail/dynamic_buffer_ref.hpp b/include/boost/beast/_experimental/core/detail/dynamic_buffer_ref.hpp deleted file mode 100644 index 12efae65..00000000 --- a/include/boost/beast/_experimental/core/detail/dynamic_buffer_ref.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_CORE_DETAIL_DYNAMIC_BUFFER_REF_HPP -#define BOOST_BEAST_CORE_DETAIL_DYNAMIC_BUFFER_REF_HPP - -#include -#include -#include - -namespace boost { -namespace beast { -namespace detail { - -template -class dynamic_buffer_ref -{ - DynamicBuffer& b_; - -public: - using const_buffers_type = typename - DynamicBuffer::const_buffers_type; - - using mutable_buffers_type = typename - DynamicBuffer::mutable_buffers_type; - - dynamic_buffer_ref( - dynamic_buffer_ref&&) = default; - - explicit - dynamic_buffer_ref( - DynamicBuffer& b) noexcept - : b_(b) - { - } - - std::size_t - size() const noexcept - { - return b_.size(); - } - - std::size_t - max_size() const noexcept - { - return b_.max_size(); - } - - std::size_t - capacity() const noexcept - { - return b_.capacity(); - } - - const_buffers_type - data() const noexcept - { - return b_.data(); - } - - mutable_buffers_type - prepare(std::size_t n) - { - return b_.prepare(n); - } - - void - commit(std::size_t n) - { - b_.commit(n); - } - - void - consume(std::size_t n) - { - b_.consume(n); - } -}; - -template -typename std::enable_if< - net::is_dynamic_buffer::value, - dynamic_buffer_ref>::type -ref(DynamicBuffer& b) -{ - return dynamic_buffer_ref(b); -} - -} // detail -} // beast -} // boost - -#endif diff --git a/include/boost/beast/_experimental/http/impl/icy_stream.hpp b/include/boost/beast/_experimental/http/impl/icy_stream.hpp index b3f640a3..e390a9ac 100644 --- a/include/boost/beast/_experimental/http/impl/icy_stream.hpp +++ b/include/boost/beast/_experimental/http/impl/icy_stream.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP #define BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP -#include +#include #include #include #include @@ -164,7 +164,7 @@ public: std::size_t bytes_transferred) { using iterator = net::buffers_iterator< - typename beast::detail::dynamic_buffer_ref< + typename beast::dynamic_buffer_ref_wrapper< buffers_adaptor>::const_buffers_type>; BOOST_ASIO_CORO_REENTER(*this) { @@ -250,7 +250,7 @@ public: BOOST_ASIO_CORO_YIELD net::async_read_until( d_.s.next_layer(), - beast::detail::ref(d_.b), + beast::dynamic_buffer_ref(d_.b), detail::match_icy(d_.match), std::move(*this)); if(ec) @@ -329,7 +329,7 @@ read_some(MutableBufferSequence const& buffers, error_code& ec) MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); using iterator = net::buffers_iterator< - typename beast::detail::dynamic_buffer_ref< + typename beast::dynamic_buffer_ref_wrapper< buffers_adaptor>::const_buffers_type>; buffers_adaptor b(buffers); if(b.max_size() == 0) @@ -403,7 +403,7 @@ read_some(MutableBufferSequence const& buffers, error_code& ec) bool match = false; auto n = net::read_until( stream_, - beast::detail::ref(b), + beast::dynamic_buffer_ref(b), detail::match_icy(match), ec); if(ec) diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index fca13c09..b337317b 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/beast/core/dynamic_buffer_ref.hpp b/include/boost/beast/core/dynamic_buffer_ref.hpp new file mode 100644 index 00000000..5c17f4c9 --- /dev/null +++ b/include/boost/beast/core/dynamic_buffer_ref.hpp @@ -0,0 +1,140 @@ +// +// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_CORE_DYNAMIC_BUFFER_REF_HPP +#define BOOST_BEAST_CORE_DYNAMIC_BUFFER_REF_HPP + +#include +#include +#include +#include + +namespace boost { +namespace beast { + +/** A lightweight reference to a dynamic buffer. + + Objects of this type meet the requirements of DynamicBuffer. + This is the wrapper returned by the function @ref dynamic_buffer_ref. + + @see dynamic_buffer_ref +*/ +template +class dynamic_buffer_ref_wrapper +#if ! BOOST_BEAST_DOXYGEN +{ + static_assert(net::is_dynamic_buffer::value, + "DynamicBuffer requirements not met"); + + DynamicBuffer& b_; + +public: + using const_buffers_type = typename + DynamicBuffer::const_buffers_type; + + using mutable_buffers_type = typename + DynamicBuffer::mutable_buffers_type; + + dynamic_buffer_ref_wrapper( + dynamic_buffer_ref_wrapper&&) = default; + + explicit + dynamic_buffer_ref_wrapper( + DynamicBuffer& b) noexcept + : b_(b) + { + } + + std::size_t + size() const noexcept + { + return b_.size(); + } + + std::size_t + max_size() const noexcept + { + return b_.max_size(); + } + + std::size_t + capacity() const noexcept + { + return b_.capacity(); + } + + const_buffers_type + data() const noexcept + { + return b_.data(); + } + + mutable_buffers_type + prepare(std::size_t n) + { + return b_.prepare(n); + } + + void + commit(std::size_t n) + { + b_.commit(n); + } + + void + consume(std::size_t n) + { + b_.consume(n); + } +} +#endif +; + +/** Return a non-owning reference to a dynamic buffer. + + This function returns a wrapper which holds a reference to the + passed dynamic buffer. The wrapper meets the requirements of + DynamicBuffer, allowing its use in Networking algorithms + which want to take ownership of the dynamic buffer. Since Beast + dynamic buffers are true storage types, they cannot be used directly + with functions that take ownership of the dynamic buffer. + + @par Example + This function reads a line of text from a stream into a + @ref flat_buffer, using the net function `async_read_until`. The + @code + template + std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer) + { + return net::read_until(stream, dynamic_buffer_ref(buffer), "\r\n"); + } + @endcode + + @param buffer The dynamic buffer to wrap. Ownership of the buffer is + not transferred, the caller is still responsible for managing the + lifetime of the original object. + + @return A wrapper meeting the requirements of DynamicBuffer + which references the original dynamic buffer. + + @see dynamic_buffer_ref_wrapper +*/ +template +dynamic_buffer_ref_wrapper +dynamic_buffer_ref(DynamicBuffer& buffer) noexcept +{ + static_assert(net::is_dynamic_buffer::value, + "DynamicBuffer requirements not met"); + return dynamic_buffer_ref_wrapper(buffer); +} + +} // beast +} // boost + +#endif diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index 7b285631..72ee830f 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable (tests-beast-core buffers_suffix.cpp buffers_to_string.cpp close_socket.cpp + dynamic_buffer_ref.cpp error.cpp file.cpp file_posix.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index 51aa2a9b..ebbb8d53 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -29,6 +29,7 @@ local SOURCES = buffers_suffix.cpp buffers_to_string.cpp close_socket.cpp + dynamic_buffer_ref.cpp error.cpp file.cpp file_posix.cpp diff --git a/test/beast/core/dynamic_buffer_ref.cpp b/test/beast/core/dynamic_buffer_ref.cpp new file mode 100644 index 00000000..a0b6785d --- /dev/null +++ b/test/beast/core/dynamic_buffer_ref.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +#include + +#include +#include +#include +#include + +namespace boost { +namespace beast { + +namespace { + +template +std::size_t read_line (SyncReadStream& stream, flat_buffer& buffer) +{ + return net::read_until(stream, dynamic_buffer_ref(buffer), "\r\n"); +} + +} // (anon) + +class dynamic_buffer_ref_test : public beast::unit_test::suite +{ +public: + void + testJavadocs() + { + BEAST_EXPECT(static_cast< + std::size_t(*)(test::stream&, flat_buffer&)>( + &read_line)); + } + + void run() override + { + testJavadocs(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,dynamic_buffer_ref); + +} // beast +} // boost