diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a55780e..5511df80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ Version 200 API Changes: -* buffers_adaptor is renamed (was buffers_adapter) +* buffers_adaptor replaces buffers_adapter (rename) +* make_printable replaces buffers (rename) Actions Required: @@ -29,6 +30,9 @@ Actions Required: replace buffers_adapter with buffers_adaptor. Or, define BOOST_BEAST_ALLOW_DEPRECATED +* Replace call sites to use make_printable instead of buffers, + and also include make_printable.hpp instead of ostream.hpp. + -------------------------------------------------------------------------------- Version 199: diff --git a/doc/qbk/03_core/3_buffers.qbk b/doc/qbk/03_core/3_buffers.qbk index a84a6944..cf61e471 100644 --- a/doc/qbk/03_core/3_buffers.qbk +++ b/doc/qbk/03_core/3_buffers.qbk @@ -146,7 +146,7 @@ output streams. [table Buffer Output Streams [[Name][Description]] [[ - [link beast.ref.boost__beast__buffers `buffers`] + [link beast.ref.boost__beast__make_printable `make_printable`] ][ This function wraps a __ConstBufferSequence__ so it may be used with `operator<<` and `std::ostream`. diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index fbbb3341..220d2bba 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -214,7 +214,7 @@ bind_handler bind_front_handler - buffers + make_printable buffers_cat buffers_front buffers_prefix diff --git a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp index a29fc8da..2135a22b 100644 --- a/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp +++ b/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp @@ -193,8 +193,8 @@ public: // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(buffer_.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer_.data()) << std::endl; } }; diff --git a/example/websocket/client/async/websocket_client_async.cpp b/example/websocket/client/async/websocket_client_async.cpp index 2e95bdab..6d1e40e4 100644 --- a/example/websocket/client/async/websocket_client_async.cpp +++ b/example/websocket/client/async/websocket_client_async.cpp @@ -173,8 +173,8 @@ public: // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(buffer_.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer_.data()) << std::endl; } }; diff --git a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp index 322e5a31..59e48e4d 100644 --- a/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp +++ b/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp @@ -85,10 +85,10 @@ do_session( return fail(ec, "write"); // This buffer will hold the incoming message - beast::multi_buffer b; + beast::multi_buffer buffer; // Read a message into our buffer - ws.async_read(b, yield[ec]); + ws.async_read(buffer, yield[ec]); if(ec) return fail(ec, "read"); @@ -99,8 +99,8 @@ do_session( // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(b.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer.data()) << std::endl; } //------------------------------------------------------------------------------ diff --git a/example/websocket/client/coro/websocket_client_coro.cpp b/example/websocket/client/coro/websocket_client_coro.cpp index f9e82efb..c4c7497e 100644 --- a/example/websocket/client/coro/websocket_client_coro.cpp +++ b/example/websocket/client/coro/websocket_client_coro.cpp @@ -74,10 +74,10 @@ do_session( return fail(ec, "write"); // This buffer will hold the incoming message - beast::multi_buffer b; + beast::multi_buffer buffer; // Read a message into our buffer - ws.async_read(b, yield[ec]); + ws.async_read(buffer, yield[ec]); if(ec) return fail(ec, "read"); @@ -88,8 +88,8 @@ do_session( // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(b.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer.data()) << std::endl; } //------------------------------------------------------------------------------ diff --git a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp index b83e51d7..7f4402fa 100644 --- a/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp +++ b/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp @@ -79,18 +79,18 @@ int main(int argc, char** argv) ws.write(net::buffer(std::string(text))); // This buffer will hold the incoming message - beast::multi_buffer b; + beast::multi_buffer buffer; // Read a message into our buffer - ws.read(b); + ws.read(buffer); // Close the WebSocket connection ws.close(websocket::close_code::normal); // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(b.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer.data()) << std::endl; } catch(std::exception const& e) { diff --git a/example/websocket/client/sync/websocket_client_sync.cpp b/example/websocket/client/sync/websocket_client_sync.cpp index 6543d6ed..3821618f 100644 --- a/example/websocket/client/sync/websocket_client_sync.cpp +++ b/example/websocket/client/sync/websocket_client_sync.cpp @@ -77,8 +77,8 @@ int main(int argc, char** argv) // If we get here then the connection is closed gracefully - // The buffers() function helps print a ConstBufferSequence - std::cout << beast::buffers(buffer.data()) << std::endl; + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer.data()) << std::endl; } catch(std::exception const& e) { diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index 15fc4867..642d6eda 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/beast/core/detail/ostream.hpp b/include/boost/beast/core/detail/ostream.hpp index 57e4e516..4356cd34 100644 --- a/include/boost/beast/core/detail/ostream.hpp +++ b/include/boost/beast/core/detail/ostream.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,38 +25,6 @@ namespace boost { namespace beast { namespace detail { -template -class buffers_helper -{ - Buffers b_; - -public: - explicit - buffers_helper(Buffers const& b) - : b_(b) - { - } - - template - friend - std::ostream& - operator<<(std::ostream& os, - buffers_helper const& v); -}; - -template -std::ostream& -operator<<(std::ostream& os, - buffers_helper const& v) -{ - for(auto b : buffers_range(std::ref(v.b_))) - os.write(static_cast( - b.data()), b.size()); - return os; -} - -//------------------------------------------------------------------------------ - struct basic_streambuf_movable_helper : std::basic_streambuf> { @@ -67,12 +35,12 @@ struct basic_streambuf_movable_helper : using basic_streambuf_movable = std::is_move_constructible; -//------------------------------------------------------------------------------ - template class ostream_buffer; +//------------------------------------------------------------------------------ + template class ostream_buffer @@ -136,6 +104,8 @@ public: } }; +//------------------------------------------------------------------------------ + // This nonsense is all to work around a glitch in libstdc++ // where std::basic_streambuf copy constructor is private: // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799 diff --git a/include/boost/beast/core/make_printable.hpp b/include/boost/beast/core/make_printable.hpp new file mode 100644 index 00000000..f3eaa4c3 --- /dev/null +++ b/include/boost/beast/core/make_printable.hpp @@ -0,0 +1,107 @@ +// +// 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_MAKE_PRINTABLE_HPP +#define BOOST_BEAST_MAKE_PRINTABLE_HPP + +#include +#include +#include + +namespace boost { +namespace beast { + +namespace detail { + +template +class make_printable_adaptor +{ + Buffers b_; + +public: + explicit + make_printable_adaptor(Buffers const& b) + : b_(b) + { + } + + template + friend + std::ostream& + operator<<(std::ostream& os, + make_printable_adaptor const& v); +}; + +template +std::ostream& +operator<<(std::ostream& os, + make_printable_adaptor const& v) +{ + for( + auto it = net::buffer_sequence_begin(v.b_), + end = net::buffer_sequence_end(v.b_); + it != end; + ++it) + { + net::const_buffer cb = *it; + os.write(static_cast( + cb.data()), cb.size()); + } + return os; +} + +} // detail + +/** Helper to permit a buffer sequence to be printed to a std::ostream + + This function is used to wrap a buffer sequence to allow it to + be interpreted as characters and written to a `std::ostream` such + as `std::cout`. No character translation is performed; unprintable + and null characters will be transferred as-is to the output stream. + + @par Example + This function prints the size and contents of a buffer sequence + to standard output: + @code + template + void + print (ConstBufferSequence const& buffers) + { + using net::buffer_size; + std::cout << + "Buffer size: " << buffer_size(buffers) << " bytes\n" + "Buffer data: '" << make_printable(buffers) << "'\n"; + } + @endcode + + @param buffers An object meeting the requirements of + ConstBufferSequence to be streamed. The implementation + will make a copy of this object. Ownership of the underlying + memory is not transferred, the application is still responsible + for managing its lifetime. +*/ +template +#if BOOST_BEAST_DOXYGEN +__implementation_defined__ +#else +detail::make_printable_adaptor +#endif +make_printable(ConstBufferSequence const& buffers) +{ + static_assert(net::is_const_buffer_sequence< + ConstBufferSequence>::value, + "ConstBufferSequence requirements not met"); + return detail::make_printable_adaptor< + ConstBufferSequence>{buffers}; +} + +} // beast +} // boost + +#endif diff --git a/include/boost/beast/core/ostream.hpp b/include/boost/beast/core/ostream.hpp index 0523c87f..9daabea6 100644 --- a/include/boost/beast/core/ostream.hpp +++ b/include/boost/beast/core/ostream.hpp @@ -17,45 +17,13 @@ #include #include +#ifdef BOOST_BEAST_ALLOW_DEPRECATED +#include +#endif + namespace boost { namespace beast { -/** Return an object representing a @b ConstBufferSequence. - - This function wraps a reference to a buffer sequence and permits - the following operation: - - @li `operator<<` to `std::ostream`. No character translation is - performed; unprintable and null characters will be transferred - as-is to the output stream. - - @par Example - @code - multi_buffer b; - ... - std::cout << buffers(b.data()) << std::endl; - @endcode - - @param b An object meeting the requirements of @b ConstBufferSequence - to be streamed. The implementation will make a copy of this object. - Ownership of the underlying memory is not transferred, the application - is still responsible for managing its lifetime. -*/ -template -#if BOOST_BEAST_DOXYGEN -__implementation_defined__ -#else -detail::buffers_helper -#endif -buffers(ConstBufferSequence const& b) -{ - static_assert(net::is_const_buffer_sequence< - ConstBufferSequence>::value, - "ConstBufferSequence requirements not met"); - return detail::buffers_helper< - ConstBufferSequence>{b}; -} - /** Return an output stream that formats values into a @b DynamicBuffer. This function wraps the caller provided @b DynamicBuffer into @@ -98,6 +66,25 @@ ostream(DynamicBuffer& buffer) detail::basic_streambuf_movable::value>{buffer}; } +//------------------------------------------------------------------------------ + +#ifdef BOOST_BEAST_ALLOW_DEPRECATED +template +detail::make_printable_adaptor +buffers(T const& t) +{ + return make_printable(t); +} +#else +template +void buffers(T const&) +{ + static_assert(sizeof(T) == 0, + "The function buffers() is deprecated, use make_printable() instead, " + "or define BOOST_BEAST_ALLOW_DEPRECATED to silence this error."); +} +#endif + } // beast } // boost diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index 53efbe5e..c74d8c02 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -36,6 +36,7 @@ add_executable (tests-beast-core flat_buffer.cpp flat_static_buffer.cpp handler_ptr.cpp + make_printable.cpp multi_buffer.cpp ostream.cpp read_size.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index c09167b3..a634e848 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -26,6 +26,7 @@ local SOURCES = flat_buffer.cpp flat_static_buffer.cpp handler_ptr.cpp + make_printable.cpp multi_buffer.cpp ostream.cpp read_size.cpp diff --git a/test/beast/core/make_printable.cpp b/test/beast/core/make_printable.cpp new file mode 100644 index 00000000..002cd2b8 --- /dev/null +++ b/test/beast/core/make_printable.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2016-2017 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 "buffer_test.hpp" + +namespace boost { +namespace beast { + +class make_printable_test : public beast::unit_test::suite +{ +public: + template + void + print (ConstBufferSequence const& buffers) + { + using net::buffer_size; + std::cout << + "Buffer size: " << buffer_size(buffers) << " bytes\n" + "Buffer data: '" << make_printable(buffers) << "'\n"; + } + + void + testJavadoc() + { + BEAST_EXPECT(&make_printable_test::print); + } + + void + testMakePrintable() + { + using net::buffer; + + char buf[13]; + buffers_triple b(buf, sizeof(buf)); + string_view src = "Hello, world!"; + BEAST_EXPECT(src.size() == sizeof(buf)); + net::buffer_copy(b, + net::const_buffer(src.data(), src.size())); + std::ostringstream ss; + ss << make_printable(b); + BEAST_EXPECT(ss.str() == src); + } + + void + run() override + { + testJavadoc(); + testMakePrintable(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,make_printable); + +} // beast +} // boost