diff --git a/include/boost/http_proto/detail/impl/workspace.hpp b/include/boost/http_proto/detail/impl/workspace.hpp index 74aa72c7..04d38b1d 100644 --- a/include/boost/http_proto/detail/impl/workspace.hpp +++ b/include/boost/http_proto/detail/impl/workspace.hpp @@ -36,11 +36,12 @@ struct alignas(alignof(::max_align_t)) U u; any_impl() = delete; - any_impl(any_impl&&) = default; + any_impl(any_impl const&) = delete; + any_impl(any_impl&&) = delete; - template - explicit any_impl(U_&& u_) - : u(std::move(u_)) + template + explicit any_impl(Args&&... args) + : u(std::forward(args)...) { } }; @@ -86,10 +87,10 @@ space_needed() return sizeof(any_impl); } -template +template auto workspace:: -push(T&& t) -> +emplace(Args&&... args) -> typename std::decay::type& { static_assert( @@ -102,7 +103,7 @@ push(T&& t) -> undo u(*this); auto p = ::new(bump_down( sizeof(U), alignof(U))) U( - std::forward(t)); + std::forward(args)...); u.commit(); p->next = reinterpret_cast< any*>(head_); @@ -111,6 +112,15 @@ push(T&& t) -> return p->u; } +template +auto +workspace:: +push(T&& t) -> + typename std::decay::type& +{ + return emplace(std::forward(t)); +} + template T* workspace:: diff --git a/include/boost/http_proto/detail/workspace.hpp b/include/boost/http_proto/detail/workspace.hpp index 81b9fba1..33df366f 100644 --- a/include/boost/http_proto/detail/workspace.hpp +++ b/include/boost/http_proto/detail/workspace.hpp @@ -128,6 +128,10 @@ class workspace reserve_front( std::size_t n); + template + typename std::decay::type& + emplace(Args&&... args); + template typename std::decay::type& push(T&& t); diff --git a/include/boost/http_proto/impl/serializer.hpp b/include/boost/http_proto/impl/serializer.hpp index d49d69e3..10068be5 100644 --- a/include/boost/http_proto/impl/serializer.hpp +++ b/include/boost/http_proto/impl/serializer.hpp @@ -12,8 +12,6 @@ #include #include -#include -#include #include namespace boost { @@ -91,21 +89,23 @@ start( template< class Source, + class... Args, class> -auto +Source& serializer:: start( message_view_base const& m, - Source&& src0) -> - typename std::decay< - Source>::type& + Args&&... args) { + static_assert( + std::is_constructible::value || + std::is_constructible::value, + "The Source cannot be constructed with the given arguments"); + start_init(m); - auto& src = ws_.push( - std::forward< - Source>(src0)); - start_source( - m, std::addressof(src)); + auto& src = construct_source( + std::forward(args)...); + start_source(m, std::addressof(src)); return src; } diff --git a/include/boost/http_proto/serializer.hpp b/include/boost/http_proto/serializer.hpp index 5d4b643d..2c19c75a 100644 --- a/include/boost/http_proto/serializer.hpp +++ b/include/boost/http_proto/serializer.hpp @@ -130,18 +130,17 @@ class BOOST_SYMBOL_VISIBLE undefined behavior. */ template< - class Source + class Source, + class... Args #ifndef BOOST_HTTP_PROTO_DOCS ,class = typename std::enable_if< is_source::value>::type #endif > - auto + Source& start( message_view_base const& m, - Source&& body) -> - typename std::decay< - Source>::type&; + Args&&... args); //-------------------------------------------- @@ -192,6 +191,41 @@ class BOOST_SYMBOL_VISIBLE make_array(std::size_t n) -> detail::array_of_const_buffers; + template< + class Source, + class... Args, + typename std::enable_if< + std::is_constructible< + Source, + Args...>::value>::type* = nullptr> + Source& + construct_source(Args&&... args) + { + return ws_.emplace( + std::forward(args)...); + } + + template< + class Source, + class... Args, + typename std::enable_if< + std::is_constructible< + Source, + buffered_base::allocator&, + Args...>::value>::type* = nullptr> + Source& + construct_source(Args&&... args) + { + buffered_base::allocator a( + ws_.data(), + (ws_.size() - ws_.space_needed()) / 2, + false); + auto& src = ws_.emplace( + a, std::forward(args)...); + ws_.reserve_front(a.size_used()); + return src; + } + BOOST_HTTP_PROTO_DECL void start_init(message_view_base const&); BOOST_HTTP_PROTO_DECL void start_empty(message_view_base const&); BOOST_HTTP_PROTO_DECL void start_buffers(message_view_base const&); diff --git a/include/boost/http_proto/source.hpp b/include/boost/http_proto/source.hpp index ff086df4..62d2b5f9 100644 --- a/include/boost/http_proto/source.hpp +++ b/include/boost/http_proto/source.hpp @@ -34,7 +34,6 @@ namespace http_proto { */ struct BOOST_HTTP_PROTO_DECL source - : buffered_base { /** The results of producing data. */ diff --git a/src/serializer.cpp b/src/serializer.cpp index 65b00831..70305744 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -435,11 +435,6 @@ start_source( 2); // tmp //if(! cod_) { - buffered_base::allocator a( - ws_.data(), ws_.size()/2, false); - src->init(a); - ws_.reserve_front(a.size_used()); - tmp0_ = { ws_.data(), ws_.size() }; if(tmp0_.capacity() < 18 + // chunk size diff --git a/test/unit/serializer.cpp b/test/unit/serializer.cpp index 55d58799..8ff5dfc2 100644 --- a/test/unit/serializer.cpp +++ b/test/unit/serializer.cpp @@ -40,7 +40,7 @@ struct serializer_test results on_read( - buffers::mutable_buffer b) + buffers::mutable_buffer b) override { BOOST_TEST(! is_done_); results rv; @@ -162,10 +162,10 @@ struct serializer_test sr.start(res); sr.start(res, buffers::const_buffer{}); sr.start(res, buffers::mutable_buffer{}); - sr.start(res, test_source{"12345"}); + sr.start(res, "12345"); sr.start(res, make_const(buffers::const_buffer{})); sr.start(res, make_const(buffers::mutable_buffer{})); - sr.start(res, make_const(test_source{"12345"})); + sr.start(res, make_const("12345")); serializer(65536); #ifdef BOOST_HTTP_PROTO_HAS_ZLIB @@ -244,7 +244,7 @@ struct serializer_test // we limit the buffer size of the serializer, requiring // it to make multiple calls to source::read serializer sr(1024); - sr.start(res, std::forward< + sr.start(res, std::forward< Source>(src)); std::string s = read(sr); f(s); @@ -377,7 +377,7 @@ struct serializer_test "Expect: 100-continue\r\n" "Content-Length: 5\r\n" "\r\n"); - sr.start(req, test_source{"12345"}); + sr.start(req, "12345"); std::string s; system::result< serializer::const_buffers_type> rv; @@ -457,7 +457,7 @@ struct serializer_test "\r\n"; serializer sr; response res(sv); - sr.start(res, test_source{"12345"}); + sr.start(res, "12345"); auto s = read(sr); BOOST_TEST(s == "HTTP/1.1 200 OK\r\n"