diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32d63638..0ed56e67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@ Version 78:
HTTP:
* Tidy up basic_string_body
+* Add vector_body
--------------------------------------------------------------------------------
diff --git a/doc/5_02_message.qbk b/doc/5_02_message.qbk
index f6015056..89ab4789 100644
--- a/doc/5_02_message.qbk
+++ b/doc/5_02_message.qbk
@@ -169,6 +169,13 @@ meet the requirements, or use the ones that come with the library:
is responsible for managing the lifetime of the buffer pointed to
by the string view.
]]
+[[
+ [link beast.ref.beast__http__vector_body `vector_body`]
+][
+ A body whose `value_type` is `std::vector`. Insertion complexity
+ is amortized constant time, while capacity grows geometrically.
+ Messages with this body type may be serialized and parsed.
+]]
]
[heading Usage]
diff --git a/doc/quickref.xml b/doc/quickref.xml
index 13e5b9ff..7d80de55 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -53,13 +53,7 @@
serializer
string_body
string_view_body
-
- rfc7230
-
- ext_list
- opt_token_list
- param_list
- token_list
+ vector_body
@@ -86,6 +80,13 @@
write_header
write_some
+ rfc7230
+
+ ext_list
+ opt_token_list
+ param_list
+ token_list
+
Constants
diff --git a/include/beast/http.hpp b/include/beast/http.hpp
index 3d0ae11e..5ebf1b7a 100644
--- a/include/beast/http.hpp
+++ b/include/beast/http.hpp
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#include
#endif
diff --git a/include/beast/http/vector_body.hpp b/include/beast/http/vector_body.hpp
new file mode 100644
index 00000000..36a19c42
--- /dev/null
+++ b/include/beast/http/vector_body.hpp
@@ -0,0 +1,182 @@
+//
+// Copyright (c) 2013-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)
+//
+
+#ifndef BEAST_HTTP_VECTOR_BODY_HPP
+#define BEAST_HTTP_VECTOR_BODY_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace beast {
+namespace http {
+
+/** A @b Body using `std::vector`
+
+ This body uses `std::vector` as a memory-based container
+ for holding message payloads. Messages using this body type
+ may be serialized and parsed.
+*/
+template>
+struct vector_body
+{
+private:
+ static_assert(sizeof(T) == 1 &&
+ std::is_integral::value,
+ "T 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::vector;
+
+ /** 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 serializing the body
+
+ Meets the requirements of @b BodyReader.
+ */
+#if BEAST_DOXYGEN
+ using reader = implementation_defined;
+#else
+ class reader
+ {
+ value_type const& body_;
+
+ public:
+ using const_buffers_type =
+ boost::asio::const_buffers_1;
+
+ template
+ explicit
+ reader(message const& msg)
+ : body_(msg.body)
+ {
+ }
+
+ void
+ init(error_code& ec)
+ {
+ ec.assign(0, ec.category());
+ }
+
+ boost::optional>
+ get(error_code& ec)
+ {
+ ec.assign(0, ec.category());
+ return {{const_buffers_type{
+ body_.data(), body_.size()}, false}};
+ }
+ };
+#endif
+
+ /** The algorithm for parsing the body
+
+ Meets the requirements of @b BodyReader.
+ */
+#if BEAST_DOXYGEN
+ using writer = implementation_defined;
+#else
+ class writer
+ {
+ value_type& body_;
+
+ public:
+ template
+ explicit
+ writer(message& m)
+ : body_(m.body)
+ {
+ }
+
+ void
+ init(boost::optional<
+ std::uint64_t> const& length, error_code& ec)
+ {
+ if(length)
+ {
+ if(*length > (
+ std::numeric_limits::max)())
+ {
+ ec = error::buffer_overflow;
+ return;
+ }
+ try
+ {
+ body_.reserve(
+ static_cast(*length));
+ }
+ catch(std::exception const&)
+ {
+ ec = error::buffer_overflow;
+ return;
+ }
+ }
+ ec.assign(0, ec.category());
+ }
+
+ template
+ std::size_t
+ put(ConstBufferSequence const& buffers,
+ 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 = error::buffer_overflow;
+ return 0;
+ }
+ ec.assign(0, ec.category());
+ return buffer_copy(boost::asio::buffer(
+ &body_[0] + len, n), buffers);
+ }
+
+ void
+ finish(error_code& ec)
+ {
+ ec.assign(0, ec.category());
+ }
+ };
+#endif
+};
+
+} // http
+} // beast
+
+#endif
diff --git a/test/http/CMakeLists.txt b/test/http/CMakeLists.txt
index 743b3a48..9a5f2284 100644
--- a/test/http/CMakeLists.txt
+++ b/test/http/CMakeLists.txt
@@ -32,6 +32,7 @@ add_executable (http-tests
string_body.cpp
string_view_body.cpp
type_traits.cpp
+ vector_body.cpp
verb.cpp
write.cpp
)
diff --git a/test/http/Jamfile b/test/http/Jamfile
index 0c059509..66a959f2 100644
--- a/test/http/Jamfile
+++ b/test/http/Jamfile
@@ -25,6 +25,7 @@ unit-test http-tests :
string_body.cpp
string_view_body.cpp
type_traits.cpp
+ vector_body.cpp
verb.cpp
write.cpp
;
diff --git a/test/http/vector_body.cpp b/test/http/vector_body.cpp
new file mode 100644
index 00000000..91252137
--- /dev/null
+++ b/test/http/vector_body.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2013-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)
+//
+
+// Test that header file is self-contained.
+#include
+
+namespace beast {
+namespace http {
+
+BOOST_STATIC_ASSERT(is_body>::value);
+BOOST_STATIC_ASSERT(is_body_reader>::value);
+BOOST_STATIC_ASSERT(is_body_writer>::value);
+
+} // http
+} // beast