From 335f5c2333afedb75c14602f49d4e986c45eda64 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 9 Oct 2018 19:39:42 -0700 Subject: [PATCH] Add detail::dynamic_buffer_prepare: This function acts as a bottleneck for handling exceptions thrown by dynamic buffers. --- include/boost/beast/core/detail/buffer.hpp | 83 +++++++++++++++++++++ test/beast/core/CMakeLists.txt | 1 + test/beast/core/Jamfile | 1 + test/beast/core/buffer.cpp | 87 ++++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 include/boost/beast/core/detail/buffer.hpp create mode 100644 test/beast/core/buffer.cpp diff --git a/include/boost/beast/core/detail/buffer.hpp b/include/boost/beast/core/detail/buffer.hpp new file mode 100644 index 00000000..d359d100 --- /dev/null +++ b/include/boost/beast/core/detail/buffer.hpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2018 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_DETAIL_BUFFER_HPP +#define BOOST_BEAST_CORE_DETAIL_BUFFER_HPP + +#include +#include +#include + +namespace boost { +namespace beast { +namespace detail { + +template< + class DynamicBuffer, + class ErrorValue> +auto +dynamic_buffer_prepare_noexcept( + DynamicBuffer& buffer, + std::size_t size, + error_code& ec, + ErrorValue ev) -> + boost::optional +{ + if(buffer.max_size() - buffer.size() < size) + { + // length error + ec = ev; + return boost::none; + } + boost::optional result; + result.emplace(buffer.prepare(size)); + ec.assign(0, ec.category()); + return result; +} + +template< + class DynamicBuffer, + class ErrorValue> +auto +dynamic_buffer_prepare( + DynamicBuffer& buffer, + std::size_t size, + error_code& ec, + ErrorValue ev) -> + boost::optional +{ +#ifndef BOOST_NO_EXCEPTIONS + try + { + boost::optional result; + result.emplace(buffer.prepare(size)); + ec.assign(0, ec.category()); + return result; + } + catch(std::length_error const&) + { + ec = ev; + } + return boost::none; + +#else + return dynamic_buffer_prepare_noexcept( + buffer, size, ec, ev); +#endif +} + +} // detail +} // beast +} // boost + +#endif diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index ef54cbdb..abb40c53 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable (tests-beast-core buffer_test.hpp file_test.hpp bind_handler.cpp + buffer.cpp buffered_read_stream.cpp buffers_adapter.cpp buffers_cat.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index 5d5e4903..52c3401d 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -9,6 +9,7 @@ local SOURCES = bind_handler.cpp + buffer.cpp buffered_read_stream.cpp buffers_adapter.cpp buffers_cat.cpp diff --git a/test/beast/core/buffer.cpp b/test/beast/core/buffer.cpp new file mode 100644 index 00000000..6618e138 --- /dev/null +++ b/test/beast/core/buffer.cpp @@ -0,0 +1,87 @@ +// +// Copyright (c) 2016-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) +// +// Official repository: https://github.com/boostorg/beast +// + +// Test that header file is self-contained. +//#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace beast { + +// VFALCO No idea why boost::system::errc::message_size fails +// to compile, so we use boost::asio::error::eof instead. +// +class buffer_test : public beast::unit_test::suite +{ +public: + template + void + testPrepare() + { + #ifndef BOOST_NO_EXCEPTIONS + error_code ec; + DynamicBuffer b(32); + detail::dynamic_buffer_prepare(b, 20, ec, + //boost::system::errc::message_size); + boost::asio::error::eof); + BEAST_EXPECTS(! ec, ec.message()); + b.commit(20); + auto const result = + detail::dynamic_buffer_prepare(b, 20, ec, + //boost::system::errc::message_size); + boost::asio::error::eof); + BEAST_EXPECT(result == boost::none); + BEAST_EXPECTS( + //ec == boost::system::errc::message_size, + ec == boost::asio::error::eof, ec.message()); + #else + fail("exceptions disabled", __FILE__, __LINE__); + #endif + } + + template + void + testPrepareNoexcept() + { + error_code ec; + DynamicBuffer b(32); + detail::dynamic_buffer_prepare_noexcept(b, 20, ec, + //boost::system::errc::message_size); + boost::asio::error::eof); + BEAST_EXPECTS(! ec, ec.message()); + b.commit(20); + auto const result = + detail::dynamic_buffer_prepare_noexcept(b, 20, ec, + //boost::system::errc::message_size); + boost::asio::error::eof); + BEAST_EXPECT(result == boost::none); + BEAST_EXPECTS( + //ec == boost::system::errc::message_size, + ec == boost::asio::error::eof, ec.message()); + } + + void + run() override + { + testPrepare(); + testPrepareNoexcept(); + pass(); + } +}; + +BEAST_DEFINE_TESTSUITE(beast,core,buffer); + +} // beast +} // boost