From 4952ea2707691a29c53fd647b38ebfe50d403769 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 16 Aug 2013 03:39:22 -0700 Subject: [PATCH] Add class PrefilledReadStream --- .../Builds/VisualStudio2012/beast.vcxproj | 1 + .../VisualStudio2012/beast.vcxproj.filters | 6 + .../beast/modules/beast_asio/beast_asio.h | 2 + .../streams/beast_prefilled_read_stream.h | 204 ++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj index d640a10e5..ebe6f0fe0 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj @@ -84,6 +84,7 @@ + diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters index a782b727c..a29fdd4db 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters @@ -158,6 +158,9 @@ {ccdc0c8e-f77a-486e-ba2f-29c10ec97f18} + + {dfa79046-33ef-4653-a6f9-83954b76a10f} + @@ -845,6 +848,9 @@ beast_asio\protocol + + beast_asio\streams + diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.h b/Subtrees/beast/modules/beast_asio/beast_asio.h index 8b5ab9dc8..4006b8110 100644 --- a/Subtrees/beast/modules/beast_asio/beast_asio.h +++ b/Subtrees/beast/modules/beast_asio/beast_asio.h @@ -65,6 +65,8 @@ namespace beast #include "protocol/beast_HandshakeDetectorType.h" #include "protocol/beast_StreamHandshakeDetectorType.h" +#include "streams/beast_prefilled_read_stream.h" + #include "tests/beast_TestPeerBasics.h" #include "tests/beast_TestPeer.h" #include "tests/beast_TestPeerDetails.h" diff --git a/Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h b/Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h new file mode 100644 index 000000000..a9ca192b3 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h @@ -0,0 +1,204 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_PREFILLEDREADSTREAM_H_INCLUDED +#define BEAST_PREFILLEDREADSTREAM_H_INCLUDED + +/** Front-ends a stream with a provided block of data. + + When read operations are performed on this object, bytes will first be + returned from the buffer provided on construction. When those bytes + are exhausted, read operations will then pass through to the underlying + stream. + + Write operations are all simply passed through. +*/ +template +class PrefilledReadStream : public Uncopyable +{ +protected: + typedef boost::system::error_code error_code; + + void throw_error (error_code const& ec, char const* fileName, int lineNumber) + { + Throw (boost::system::system_error (ec), fileName, lineNumber); + } + +public: + typedef typename boost::remove_reference ::type next_layer_type; + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + + /** Single argument constructor for when we are wrapped in something. + arg is passed through to the next layer's constructor. + */ + template + explicit PrefilledReadStream (Arg& arg) + : m_next_layer (arg) + { + } + + /** Construct with the buffer, and argument passed through. + This creates a copy of the data. The argument is passed through + to the constructor of Stream. + */ + template + PrefilledReadStream (Arg& arg, ConstBufferSequence const& buffers) + : m_next_layer (arg) + { + fill (buffers); + } + + /** Place some input into the prefilled buffer. + Note that this is in no way thread safe. The only reason this function + is here is for the case when you can't pass the buffer through the + constructor because there is another object wrapping this stream. + */ + template + void fill (ConstBufferSequence const& buffers) + { + using namespace boost; + // We don't assume the caller's buffers will + // remain valid for the lifetime of this object. + // + m_buffer.commit (asio::buffer_copy ( + m_buffer.prepare (asio::buffer_size (buffers)), + buffers)); + } + + next_layer_type& next_layer() + { + return m_next_layer; + } + + next_layer_type const& next_layer() const + { + return m_next_layer; + } + + lowest_layer_type& lowest_layer() + { + return m_next_layer.lowest_layer(); + } + + const lowest_layer_type& lowest_layer() const + { + return m_next_layer.lowest_layer(); + } + + boost::asio::io_service& get_io_service() + { + return m_next_layer.get_io_service(); + } + + void close() + { + m_next_layer.close(); + } + + error_code close(error_code& ec) + { + return m_next_layer.close(ec); + } + + template + std::size_t write_some (ConstBufferSequence const& buffers) + { + return m_next_layer.write_some (buffers); + } + + template + std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec) + { + return m_next_layer.write_some (buffers, ec); + } + + template + std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec) + { + ec = error_code (); + if (m_buffer.size () > 0) + { + std::size_t const bytes_transferred = boost::asio::buffer_copy ( + buffers, m_buffer.data ()); + m_buffer.consume (bytes_transferred); + return bytes_transferred; + } + return m_next_layer.read_some (buffers, ec); + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (error_code, std::size_t)) + async_read_some (MutableBufferSequence const& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + using namespace boost; + if (m_buffer.size () > 0) + { + std::size_t const bytes_transferred = asio::buffer_copy ( + buffers, m_buffer.data ()); + m_buffer.consume (bytes_transferred); + +#if BEAST_ASIO_HAS_FUTURE_RETURNS + asio::detail::async_result_init < + ReadHandler, void (error_code, std::size_t)> init ( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + get_io_service ().post (CompletionCall ( + ReadHandler(init.handler), // handler is copied + error_code (), bytes_transferred)); + + return init.result.get(); + +#else + return get_io_service ().post (CompletionCall ( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), + error_code (), bytes_transferred)); + +#endif + } + + return m_next_layer.async_read_some (buffers, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (error_code, std::size_t)) + async_write_some (ConstBufferSequence const& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return m_next_layer.async_write_some (buffers, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + template + std::size_t read_some (MutableBufferSequence const& buffers) + { + error_code ec; + std::size_t const amount = read_some (buffers, ec); + if (ec) + throw_error (ec, __FILE__, __LINE__); + return amount; + } + +private: + Stream m_next_layer; + boost::asio::streambuf m_buffer; +}; + +#endif