diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96bf8e0c..8c4ce4d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ API Changes:
* Refactor http::header contents
* New ostream() returns dynamic buffer output stream
+* New buffers() replaces to_string()
--------------------------------------------------------------------------------
diff --git a/doc/quickref.xml b/doc/quickref.xml
index b72d05ba..3c8c7f8a 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -176,11 +176,11 @@
bind_handler
buffer_cat
+ buffers
ostream
prepare_buffer
prepare_buffers
system_category
- to_string
diff --git a/examples/ssl/websocket_ssl_example.cpp b/examples/ssl/websocket_ssl_example.cpp
index bba99c7a..214d1833 100644
--- a/examples/ssl/websocket_ssl_example.cpp
+++ b/examples/ssl/websocket_ssl_example.cpp
@@ -5,7 +5,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#include
+#include
#include
#include
#include
@@ -45,5 +45,5 @@ int main()
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
- std::cout << to_string(sb.data()) << "\n";
+ std::cout << beast::buffers(sb.data()) << "\n";
}
diff --git a/examples/websocket_example.cpp b/examples/websocket_example.cpp
index bda489be..3d7547f6 100644
--- a/examples/websocket_example.cpp
+++ b/examples/websocket_example.cpp
@@ -5,7 +5,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#include
+#include
#include
#include
#include
@@ -31,5 +31,5 @@ int main()
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
- std::cout << beast::to_string(sb.data()) << "\n";
+ std::cout << beast::buffers(sb.data()) << "\n";
}
diff --git a/include/beast/core.hpp b/include/beast/core.hpp
index c60f8e88..75c27f07 100644
--- a/include/beast/core.hpp
+++ b/include/beast/core.hpp
@@ -17,19 +17,18 @@
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
-#include
#endif
diff --git a/include/beast/core/detail/ostream.hpp b/include/beast/core/detail/ostream.hpp
index 4eb5cbdc..01853070 100644
--- a/include/beast/core/detail/ostream.hpp
+++ b/include/beast/core/detail/ostream.hpp
@@ -19,6 +19,40 @@
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)
+{
+ using boost::asio::buffer_cast;
+ using boost::asio::buffer_size;
+ for(auto const& b : v.b_)
+ os.write(buffer_cast(b),
+ buffer_size(b));
+ return os;
+}
+
+//------------------------------------------------------------------------------
+
template<
class DynamicBuffer,
class CharT,
diff --git a/include/beast/core/ostream.hpp b/include/beast/core/ostream.hpp
index a3186963..e991f5e7 100644
--- a/include/beast/core/ostream.hpp
+++ b/include/beast/core/ostream.hpp
@@ -17,6 +17,40 @@
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
+ streambuf sb;
+ ...
+ std::cout << buffers(sb.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.
+*/
+template
+#if BEAST_DOXYGEN
+implementation_defined
+#else
+detail::buffers_helper
+#endif
+buffers(ConstBufferSequence const& b)
+{
+ static_assert(is_ConstBufferSequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence 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
diff --git a/include/beast/core/to_string.hpp b/include/beast/core/to_string.hpp
deleted file mode 100644
index 14d32589..00000000
--- a/include/beast/core/to_string.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2013-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)
-//
-
-#ifndef BEAST_TO_STRING_HPP
-#define BEAST_TO_STRING_HPP
-
-#include
-#include
-#include
-#include
-
-namespace beast {
-
-/** Convert a @b `ConstBufferSequence` to a `std::string`.
-
- This function will convert the octets in a buffer sequence to a string.
- All octets will be inserted into the resulting string, including null
- or unprintable characters.
-
- @param buffers The buffer sequence to convert.
-
- @return A string representing the contents of the input area.
-
- @note This function participates in overload resolution only if
- the buffers parameter meets the requirements of @b `ConstBufferSequence`.
-*/
-template
-#if BEAST_DOXYGEN
-std::string
-#else
-typename std::enable_if<
- is_ConstBufferSequence::value,
- std::string>::type
-#endif
-to_string(ConstBufferSequence const& buffers)
-{
- using boost::asio::buffer_cast;
- using boost::asio::buffer_size;
- std::string s;
- s.reserve(buffer_size(buffers));
- for(auto const& buffer : buffers)
- s.append(buffer_cast(buffer),
- buffer_size(buffer));
- return s;
-}
-
-} // beast
-
-#endif
diff --git a/scripts/blacklist.supp b/scripts/blacklist.supp
deleted file mode 100644
index 08968f04..00000000
--- a/scripts/blacklist.supp
+++ /dev/null
@@ -1,39 +0,0 @@
-# Remember that this blacklist file is GLOBAL to all sanitizers
-# Be therefore extremely careful when considering to add a sanitizer
-# filter here instead of using a runtime suppression
-#
-# Remember also that filters here quite literally completely
-# remove instrumentation altogether, so filtering here means
-# that sanitizers such as tsan will false positive on problems
-# introduced by code filtered here.
-#
-# The main use for this file is ubsan, as it's the only sanitizer
-# without a runtime suppression facility.
-#
-# Be ESPECIALLY careful when filtering out entire source files!
-# Try if at all possible to filter only functions using fun:regex
-# Remember you must use mangled symbol names with fun:regex
-
-
-#### Compile time filters for ubsan ####
-
-## The well known ubsan failure in libstdc++ extant for years :)
-# Line 96:24: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
-fun:*_Ios_Fmtflags*
-
-# boost/any.hpp:259:16: runtime error: downcast of address 0x000004392e70 which does not point to an object of type 'any::holder'
-fun:*any_cast*
-
-# boost/lexical_cast.hpp:1625:43: runtime error: downcast of address 0x7fbb4fffbce8 which does not point to an object of type 'buffer_t' (aka 'parser_buf >, char>')
-fun:*shl_input_streamable*
-
-
-
-
-#### Compile time filters for asan ####
-
-
-#### Compile time filters for msan ####
-
-
-#### Compile time filters for tsan ####
diff --git a/test/Jamfile b/test/Jamfile
index 38759e84..bf5a2b0b 100644
--- a/test/Jamfile
+++ b/test/Jamfile
@@ -37,7 +37,6 @@ unit-test core-tests :
core/static_string.cpp
core/stream_concepts.cpp
core/streambuf.cpp
- core/to_string.cpp
core/base64.cpp
core/empty_base_optimization.cpp
core/get_lowest_layer.cpp
diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt
index 0c353d99..f1f654a6 100644
--- a/test/core/CMakeLists.txt
+++ b/test/core/CMakeLists.txt
@@ -30,7 +30,6 @@ add_executable (core-tests
static_string.cpp
stream_concepts.cpp
streambuf.cpp
- to_string.cpp
base64.cpp
empty_base_optimization.cpp
get_lowest_layer.cpp
diff --git a/test/core/buffers_adapter.cpp b/test/core/buffers_adapter.cpp
index 9f8054c6..b14dc676 100644
--- a/test/core/buffers_adapter.cpp
+++ b/test/core/buffers_adapter.cpp
@@ -8,10 +8,12 @@
// Test that header file is self-contained.
#include
+#include
#include
#include
#include
#include
+#include
#include
namespace beast {
@@ -24,14 +26,8 @@ public:
std::string
to_string(ConstBufferSequence const& bs)
{
- using boost::asio::buffer_cast;
- using boost::asio::buffer_size;
- std::string s;
- s.reserve(buffer_size(bs));
- for(auto const& b : bs)
- s.append(buffer_cast(b),
- buffer_size(b));
- return s;
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
}
void testBuffersAdapter()
diff --git a/test/core/consuming_buffers.cpp b/test/core/consuming_buffers.cpp
index d4a1dc47..2a10ab00 100644
--- a/test/core/consuming_buffers.cpp
+++ b/test/core/consuming_buffers.cpp
@@ -9,7 +9,7 @@
#include
#include "buffer_test.hpp"
-#include
+#include
#include
#include
#include
@@ -19,6 +19,15 @@ namespace beast {
class consuming_buffers_test : public beast::unit_test::suite
{
public:
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
template
static
consuming_buffers
diff --git a/test/core/flat_streambuf.cpp b/test/core/flat_streambuf.cpp
index 77d79000..fec9c452 100644
--- a/test/core/flat_streambuf.cpp
+++ b/test/core/flat_streambuf.cpp
@@ -9,9 +9,10 @@
#include
#include "buffer_test.hpp"
-#include
+#include
#include
#include
+#include
#include
namespace beast {
@@ -22,6 +23,15 @@ static_assert(is_DynamicBuffer::value,
class flat_streambuf_test : public beast::unit_test::suite
{
public:
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
template
static
bool
diff --git a/test/core/ostream.cpp b/test/core/ostream.cpp
index 055fbd15..f96fd8b7 100644
--- a/test/core/ostream.cpp
+++ b/test/core/ostream.cpp
@@ -10,10 +10,9 @@
#include
#include
+#include
#include
-#include
-
namespace beast {
class ostream_test : public beast::unit_test::suite
@@ -23,7 +22,8 @@ public:
{
streambuf sb;
ostream(sb) << "Hello, world!\n";
- BEAST_EXPECT(to_string(sb.data()) == "Hello, world!\n");
+ BEAST_EXPECT(boost::lexical_cast(
+ buffers(sb.data())) == "Hello, world!\n");
}
};
diff --git a/test/core/streambuf.cpp b/test/core/streambuf.cpp
index 02a7b56e..892aabd6 100644
--- a/test/core/streambuf.cpp
+++ b/test/core/streambuf.cpp
@@ -10,7 +10,7 @@
#include "buffer_test.hpp"
#include
-#include
+#include
#include
#include
#include
@@ -26,6 +26,15 @@ static_assert(is_DynamicBuffer::value, "");
class basic_streambuf_test : public beast::unit_test::suite
{
public:
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
template
static
bool
diff --git a/test/core/to_string.cpp b/test/core/to_string.cpp
deleted file mode 100644
index e449dd33..00000000
--- a/test/core/to_string.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2013-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)
-//
-
-// Test that header file is self-contained.
-#include
-
-#include
-#include
-
-namespace beast {
-
-class to_string_test : public beast::unit_test::suite
-{
-public:
- void run()
- {
- BEAST_EXPECT(to_string(boost::asio::const_buffers_1("x", 1)) == "x");
- }
-};
-
-BEAST_DEFINE_TESTSUITE(to_string,core,beast);
-
-} // beast
-
diff --git a/test/http/chunk_encode.cpp b/test/http/chunk_encode.cpp
index 9bbe68f3..881fa4ca 100644
--- a/test/http/chunk_encode.cpp
+++ b/test/http/chunk_encode.cpp
@@ -8,8 +8,9 @@
// Test that header file is self-contained.
#include
-#include
+#include
#include
+#include
namespace beast {
namespace http {
@@ -30,6 +31,15 @@ public:
}
};
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
static
void
encode1(std::string& s, final_chunk const& fc)
diff --git a/test/http/dynamic_body.cpp b/test/http/dynamic_body.cpp
index 77b86a91..5b06e030 100644
--- a/test/http/dynamic_body.cpp
+++ b/test/http/dynamic_body.cpp
@@ -8,7 +8,7 @@
// Test that header file is self-contained.
#include
-#include
+#include
#include
#include
#include
@@ -25,7 +25,8 @@ class dynamic_body_test : public beast::unit_test::suite
boost::asio::io_service ios_;
public:
- void run() override
+ void
+ run() override
{
std::string const s =
"HTTP/1.1 200 OK\r\n"
@@ -38,7 +39,8 @@ public:
streambuf sb;
read(ss, sb, p);
auto const& m = p.get();
- BEAST_EXPECT(to_string(m.body.data()) == "xyz");
+ BEAST_EXPECT(boost::lexical_cast(
+ buffers(m.body.data())) == "xyz");
BEAST_EXPECT(boost::lexical_cast(m) == s);
}
};
diff --git a/test/http/parser_bench.cpp b/test/http/parser_bench.cpp
index bf555f9b..9344411b 100644
--- a/test/http/parser_bench.cpp
+++ b/test/http/parser_bench.cpp
@@ -10,9 +10,10 @@
#include
#include
+#include
#include
-#include
#include
+#include
#include
#include
#include
@@ -31,6 +32,15 @@ public:
corpus cres_;
std::size_t size_ = 0;
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
parser_bench_test()
{
creq_ = build_corpus(N/2, std::true_type{});
diff --git a/test/http/write.cpp b/test/http/write.cpp
index 51bfc2f0..656e59e6 100644
--- a/test/http/write.cpp
+++ b/test/http/write.cpp
@@ -14,7 +14,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/test/websocket/ssl/ssl_server.cpp b/test/websocket/ssl/ssl_server.cpp
index 0303e4a4..cb6896c1 100644
--- a/test/websocket/ssl/ssl_server.cpp
+++ b/test/websocket/ssl/ssl_server.cpp
@@ -8,7 +8,7 @@
#include "websocket_async_ssl_echo_server.hpp"
#include
-#include
+#include
#include
#include
#include
@@ -126,7 +126,7 @@ public:
// Secure WebSocket connect and send message using Beast
beast::websocket::stream ws{stream};
ws.handshake("localhost", "/");
- ws.write(boost::asio::buffer("Hello, world!"));
+ ws.write(boost::asio::buffer("Hello, world!", 13));
// Receive Secure WebSocket message, print and close using Beast
beast::streambuf sb;
@@ -146,9 +146,8 @@ public:
if(se.code() != beast::websocket::error::closed)
throw;
}
- log << to_string(sb.data()) << std::endl;
-
- pass();
+ BEAST_EXPECT(boost::lexical_cast(
+ buffers(sb.data())) == "Hello, world!");
}
};
diff --git a/test/websocket/stream.cpp b/test/websocket/stream.cpp
index 2d3e42ee..0a1e4254 100644
--- a/test/websocket/stream.cpp
+++ b/test/websocket/stream.cpp
@@ -11,8 +11,8 @@
#include "websocket_async_echo_server.hpp"
#include "websocket_sync_echo_server.hpp"
+#include
#include
-#include
#include
#include
#include
@@ -38,6 +38,15 @@ public:
using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket;
+ template
+ static
+ std::string
+ to_string(ConstBufferSequence const& bs)
+ {
+ return boost::lexical_cast<
+ std::string>(buffers(bs));
+ }
+
struct con
{
stream ws;
@@ -1169,7 +1178,8 @@ public:
);
}
- void testMask(endpoint_type const& ep,
+ void
+ testMask(endpoint_type const& ep,
yield_context do_yield)
{
{