diff --git a/CHANGELOG.md b/CHANGELOG.md index 918ff200..234a73c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Version 48 * Make buffer_prefix_view public +* Remove detail::sync_ostream API Changes: diff --git a/include/beast/core/detail/sync_ostream.hpp b/include/beast/core/detail/sync_ostream.hpp deleted file mode 100644 index 44cf74fd..00000000 --- a/include/beast/core/detail/sync_ostream.hpp +++ /dev/null @@ -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 -#include -#include -#include -// BOOST_THROW_EXCEPTION( -#include - -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 - std::size_t - write_some(ConstBufferSequence const& buffers); - - template - std::size_t - write_some(ConstBufferSequence const& buffers, - error_code& ec); -}; - -template -std::size_t -sync_ostream:: -write_some(ConstBufferSequence const& buffers) -{ - static_assert( - is_const_buffer_sequence::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 -std::size_t -sync_ostream:: -write_some(ConstBufferSequence const& buffers, - error_code& ec) -{ - static_assert( - is_const_buffer_sequence::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(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 diff --git a/include/beast/http/impl/write.ipp b/include/beast/http/impl/write.ipp index f96f9d99..1f5f58a5 100644 --- a/include/beast/http/impl/write.ipp +++ b/include/beast/http/impl/write.ipp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -783,6 +782,46 @@ async_write(AsyncWriteStream& stream, //------------------------------------------------------------------------------ +namespace detail { + +template +class write_ostream_lambda +{ + std::ostream& os_; + Serializer& sr_; + +public: + write_ostream_lambda(std::ostream& os, + Serializer& sr) + : os_(os) + , sr_(sr) + { + } + + template + 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(b), n); + if(os_.fail()) + return; + bytes_transferred += n; + } + sr_.consume(bytes_transferred); + } +}; + +} // detail + template std::ostream& operator<<(std::ostream& os, @@ -803,11 +842,23 @@ operator<<(std::ostream& os, "Body requirements not met"); static_assert(is_body_reader::value, "BodyReader requirements not met"); - beast::detail::sync_ostream oss{os}; + serializer 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 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; } diff --git a/test/http/write.cpp b/test/http/write.cpp index d626f927..e79d7907 100644 --- a/test/http/write.cpp +++ b/test/http/write.cpp @@ -658,48 +658,6 @@ public: "GET / HTTP/1.1\r\nUser-Agent: test\r\n\r\n*"); BEAST_EXPECT(boost::lexical_cast(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 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)