diff options
Diffstat (limited to 'boost/beast/http/string_body.hpp')
-rw-r--r-- | boost/beast/http/string_body.hpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/boost/beast/http/string_body.hpp b/boost/beast/http/string_body.hpp new file mode 100644 index 0000000000..18eda414e8 --- /dev/null +++ b/boost/beast/http/string_body.hpp @@ -0,0 +1,199 @@ +// +// 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 +// + +#ifndef BOOST_BEAST_HTTP_STRING_BODY_HPP +#define BOOST_BEAST_HTTP_STRING_BODY_HPP + +#include <boost/beast/core/detail/config.hpp> +#include <boost/beast/http/error.hpp> +#include <boost/beast/http/message.hpp> +#include <boost/beast/core/detail/type_traits.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/optional.hpp> +#include <cstdint> +#include <limits> +#include <memory> +#include <stdexcept> +#include <string> +#include <utility> + +namespace boost { +namespace beast { +namespace http { + +/** A @b Body using `std::basic_string` + + This body uses `std::basic_string` as a memory-based container + for holding message payloads. Messages using this body type + may be serialized and parsed. +*/ +template< + class CharT, + class Traits = std::char_traits<CharT>, + class Allocator = std::allocator<CharT>> +struct basic_string_body +{ +private: + static_assert( + std::is_integral<CharT>::value && + sizeof(CharT) == 1, + "CharT requirements not met"); + +public: + /** The type of container used for the body + + This determines the type of @ref message::body + when this body type is used with a message container. + */ + using value_type = + std::basic_string<CharT, Traits, Allocator>; + + /** Returns the payload size of the body + + When this body is used with @ref message::prepare_payload, + the Content-Length will be set to the payload size, and + any chunked Transfer-Encoding will be removed. + */ + static + std::uint64_t + size(value_type const& body) + { + return body.size(); + } + + /** The algorithm for parsing the body + + Meets the requirements of @b BodyReader. + */ +#if BOOST_BEAST_DOXYGEN + using reader = implementation_defined; +#else + class reader + { + value_type& body_; + + public: + template<bool isRequest, class Fields> + explicit + reader(message<isRequest, + basic_string_body, Fields>& m) + : body_(m.body()) + { + } + + void + init(boost::optional< + std::uint64_t> const& length, error_code& ec) + { + if(length) + { + if(static_cast<std::size_t>(*length) != *length) + { + ec = error::buffer_overflow; + return; + } + try + { + body_.reserve( + static_cast<std::size_t>(*length)); + } + catch(std::exception const&) + { + ec = error::buffer_overflow; + return; + } + } + ec.assign(0, ec.category()); + } + + template<class ConstBufferSequence> + std::size_t + put(ConstBufferSequence const& buffers, + error_code& ec) + { + using boost::asio::buffer_size; + using boost::asio::buffer_copy; + auto const extra = buffer_size(buffers); + auto const size = body_.size(); + try + { + body_.resize(size + extra); + } + catch(std::exception const&) + { + ec = error::buffer_overflow; + return 0; + } + ec.assign(0, ec.category()); + CharT* dest = &body_[size]; + for(auto b : beast::detail::buffers_range(buffers)) + { + Traits::copy(dest, reinterpret_cast< + CharT const*>(b.data()), b.size()); + dest += b.size(); + } + return extra; + } + + void + finish(error_code& ec) + { + ec.assign(0, ec.category()); + } + }; +#endif + + /** The algorithm for serializing the body + + Meets the requirements of @b BodyWriter. + */ +#if BOOST_BEAST_DOXYGEN + using writer = implementation_defined; +#else + class writer + { + value_type const& body_; + + public: + using const_buffers_type = + boost::asio::const_buffer; + + template<bool isRequest, class Fields> + explicit + writer(message<isRequest, + basic_string_body, Fields> const& msg) + : body_(msg.body()) + { + } + + void + init(error_code& ec) + { + ec.assign(0, ec.category()); + } + + boost::optional<std::pair<const_buffers_type, bool>> + get(error_code& ec) + { + ec.assign(0, ec.category()); + return {{const_buffers_type{ + body_.data(), body_.size()}, false}}; + } + }; +#endif +}; + +/// A @b Body using `std::string` +using string_body = basic_string_body<char>; + +} // http +} // beast +} // boost + +#endif |