diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34311354..96bf8e0c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ WebSocket:
API Changes:
* Refactor http::header contents
+* New ostream() returns dynamic buffer output stream
--------------------------------------------------------------------------------
diff --git a/doc/quickref.xml b/doc/quickref.xml
index 208c3889..b72d05ba 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -176,11 +176,11 @@
bind_handler
buffer_cat
+ ostream
prepare_buffer
prepare_buffers
system_category
to_string
- write
diff --git a/include/beast/core.hpp b/include/beast/core.hpp
index b0dd3fc3..c60f8e88 100644
--- a/include/beast/core.hpp
+++ b/include/beast/core.hpp
@@ -16,6 +16,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -28,8 +30,6 @@
#include
#include
#include
-#include
#include
-#include
#endif
diff --git a/include/beast/core/detail/ostream.hpp b/include/beast/core/detail/ostream.hpp
new file mode 100644
index 00000000..4eb5cbdc
--- /dev/null
+++ b/include/beast/core/detail/ostream.hpp
@@ -0,0 +1,210 @@
+//
+// 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_DETAIL_OSTREAM_HPP
+#define BEAST_DETAIL_OSTREAM_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace beast {
+namespace detail {
+
+template<
+ class DynamicBuffer,
+ class CharT,
+ class Traits
+>
+class ostream_buffer
+ : public std::basic_streambuf
+{
+ using int_type = typename
+ std::basic_streambuf::int_type;
+
+ using traits_type = typename
+ std::basic_streambuf::traits_type;
+
+ static std::size_t constexpr max_size = 512;
+
+ DynamicBuffer& buf_;
+
+public:
+ ostream_buffer(ostream_buffer&&) = default;
+ ostream_buffer(ostream_buffer const&) = delete;
+
+ ~ostream_buffer() noexcept;
+
+ explicit
+ ostream_buffer(DynamicBuffer& buf);
+
+ int_type
+ overflow(int_type ch) override;
+
+ int
+ sync() override;
+
+private:
+ void
+ prepare();
+
+ void
+ flush(int extra = 0);
+};
+
+template
+ostream_buffer::
+~ostream_buffer() noexcept
+{
+ sync();
+}
+
+template
+ostream_buffer::
+ostream_buffer(DynamicBuffer& buf)
+ : buf_(buf)
+{
+ prepare();
+}
+
+template
+auto
+ostream_buffer::
+overflow(int_type ch) ->
+ int_type
+{
+ if(ch != traits_type::eof())
+ {
+ Traits::assign(*this->pptr(), ch);
+ flush(1);
+ prepare();
+ return ch;
+ }
+ flush();
+ return traits_type::eof();
+}
+
+template
+int
+ostream_buffer::
+sync()
+{
+ flush();
+ prepare();
+ return 0;
+}
+
+template
+void
+ostream_buffer::
+prepare()
+{
+ using boost::asio::buffer_cast;
+ using boost::asio::buffer_size;
+ auto mbs = buf_.prepare(
+ read_size_helper(buf_, max_size));
+ auto const mb = *mbs.begin();
+ auto const p = buffer_cast(mb);
+ this->setp(p,
+ p + buffer_size(mb) / sizeof(CharT) - 1);
+}
+
+template
+void
+ostream_buffer::
+flush(int extra)
+{
+ buf_.commit(
+ (this->pptr() - this->pbase() + extra) *
+ sizeof(CharT));
+}
+
+//------------------------------------------------------------------------------
+
+template
+class ostream_helper;
+
+template
+class ostream_helper<
+ DynamicBuffer, CharT, Traits, true>
+ : public std::basic_ostream
+{
+ ostream_buffer osb_;
+
+public:
+ explicit
+ ostream_helper(DynamicBuffer& buf);
+
+ ostream_helper(ostream_helper&& other);
+};
+
+template
+ostream_helper::
+ostream_helper(DynamicBuffer& buf)
+ : std::basic_ostream(
+ &this->osb_)
+ , osb_(buf)
+{
+}
+
+template
+ostream_helper::
+ostream_helper(
+ ostream_helper&& other)
+ : std::basic_ostream(&osb_)
+ , osb_(std::move(other.osb_))
+{
+}
+
+// This work-around is for libstdc++ versions that
+// don't have a movable std::basic_streambuf
+
+template
+struct ostream_helper<
+ DynamicBuffer, CharT, Traits, false>
+ : private boost::base_from_member<
+ std::unique_ptr>>
+ , std::basic_ostream
+{
+ explicit
+ ostream_helper(DynamicBuffer& buf);
+
+ ostream_helper(ostream_helper&& other);
+};
+
+template
+ostream_helper::
+ostream_helper(DynamicBuffer& buf)
+ : boost::base_from_member>>(
+ new ostream_buffer(buf))
+ , std::basic_ostream(
+ this->member.get())
+{
+}
+
+template
+ostream_helper::
+ostream_helper(ostream_helper&& other)
+ : boost::base_from_member>>(
+ std::move(other.member))
+ , std::basic_ostream(
+ this->member.get())
+{
+}
+
+} // detail
+} // beast
+
+#endif
diff --git a/include/beast/core/detail/write_dynabuf.hpp b/include/beast/core/detail/write_dynabuf.hpp
deleted file mode 100644
index dcef73af..00000000
--- a/include/beast/core/detail/write_dynabuf.hpp
+++ /dev/null
@@ -1,140 +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_DETAIL_WRITE_DYNABUF_HPP
-#define BEAST_DETAIL_WRITE_DYNABUF_HPP
-
-#include
-#include
-#include
-#include
-
-namespace beast {
-namespace detail {
-
-// detects string literals.
-template
-struct is_string_literal : std::integral_constant::type>::value &&
- std::is_same::type>::value>
-{
-};
-
-// `true` if a call to boost::asio::buffer(T const&) is possible
-// note: we exclude string literals because boost::asio::buffer()
-// will include the null terminator, which we don't want.
-template
-class is_BufferConvertible
-{
- template()),
- std::true_type{})>
- static R check(int);
- template
- static std::false_type check(...);
- using type = decltype(check(0));
-public:
- static bool const value = type::value &&
- ! is_string_literal::value;
-};
-
-template
-void
-write_dynabuf(DynamicBuffer& dynabuf,
- boost::asio::const_buffer const& buffer)
-{
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(buffer_size(buffer)),
- buffer));
-}
-
-template
-void
-write_dynabuf(DynamicBuffer& dynabuf,
- boost::asio::mutable_buffer const& buffer)
-{
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(buffer_size(buffer)),
- buffer));
-}
-
-template
-typename std::enable_if<
- is_BufferConvertible::value &&
- ! std::is_convertible::value &&
- ! std::is_convertible::value
->::type
-write_dynabuf(DynamicBuffer& dynabuf, T const& t)
-{
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- auto const buffers = boost::asio::buffer(t);
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(buffer_size(buffers)),
- buffers));
-}
-
-template
-typename std::enable_if<
- is_ConstBufferSequence::value &&
- ! is_BufferConvertible::value &&
- ! std::is_convertible::value &&
- ! std::is_convertible::value
->::type
-write_dynabuf(DynamicBuffer& dynabuf, Buffers const& buffers)
-{
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(buffer_size(buffers)),
- buffers));
-}
-
-template
-void
-write_dynabuf(DynamicBuffer& dynabuf, const char (&s)[N])
-{
- using boost::asio::buffer_copy;
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(N - 1),
- boost::asio::buffer(s, N - 1)));
-}
-
-template
-typename std::enable_if<
- ! is_string_literal::value &&
- ! is_ConstBufferSequence::value &&
- ! is_BufferConvertible::value &&
- ! std::is_convertible::value &&
- ! std::is_convertible::value
->::type
-write_dynabuf(DynamicBuffer& dynabuf, T const& t)
-{
- using boost::asio::buffer;
- using boost::asio::buffer_copy;
- auto const s = boost::lexical_cast(t);
- dynabuf.commit(buffer_copy(
- dynabuf.prepare(s.size()), buffer(s)));
-}
-
-template
-void
-write_dynabuf(DynamicBuffer& dynabuf,
- T0 const& t0, T1 const& t1, TN const&... tn)
-{
- write_dynabuf(dynabuf, t0);
- write_dynabuf(dynabuf, t1, tn...);
-}
-
-} // detail
-} // beast
-
-#endif
diff --git a/include/beast/core/impl/streambuf.ipp b/include/beast/core/impl/streambuf.ipp
index ea39d763..ec51615f 100644
--- a/include/beast/core/impl/streambuf.ipp
+++ b/include/beast/core/impl/streambuf.ipp
@@ -9,7 +9,6 @@
#define BEAST_IMPL_STREAMBUF_IPP
#include
-#include
#include
#include
#include
@@ -871,14 +870,6 @@ read_size_helper(basic_streambuf<
return (std::min)(max_size, low);
}
-template
-basic_streambuf&
-operator<<(basic_streambuf& streambuf, T const& t)
-{
- detail::write_dynabuf(streambuf, t);
- return streambuf;
-}
-
} // beast
#endif
diff --git a/include/beast/core/ostream.hpp b/include/beast/core/ostream.hpp
new file mode 100644
index 00000000..a3186963
--- /dev/null
+++ b/include/beast/core/ostream.hpp
@@ -0,0 +1,66 @@
+//
+// 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_WRITE_OSTREAM_HPP
+#define BEAST_WRITE_OSTREAM_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace beast {
+
+/** Return an output stream that formats values into a @b DynamicBuffer.
+
+ This function wraps the caller provided @b DynamicBuffer into
+ a `std::ostream` derived class, to allow `operator<<` stream style
+ formatting operations.
+
+ @par Example
+ @code
+ ostream(buffer) << "Hello, world!" << std::endl;
+ @endcode
+
+ @note Calling members of the underlying buffer before the output
+ stream is destroyed results in undefined behavior.
+
+ @param buffer An object meeting the requirements of @b DynamicBuffer
+ into which the formatted output will be placed.
+
+ @return An object derived from `std::ostream` which directs output
+ into the specified dynamic buffer. Ownership of the dynamic buffer
+ is not transferred. The caller is responsible for ensuring the
+ dynamic buffer is not destroyed for the lifetime of the output
+ stream.
+*/
+template
+#if BEAST_DOXYGEN
+implementation_defined
+#else
+detail::ostream_helper<
+ DynamicBuffer, char, std::char_traits,
+ std::is_move_constructible<
+ detail::ostream_buffer>>::value>
+#endif
+ostream(DynamicBuffer& buffer)
+{
+ static_assert(is_DynamicBuffer::value,
+ "DynamicBuffer requirements not met");
+ return detail::ostream_helper<
+ DynamicBuffer, char, std::char_traits,
+ std::is_move_constructible<
+ detail::ostream_buffer>>::value>{buffer};
+}
+
+} // beast
+
+#endif
diff --git a/include/beast/core/streambuf.hpp b/include/beast/core/streambuf.hpp
index ed0cae6d..26809043 100644
--- a/include/beast/core/streambuf.hpp
+++ b/include/beast/core/streambuf.hpp
@@ -326,18 +326,6 @@ private:
*/
using streambuf = basic_streambuf>;
-/** Format output to a @ref basic_streambuf.
-
- @param streambuf The @ref basic_streambuf to write to.
-
- @param t The object to write.
-
- @return A reference to the @ref basic_streambuf.
-*/
-template
-basic_streambuf&
-operator<<(basic_streambuf& streambuf, T const& t);
-
} // beast
#include
diff --git a/include/beast/core/write_dynabuf.hpp b/include/beast/core/write_dynabuf.hpp
deleted file mode 100644
index c91b984c..00000000
--- a/include/beast/core/write_dynabuf.hpp
+++ /dev/null
@@ -1,64 +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_WRITE_DYNABUF_HPP
-#define BEAST_WRITE_DYNABUF_HPP
-
-#include
-#include
-#include
-#include
-#include
-
-namespace beast {
-
-/** Write to a @b `DynamicBuffer`.
-
- This function appends the serialized representation of each provided
- argument into the dynamic buffer. It is capable of converting the
- following types of arguments:
-
- @li `boost::asio::const_buffer`
-
- @li `boost::asio::mutable_buffer`
-
- @li A type meeting the requirements of @b `ConvertibleToConstBuffer`
-
- @li A type meeting the requirements of @b `ConstBufferSequence`
-
- @li A type meeting the requirements of @b `MutableBufferSequence`
-
- For all types not listed above, the function will invoke
- `boost::lexical_cast` on the argument in an attempt to convert to
- a string, which is then appended to the dynamic buffer.
-
- When this function serializes numbers, it converts them to
- their text representation as if by a call to `std::to_string`.
-
- @param dynabuf The dynamic buffer to write to.
-
- @param args A list of one or more arguments to write.
-
- @throws unspecified Any exceptions thrown by `boost::lexical_cast`.
-
- @note This function participates in overload resolution only if
- the `dynabuf` parameter meets the requirements of @b `DynamicBuffer`.
-*/
-template
-#if BEAST_DOXYGEN
-void
-#else
-typename std::enable_if::value>::type
-#endif
-write(DynamicBuffer& dynabuf, Args const&... args)
-{
- detail::write_dynabuf(dynabuf, args...);
-}
-
-} // beast
-
-#endif
diff --git a/include/beast/http/impl/write.ipp b/include/beast/http/impl/write.ipp
index bb8f16e0..66db1648 100644
--- a/include/beast/http/impl/write.ipp
+++ b/include/beast/http/impl/write.ipp
@@ -13,11 +13,11 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -31,53 +31,39 @@ namespace http {
namespace detail {
-template
+template
void
-write_start_line(DynamicBuffer& dynabuf,
+write_start_line(std::ostream& os,
header const& msg)
{
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
- write(dynabuf, msg.method());
- write(dynabuf, " ");
- write(dynabuf, msg.target());
+ os << msg.method() << " " << msg.target();
switch(msg.version)
{
- case 10:
- write(dynabuf, " HTTP/1.0\r\n");
- break;
- case 11:
- write(dynabuf, " HTTP/1.1\r\n");
- break;
+ case 10: os << " HTTP/1.0\r\n"; break;
+ case 11: os << " HTTP/1.1\r\n"; break;
}
}
-template
+template
void
-write_start_line(DynamicBuffer& dynabuf,
+write_start_line(std::ostream& os,
header const& msg)
{
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
switch(msg.version)
{
- case 10:
- write(dynabuf, "HTTP/1.0 ");
- break;
- case 11:
- write(dynabuf, "HTTP/1.1 ");
- break;
+ case 10: os << "HTTP/1.0 "; break;
+ case 11: os << "HTTP/1.1 "; break;
}
- write(dynabuf, msg.status);
- write(dynabuf, " ");
- write(dynabuf, msg.reason());
- write(dynabuf, "\r\n");
+ os << msg.status << " " << msg.reason() << "\r\n";
}
-template
+template
void
-write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
+write_fields(std::ostream& os,
+ FieldSequence const& fields)
{
- static_assert(is_DynamicBuffer::value,
- "DynamicBuffer requirements not met");
//static_assert(is_FieldSequence::value,
// "FieldSequence requirements not met");
for(auto const& field : fields)
@@ -86,10 +72,7 @@ write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
BOOST_ASSERT(! name.empty());
if(name[0] == ':')
continue;
- write(dynabuf, field.name());
- write(dynabuf, ": ");
- write(dynabuf, field.value());
- write(dynabuf, "\r\n");
+ os << field.name() << ": " << field.value() << "\r\n";
}
}
@@ -218,9 +201,12 @@ write(SyncWriteStream& stream,
static_assert(is_SyncWriteStream::value,
"SyncWriteStream requirements not met");
streambuf sb;
- detail::write_start_line(sb, msg);
- detail::write_fields(sb, msg.fields);
- beast::write(sb, "\r\n");
+ {
+ auto os = ostream(sb);
+ detail::write_start_line(os, msg);
+ detail::write_fields(os, msg.fields);
+ os << "\r\n";
+ }
boost::asio::write(stream, sb.data(), ec);
}
@@ -238,9 +224,12 @@ async_write(AsyncWriteStream& stream,
beast::async_completion completion{handler};
streambuf sb;
- detail::write_start_line(sb, msg);
- detail::write_fields(sb, msg.fields);
- beast::write(sb, "\r\n");
+ {
+ auto os = ostream(sb);
+ detail::write_start_line(os, msg);
+ detail::write_fields(os, msg.fields);
+ os << "\r\n";
+ }
detail::write_streambuf_op{
completion.handler, stream, std::move(sb)};
@@ -281,9 +270,10 @@ struct write_preparation
if(ec)
return;
- write_start_line(sb, msg);
- write_fields(sb, msg.fields);
- beast::write(sb, "\r\n");
+ auto os = ostream(sb);
+ write_start_line(os, msg);
+ write_fields(os, msg.fields);
+ os << "\r\n";
}
};
diff --git a/test/Jamfile b/test/Jamfile
index d39b7292..38759e84 100644
--- a/test/Jamfile
+++ b/test/Jamfile
@@ -29,6 +29,7 @@ unit-test core-tests :
core/handler_alloc.cpp
core/handler_concepts.cpp
core/handler_ptr.cpp
+ core/ostream.cpp
core/placeholders.cpp
core/prepare_buffer.cpp
core/prepare_buffers.cpp
@@ -37,7 +38,6 @@ unit-test core-tests :
core/stream_concepts.cpp
core/streambuf.cpp
core/to_string.cpp
- core/write_dynabuf.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 1413262f..0c353d99 100644
--- a/test/core/CMakeLists.txt
+++ b/test/core/CMakeLists.txt
@@ -22,6 +22,7 @@ add_executable (core-tests
handler_alloc.cpp
handler_concepts.cpp
handler_ptr.cpp
+ ostream.cpp
placeholders.cpp
prepare_buffer.cpp
prepare_buffers.cpp
@@ -30,7 +31,6 @@ add_executable (core-tests
stream_concepts.cpp
streambuf.cpp
to_string.cpp
- write_dynabuf.cpp
base64.cpp
empty_base_optimization.cpp
get_lowest_layer.cpp
diff --git a/test/core/ostream.cpp b/test/core/ostream.cpp
new file mode 100644
index 00000000..055fbd15
--- /dev/null
+++ b/test/core/ostream.cpp
@@ -0,0 +1,32 @@
+//
+// 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
+#include
+
+#include
+
+namespace beast {
+
+class ostream_test : public beast::unit_test::suite
+{
+public:
+ void run() override
+ {
+ streambuf sb;
+ ostream(sb) << "Hello, world!\n";
+ BEAST_EXPECT(to_string(sb.data()) == "Hello, world!\n");
+ }
+};
+
+BEAST_DEFINE_TESTSUITE(ostream,core,beast);
+
+} // beast
diff --git a/test/core/streambuf.cpp b/test/core/streambuf.cpp
index 2d3440de..02a7b56e 100644
--- a/test/core/streambuf.cpp
+++ b/test/core/streambuf.cpp
@@ -273,13 +273,6 @@ public:
BEAST_EXPECT(test::buffer_count(sb.data()) == 4);
}
- void testOutputStream()
- {
- streambuf sb;
- sb << "x";
- BEAST_EXPECT(to_string(sb.data()) == "x");
- }
-
void testCapacity()
{
using boost::asio::buffer_size;
@@ -353,7 +346,6 @@ public:
testConsume();
testMatrix();
testIterators();
- testOutputStream();
testCapacity();
}
};
diff --git a/test/core/write_dynabuf.cpp b/test/core/write_dynabuf.cpp
deleted file mode 100644
index 36a65a6c..00000000
--- a/test/core/write_dynabuf.cpp
+++ /dev/null
@@ -1,36 +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 write_dynabuf_test : public beast::unit_test::suite
-{
-public:
- void run() override
- {
- streambuf sb;
- std::string s;
- write(sb, boost::asio::const_buffer{"", 0});
- write(sb, boost::asio::mutable_buffer{nullptr, 0});
- write(sb, boost::asio::null_buffers{});
- write(sb, boost::asio::const_buffers_1{"", 0});
- write(sb, boost::asio::mutable_buffers_1{nullptr, 0});
- write(sb, s);
- write(sb, 23);
- pass();
- }
-};
-
-BEAST_DEFINE_TESTSUITE(write_dynabuf,core,beast);
-
-} // beast
diff --git a/test/http/message_fuzz.hpp b/test/http/message_fuzz.hpp
index 991baaab..f199f4d5 100644
--- a/test/http/message_fuzz.hpp
+++ b/test/http/message_fuzz.hpp
@@ -8,7 +8,7 @@
#ifndef BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
#define BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
-#include
+#include
#include
#include
#include
@@ -319,7 +319,7 @@ public:
}
std::string
- uri()
+ target()
{
//switch(rand(4))
switch(1)
@@ -348,7 +348,7 @@ public:
#if 0
std::string
- uri()
+ target()
{
static char constexpr alpha[63] =
"0123456789" "ABCDEFGHIJ" "KLMNOPQRST"
@@ -476,13 +476,13 @@ public:
void
fields(DynamicBuffer& db)
{
+ auto os = ostream(db);
while(rand(6))
- {
- write(db, field());
- write(db, rand(4) ? ": " : ":");
- write(db, value());
- write(db, "\r\n");
- }
+ os <<
+ field() <<
+ (rand(4) ? ": " : ":") <<
+ value() <<
+ "\r\n";
}
template
@@ -491,13 +491,15 @@ public:
{
if(! rand(4))
{
- write(db, "Content-Length: 0\r\n\r\n");
+ ostream(db) <<
+ "Content-Length: 0\r\n\r\n";
return;
}
if(rand(2))
{
auto const len = rand(500);
- write(db, "Content-Length: ", len, "\r\n\r\n");
+ ostream(db) <<
+ "Content-Length: " << len << "\r\n\r\n";
for(auto const& b : db.prepare(len))
{
auto p = boost::asio::buffer_cast(b);
@@ -510,12 +512,14 @@ public:
else
{
auto len = rand(500);
- write(db, "Transfer-Encoding: chunked\r\n\r\n");
+ ostream(db) <<
+ "Transfer-Encoding: chunked\r\n\r\n";
while(len > 0)
{
auto n = (std::min)(1 + rand(300), len);
len -= n;
- write(db, to_hex(n), "\r\n");
+ ostream(db) <<
+ to_hex(n) << "\r\n";
for(auto const& b : db.prepare(n))
{
auto p = boost::asio::buffer_cast(b);
@@ -524,9 +528,9 @@ public:
*p++ = static_cast(32 + rand(26+26+10+6));
}
db.commit(n);
- write(db, "\r\n");
+ ostream(db) << "\r\n";
}
- write(db, "0\r\n\r\n");
+ ostream(db) << "0\r\n\r\n";
}
}
@@ -534,7 +538,8 @@ public:
void
request(DynamicBuffer& db)
{
- write(db, method(), " ", uri(), " HTTP/1.1\r\n");
+ ostream(db) <<
+ method() << " " << target() << " HTTP/1.1\r\n";
fields(db);
body(db);
}
@@ -543,14 +548,15 @@ public:
void
response(DynamicBuffer& db)
{
- write(db, "HTTP/1.");
- write(db, rand(2) ? "0" : "1");
- write(db, " ", 100 + rand(401), " ");
- write(db, token());
- write(db, "\r\n");
+ ostream(db) <<
+ "HTTP/1." <<
+ (rand(2) ? "0" : "1") << " " <<
+ (100 + rand(401)) << " " <<
+ token() <<
+ "\r\n";
fields(db);
body(db);
- write(db, "\r\n");
+ ostream(db) << "\r\n";
}
};