summaryrefslogtreecommitdiff
path: root/boost/beast/core/impl/flat_stream.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/impl/flat_stream.hpp')
-rw-r--r--boost/beast/core/impl/flat_stream.hpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/boost/beast/core/impl/flat_stream.hpp b/boost/beast/core/impl/flat_stream.hpp
new file mode 100644
index 0000000000..2972131198
--- /dev/null
+++ b/boost/beast/core/impl/flat_stream.hpp
@@ -0,0 +1,276 @@
+//
+// Copyright (c) 2016-2019 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)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
+#define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
+
+#include <boost/beast/core/async_base.hpp>
+#include <boost/beast/core/buffers_prefix.hpp>
+#include <boost/beast/core/static_buffer.hpp>
+#include <boost/beast/core/stream_traits.hpp>
+#include <boost/beast/websocket/teardown.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/coroutine.hpp>
+#include <memory>
+
+namespace boost {
+namespace beast {
+
+template<class NextLayer>
+struct flat_stream<NextLayer>::ops
+{
+
+template<class Handler>
+class write_op
+ : public async_base<Handler,
+ beast::executor_type<flat_stream>>
+ , public net::coroutine
+{
+public:
+ template<
+ class ConstBufferSequence,
+ class Handler_>
+ write_op(
+ Handler_&& h,
+ flat_stream<NextLayer>& s,
+ ConstBufferSequence const& b)
+ : async_base<Handler,
+ beast::executor_type<flat_stream>>(
+ std::forward<Handler_>(h),
+ s.get_executor())
+ {
+ auto const result =
+ flatten(b, max_size);
+ if(result.flatten)
+ {
+ s.buffer_.clear();
+ s.buffer_.commit(net::buffer_copy(
+ s.buffer_.prepare(result.size),
+ b, result.size));
+ s.stream_.async_write_some(
+ s.buffer_.data(), std::move(*this));
+ }
+ else
+ {
+ s.buffer_.clear();
+ s.buffer_.shrink_to_fit();
+ s.stream_.async_write_some(
+ beast::buffers_prefix(
+ result.size, b), std::move(*this));
+ }
+ }
+
+ void
+ operator()(
+ boost::system::error_code ec,
+ std::size_t bytes_transferred)
+ {
+ this->complete_now(ec, bytes_transferred);
+ }
+};
+
+struct run_write_op
+{
+ template<class WriteHandler, class Buffers>
+ void
+ operator()(
+ WriteHandler&& h,
+ flat_stream* s,
+ Buffers const& b)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_op<
+ typename std::decay<WriteHandler>::type>(
+ std::forward<WriteHandler>(h), *s, b);
+ }
+};
+
+};
+
+//------------------------------------------------------------------------------
+
+template<class NextLayer>
+template<class... Args>
+flat_stream<NextLayer>::
+flat_stream(Args&&... args)
+ : stream_(std::forward<Args>(args)...)
+{
+}
+
+template<class NextLayer>
+template<class MutableBufferSequence>
+std::size_t
+flat_stream<NextLayer>::
+read_some(MutableBufferSequence const& buffers)
+{
+ static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(net::is_mutable_buffer_sequence<
+ MutableBufferSequence>::value,
+ "MutableBufferSequence type requirements not met");
+ error_code ec;
+ auto n = read_some(buffers, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
+ return n;
+}
+
+template<class NextLayer>
+template<class MutableBufferSequence>
+std::size_t
+flat_stream<NextLayer>::
+read_some(MutableBufferSequence const& buffers, error_code& ec)
+{
+ static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(net::is_mutable_buffer_sequence<
+ MutableBufferSequence>::value,
+ "MutableBufferSequence type requirements not met");
+ return stream_.read_some(buffers, ec);
+}
+
+template<class NextLayer>
+template<
+ class MutableBufferSequence,
+ class ReadHandler>
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+flat_stream<NextLayer>::
+async_read_some(
+ MutableBufferSequence const& buffers,
+ ReadHandler&& handler)
+{
+ static_assert(boost::beast::is_async_read_stream<next_layer_type>::value,
+ "AsyncReadStream type requirements not met");
+ static_assert(net::is_mutable_buffer_sequence<
+ MutableBufferSequence >::value,
+ "MutableBufferSequence type requirements not met");
+ return stream_.async_read_some(
+ buffers, std::forward<ReadHandler>(handler));
+}
+
+template<class NextLayer>
+template<class ConstBufferSequence>
+std::size_t
+flat_stream<NextLayer>::
+write_some(ConstBufferSequence const& buffers)
+{
+ static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
+ "SyncWriteStream type requirements not met");
+ static_assert(net::is_const_buffer_sequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence type requirements not met");
+ error_code ec;
+ auto n = write_some(buffers, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
+ return n;
+}
+
+template<class NextLayer>
+template<class ConstBufferSequence>
+std::size_t
+flat_stream<NextLayer>::
+stack_write_some(
+ std::size_t size,
+ ConstBufferSequence const& buffers,
+ error_code& ec)
+{
+ static_buffer<max_stack> b;
+ b.commit(net::buffer_copy(
+ b.prepare(size), buffers));
+ return stream_.write_some(b.data(), ec);
+}
+
+template<class NextLayer>
+template<class ConstBufferSequence>
+std::size_t
+flat_stream<NextLayer>::
+write_some(ConstBufferSequence const& buffers, error_code& ec)
+{
+ static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
+ "SyncWriteStream type requirements not met");
+ static_assert(net::is_const_buffer_sequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence type requirements not met");
+ auto const result = flatten(buffers, max_size);
+ if(result.flatten)
+ {
+ if(result.size <= max_stack)
+ return stack_write_some(result.size, buffers, ec);
+
+ buffer_.clear();
+ buffer_.commit(net::buffer_copy(
+ buffer_.prepare(result.size),
+ buffers));
+ return stream_.write_some(buffer_.data(), ec);
+ }
+ buffer_.clear();
+ buffer_.shrink_to_fit();
+ return stream_.write_some(
+ boost::beast::buffers_prefix(result.size, buffers), ec);
+}
+
+template<class NextLayer>
+template<
+ class ConstBufferSequence,
+ class WriteHandler>
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
+flat_stream<NextLayer>::
+async_write_some(
+ ConstBufferSequence const& buffers,
+ WriteHandler&& handler)
+{
+ static_assert(boost::beast::is_async_write_stream<next_layer_type>::value,
+ "AsyncWriteStream type requirements not met");
+ static_assert(net::is_const_buffer_sequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence type requirements not met");
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ typename ops::run_write_op{},
+ handler,
+ this,
+ buffers);
+}
+
+template<class NextLayer>
+void
+teardown(
+ boost::beast::role_type role,
+ flat_stream<NextLayer>& s,
+ error_code& ec)
+{
+ using boost::beast::websocket::teardown;
+ teardown(role, s.next_layer(), ec);
+}
+
+template<class NextLayer, class TeardownHandler>
+void
+async_teardown(
+ boost::beast::role_type role,
+ flat_stream<NextLayer>& s,
+ TeardownHandler&& handler)
+{
+ using boost::beast::websocket::async_teardown;
+ async_teardown(role, s.next_layer(), std::move(handler));
+}
+
+} // beast
+} // boost
+
+#endif