Remove detail::sync_ostream

fix #418
This commit is contained in:
Vinnie Falco
2017-06-03 17:28:19 -07:00
parent 78d9e3bbce
commit 4b158e45ba
4 changed files with 57 additions and 143 deletions

View File

@@ -1,6 +1,7 @@
Version 48
* Make buffer_prefix_view public
* Remove detail::sync_ostream
API Changes:

View File

@@ -1,95 +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_SYNC_OSTREAM_HPP
#define BEAST_DETAIL_SYNC_OSTREAM_HPP
#include <beast/core/error.hpp>
#include <beast/core/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/throw_exception.hpp>
// BOOST_THROW_EXCEPTION(
#include <ostream>
namespace beast {
namespace detail {
/** A SyncWriteStream which outputs to a `std::ostream`
Objects of this type meet the requirements of @b SyncWriteStream.
*/
class sync_ostream
{
std::ostream& os_;
public:
/** Construct the stream.
@param os The associated `std::ostream`. All buffers
written will be passed to the associated output stream.
*/
sync_ostream(std::ostream& os)
: os_(os)
{
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers);
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers,
error_code& ec);
};
template<class ConstBufferSequence>
std::size_t
sync_ostream::
write_some(ConstBufferSequence const& buffers)
{
static_assert(
is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
error_code ec;
auto const n = write_some(buffers, ec);
if(ec)
BOOST_THROW_EXCEPTION(system_error{ec});
return n;
}
template<class ConstBufferSequence>
std::size_t
sync_ostream::
write_some(ConstBufferSequence const& buffers,
error_code& ec)
{
static_assert(
is_const_buffer_sequence<ConstBufferSequence>::value,
"ConstBufferSequence requirements not met");
std::size_t n = 0;
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
for(auto const& buffer : buffers)
{
os_.write(buffer_cast<char const*>(buffer),
buffer_size(buffer));
if(os_.fail())
{
ec = make_error_code(
errc::no_stream_resources);
break;
}
n += buffer_size(buffer);
}
return n;
}
} // detail
} // beast
#endif

View File

@@ -14,7 +14,6 @@
#include <beast/core/handler_alloc.hpp>
#include <beast/core/handler_ptr.hpp>
#include <beast/core/type_traits.hpp>
#include <beast/core/detail/sync_ostream.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
@@ -783,6 +782,46 @@ async_write(AsyncWriteStream& stream,
//------------------------------------------------------------------------------
namespace detail {
template<class Serializer>
class write_ostream_lambda
{
std::ostream& os_;
Serializer& sr_;
public:
write_ostream_lambda(std::ostream& os,
Serializer& sr)
: os_(os)
, sr_(sr)
{
}
template<class ConstBufferSequence>
void
operator()(error_code&,
ConstBufferSequence const& buffers) const
{
std::size_t bytes_transferred = 0;
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
for(auto it = buffers.begin();
it != buffers.end(); ++it)
{
boost::asio::const_buffer b = *it;
auto const n = buffer_size(b);
os_.write(buffer_cast<char const*>(b), n);
if(os_.fail())
return;
bytes_transferred += n;
}
sr_.consume(bytes_transferred);
}
};
} // detail
template<bool isRequest, class Fields>
std::ostream&
operator<<(std::ostream& os,
@@ -803,11 +842,23 @@ operator<<(std::ostream& os,
"Body requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
beast::detail::sync_ostream oss{os};
serializer<isRequest, Body, Fields> sr{msg};
error_code ec;
write(oss, msg, ec);
if(ec && ec != error::end_of_stream)
BOOST_THROW_EXCEPTION(system_error{ec});
detail::write_ostream_lambda<decltype(sr)> f{os, sr};
do
{
sr.get(ec, f);
if(os.fail())
break;
if(ec == error::end_of_stream)
ec = {};
if(ec)
{
os.setstate(std::ios::failbit);
break;
}
}
while(! sr.is_done());
return os;
}

View File

@@ -658,48 +658,6 @@ public:
"GET / HTTP/1.1\r\nUser-Agent: test\r\n\r\n*");
BEAST_EXPECT(boost::lexical_cast<std::string>(m.base()) ==
"GET / HTTP/1.1\r\nUser-Agent: test\r\n\r\n");
{
std::stringstream ss;
// header
ss << m.base();
// Cause exception in operator<<
ss.setstate(ss.rdstate() |
std::stringstream::failbit);
try
{
// message
ss << m;
fail("", __FILE__, __LINE__);
}
catch(std::exception const&)
{
pass();
}
}
}
void testOstream()
{
message<true, string_body, fields> m;
m.method(verb::get);
m.target("/");
m.version = 11;
m.fields.insert("User-Agent", "test");
m.body = "*";
prepare(m);
std::stringstream ss;
ss.setstate(ss.rdstate() |
std::stringstream::failbit);
try
{
ss << m;
fail();
}
catch(std::exception const&)
{
pass();
}
}
// Ensure completion handlers are not leaked
@@ -960,7 +918,6 @@ public:
testFailures(yield); });
testOutput();
test_std_ostream();
testOstream();
testIoService();
yield_to(
[&](yield_context yield)