// // Copyright (c) 2017 Mike Gresens (mike dot gresens 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_EXAMPLE_COMMON_MUTABLE_BODY_HPP #define BEAST_EXAMPLE_COMMON_MUTABLE_BODY_HPP #include #include #include #include namespace detail { template using is_mutable_character = std::integral_constant::value && sizeof(T) == 1 >; template struct is_mutable_container : std::false_type { }; template< class T > struct is_mutable_container() = std::declval().size() ), decltype( std::declval() = std::declval().data() ), decltype( std::declval().reserve(0) ), decltype( std::declval().resize(0) ) > > : std::true_type { }; } /** An HTTP message body represented by a mutable character container. Meets the requirements of @b Body. */ template struct mutable_body { static_assert( detail::is_mutable_character::value && detail::is_mutable_container::value, "MutableContainer requirements not met"); /// The type of the body member when used in a message. using value_type = MutableContainer; /// Returns the content length of the body in a message. static std::uint64_t size(value_type const& v) { return v.size(); } #if BEAST_DOXYGEN /// The algorithm to obtain buffers representing the body using reader = implementation_defined; #else class reader { value_type const& body_; public: using const_buffers_type = boost::asio::const_buffers_1; template explicit reader(beast::http::message const& msg, beast::error_code& ec) : body_(msg.body) { ec.assign(0, ec.category()); } boost::optional> get(beast::error_code& ec) { ec.assign(0, ec.category()); return {{const_buffers_type{ body_.data(), body_.size()}, false}}; } }; #endif #if BEAST_DOXYGEN /// The algorithm used store buffers in this body using writer = implementation_defined; #else class writer { value_type& body_; public: template explicit writer(beast::http::message& m, boost::optional const& content_length, beast::error_code& ec) : body_(m.body) { if(content_length) { if(*content_length > (std::numeric_limits< std::size_t>::max)()) { ec = beast::http::error::buffer_overflow; return; } try { body_.reserve(static_cast< std::size_t>(*content_length)); } catch(std::exception const&) { ec = beast::http::error::buffer_overflow; return; } } ec.assign(0, ec.category()); } template std::size_t put(ConstBufferSequence const& buffers, beast::error_code& ec) { using boost::asio::buffer_size; using boost::asio::buffer_copy; auto const n = buffer_size(buffers); auto const len = body_.size(); try { body_.resize(len + n); } catch(std::exception const&) { ec = beast::http::error::buffer_overflow; return 0; } ec.assign(0, ec.category()); return buffer_copy(boost::asio::buffer( &body_[0] + len, n), buffers); } void finish(beast::error_code& ec) { ec.assign(0, ec.category()); } }; #endif }; #endif