summaryrefslogtreecommitdiff
path: root/boost/beast/http
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/http')
-rw-r--r--boost/beast/http/basic_dynamic_body.hpp34
-rw-r--r--boost/beast/http/basic_file_body.hpp27
-rw-r--r--boost/beast/http/basic_parser.hpp419
-rw-r--r--boost/beast/http/buffer_body.hpp35
-rw-r--r--boost/beast/http/chunk_encode.hpp77
-rw-r--r--boost/beast/http/detail/basic_parsed_list.hpp4
-rw-r--r--boost/beast/http/detail/basic_parser.hpp813
-rw-r--r--boost/beast/http/detail/basic_parser.ipp848
-rw-r--r--boost/beast/http/detail/chunk_encode.hpp61
-rw-r--r--boost/beast/http/detail/rfc7230.hpp421
-rw-r--r--boost/beast/http/detail/rfc7230.ipp388
-rw-r--r--boost/beast/http/detail/type_traits.hpp10
-rw-r--r--boost/beast/http/dynamic_body.hpp4
-rw-r--r--boost/beast/http/empty_body.hpp22
-rw-r--r--boost/beast/http/error.hpp20
-rw-r--r--boost/beast/http/field.hpp6
-rw-r--r--boost/beast/http/fields.hpp17
-rw-r--r--boost/beast/http/file_body.hpp6
-rw-r--r--boost/beast/http/impl/basic_parser.hpp78
-rw-r--r--boost/beast/http/impl/basic_parser.ipp234
-rw-r--r--boost/beast/http/impl/chunk_encode.hpp (renamed from boost/beast/http/impl/chunk_encode.ipp)27
-rw-r--r--boost/beast/http/impl/error.hpp37
-rw-r--r--boost/beast/http/impl/error.ipp14
-rw-r--r--boost/beast/http/impl/field.ipp174
-rw-r--r--boost/beast/http/impl/fields.hpp (renamed from boost/beast/http/impl/fields.ipp)46
-rw-r--r--boost/beast/http/impl/file_body_win32.hpp (renamed from boost/beast/http/impl/file_body_win32.ipp)324
-rw-r--r--boost/beast/http/impl/message.hpp (renamed from boost/beast/http/impl/message.ipp)20
-rw-r--r--boost/beast/http/impl/parser.hpp (renamed from boost/beast/http/impl/parser.ipp)8
-rw-r--r--boost/beast/http/impl/read.hpp559
-rw-r--r--boost/beast/http/impl/read.ipp857
-rw-r--r--boost/beast/http/impl/rfc7230.hpp423
-rw-r--r--boost/beast/http/impl/rfc7230.ipp408
-rw-r--r--boost/beast/http/impl/serializer.hpp (renamed from boost/beast/http/impl/serializer.ipp)67
-rw-r--r--boost/beast/http/impl/status.ipp80
-rw-r--r--boost/beast/http/impl/verb.ipp27
-rw-r--r--boost/beast/http/impl/write.hpp (renamed from boost/beast/http/impl/write.ipp)721
-rw-r--r--boost/beast/http/message.hpp79
-rw-r--r--boost/beast/http/parser.hpp150
-rw-r--r--boost/beast/http/read.hpp850
-rw-r--r--boost/beast/http/rfc7230.hpp10
-rw-r--r--boost/beast/http/serializer.hpp39
-rw-r--r--boost/beast/http/span_body.hpp31
-rw-r--r--boost/beast/http/status.hpp18
-rw-r--r--boost/beast/http/string_body.hpp56
-rw-r--r--boost/beast/http/type_traits.hpp67
-rw-r--r--boost/beast/http/vector_body.hpp53
-rw-r--r--boost/beast/http/verb.hpp6
-rw-r--r--boost/beast/http/write.hpp170
48 files changed, 4408 insertions, 4437 deletions
diff --git a/boost/beast/http/basic_dynamic_body.hpp b/boost/beast/http/basic_dynamic_body.hpp
index ba7208b7d7..3fea37379b 100644
--- a/boost/beast/http/basic_dynamic_body.hpp
+++ b/boost/beast/http/basic_dynamic_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -11,7 +11,7 @@
#define BOOST_BEAST_HTTP_BASIC_DYNAMIC_BODY_HPP
#include <boost/beast/core/detail/config.hpp>
-#include <boost/beast/core/type_traits.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/buffer.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
@@ -24,9 +24,9 @@ namespace boost {
namespace beast {
namespace http {
-/** A @b Body using a @b DynamicBuffer
+/** A <em>Body</em> using a <em>DynamicBuffer</em>
- This body uses a @b DynamicBuffer as a memory-based container
+ This body uses a <em>DynamicBuffer</em> as a memory-based container
for holding message payloads. Messages using this body type
may be serialized and parsed.
*/
@@ -34,8 +34,8 @@ template<class DynamicBuffer>
struct basic_dynamic_body
{
static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
/** The type of container used for the body
@@ -59,10 +59,10 @@ struct basic_dynamic_body
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
class reader
{
@@ -80,7 +80,7 @@ struct basic_dynamic_body
init(boost::optional<
std::uint64_t> const&, error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -88,9 +88,7 @@ struct basic_dynamic_body
put(ConstBufferSequence const& buffers,
error_code& ec)
{
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- auto const n = buffer_size(buffers);
+ auto const n = buffer_bytes(buffers);
if(body_.size() > body_.max_size() - n)
{
ec = error::buffer_overflow;
@@ -104,7 +102,7 @@ struct basic_dynamic_body
if(ec)
return 0;
auto const bytes_transferred =
- buffer_copy(*mb, buffers);
+ net::buffer_copy(*mb, buffers);
body_.commit(bytes_transferred);
return bytes_transferred;
}
@@ -112,17 +110,17 @@ struct basic_dynamic_body
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer
{
@@ -142,13 +140,13 @@ struct basic_dynamic_body
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
return {{body_.data(), false}};
}
};
diff --git a/boost/beast/http/basic_file_body.hpp b/boost/beast/http/basic_file_body.hpp
index 7dd104d445..152df8898b 100644
--- a/boost/beast/http/basic_file_body.hpp
+++ b/boost/beast/http/basic_file_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -13,7 +13,6 @@
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/file_base.hpp>
-#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/assert.hpp>
#include <boost/optional.hpp>
@@ -39,14 +38,14 @@ namespace http {
content from a directory as part of a web service.
@tparam File The implementation to use for accessing files.
- This type must meet the requirements of @b File.
+ This type must meet the requirements of <em>File</em>.
*/
template<class File>
struct basic_file_body
{
// Make sure the type meets the requirements
static_assert(is_file<File>::value,
- "File requirements not met");
+ "File type requirements not met");
/// The type of File this body uses
using file_type = File;
@@ -235,7 +234,7 @@ public:
// The type of buffer sequence returned by `get`.
//
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
// Constructor.
//
@@ -319,7 +318,7 @@ init(error_code& ec)
// to indicate no error.
//
// We don't do anything fancy so set "no error"
- ec.assign(0, ec.category());
+ ec = {};
}
// This function is called repeatedly by the serializer to
@@ -349,7 +348,7 @@ get(error_code& ec) ->
// into the library to get the generic category because
// that saves us a possibly expensive atomic operation.
//
- ec.assign(0, ec.category());
+ ec = {};
return boost::none;
}
@@ -373,7 +372,7 @@ get(error_code& ec) ->
// we set this bool to `false` so we will not be called
// again.
//
- ec.assign(0, ec.category());
+ ec = {};
return {{
const_buffers_type{buf_, nread}, // buffer to return.
remain_ > 0 // `true` if there are more buffers.
@@ -474,7 +473,7 @@ init(
// to indicate no error.
//
// We don't do anything fancy so set "no error"
- ec.assign(0, ec.category());
+ ec = {};
}
// This will get called one or more times with body buffers
@@ -492,11 +491,11 @@ put(ConstBufferSequence const& buffers, error_code& ec)
// Loop over all the buffers in the sequence,
// and write each one to the file.
- for(auto it = boost::asio::buffer_sequence_begin(buffers);
- it != boost::asio::buffer_sequence_end(buffers); ++it)
+ for(auto it = net::buffer_sequence_begin(buffers);
+ it != net::buffer_sequence_end(buffers); ++it)
{
// Write this buffer to the file
- boost::asio::const_buffer buffer = *it;
+ net::const_buffer buffer = *it;
nwritten += body_.file_.write(
buffer.data(), buffer.size(), ec);
if(ec)
@@ -505,7 +504,7 @@ put(ConstBufferSequence const& buffers, error_code& ec)
// Indicate success
// This is required by the error_code specification
- ec.assign(0, ec.category());
+ ec = {};
return nwritten;
}
@@ -519,7 +518,7 @@ finish(error_code& ec)
{
// This has to be cleared before returning, to
// indicate no error. The specification requires it.
- ec.assign(0, ec.category());
+ ec = {};
}
//]
diff --git a/boost/beast/http/basic_parser.hpp b/boost/beast/http/basic_parser.hpp
index dfa1965ceb..650e810ab6 100644
--- a/boost/beast/http/basic_parser.hpp
+++ b/boost/beast/http/basic_parser.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -38,142 +38,48 @@ namespace http {
fields.
The parser is optimized for the case where the input buffer
sequence consists of a single contiguous buffer. The
- @ref flat_buffer class is provided, which guarantees
+ @ref beast::basic_flat_buffer class is provided, which guarantees
that the input sequence of the stream buffer will be represented
by exactly one contiguous buffer. To ensure the optimum performance
- of the parser, use @ref flat_buffer with HTTP algorithms
+ of the parser, use @ref beast::basic_flat_buffer with HTTP algorithms
such as @ref read, @ref read_some, @ref async_read, and @ref async_read_some.
Alternatively, the caller may use custom techniques to ensure that
the structured portion of the HTTP message (header or chunk header)
is contained in a linear buffer.
- The interface uses CRTP (Curiously Recurring Template Pattern).
- To use this class directly, derive from @ref basic_parser. When
+ The interface to the parser uses virtual member functions.
+ To use this class, derive your type from @ref basic_parser. When
bytes are presented, the implementation will make a series of zero
- or more calls to derived class members functions (termed "callbacks"
- in this context) matching a specific signature.
-
- Every callback must be provided by the derived class, or else
- a compilation error will be generated. This exemplar shows
- the signature and description of the callbacks required in
- the derived class.
- For each callback, the function will ensure that `!ec` is `true`
- if there was no error or set to the appropriate error code if
- there was one. If an error is set, the value is propagated to
- the caller of the parser.
-
- @par Derived Class Requirements
- @code
- template<bool isRequest>
- class derived
- : public basic_parser<isRequest, derived<isRequest>>
- {
- private:
- // The friend declaration is needed,
- // otherwise the callbacks must be made public.
- friend class basic_parser<isRequest, derived>;
-
- /// Called after receiving the request-line (isRequest == true).
- void
- on_request_impl(
- verb method, // The method verb, verb::unknown if no match
- string_view method_str, // The method as a string
- string_view target, // The request-target
- int version, // The HTTP-version
- error_code& ec); // The error returned to the caller, if any
-
- /// Called after receiving the start-line (isRequest == false).
- void
- on_response_impl(
- int code, // The status-code
- string_view reason, // The obsolete reason-phrase
- int version, // The HTTP-version
- error_code& ec); // The error returned to the caller, if any
-
- /// Called after receiving a header field.
- void
- on_field_impl(
- field f, // The known-field enumeration constant
- string_view name, // The field name string.
- string_view value, // The field value
- error_code& ec); // The error returned to the caller, if any
-
- /// Called after the complete header is received.
- void
- on_header_impl(
- error_code& ec); // The error returned to the caller, if any
-
- /// Called just before processing the body, if a body exists.
- void
- on_body_init_impl(
- boost::optional<
- std::uint64_t> const&
- content_length, // Content length if known, else `boost::none`
- error_code& ec); // The error returned to the caller, if any
-
- /// Called for each piece of the body, if a body exists.
- //!
- //! This is used when there is no chunked transfer coding.
- //!
- //! The function returns the number of bytes consumed from the
- //! input buffer. Any input octets not consumed will be will be
- //! presented on subsequent calls.
- //!
- std::size_t
- on_body_impl(
- string_view s, // A portion of the body
- error_code& ec); // The error returned to the caller, if any
-
- /// Called for each chunk header.
- void
- on_chunk_header_impl(
- std::uint64_t size, // The size of the upcoming chunk,
- // or zero for the last chunk
- string_view extension, // The chunk extensions (may be empty)
- error_code& ec); // The error returned to the caller, if any
-
- /// Called to deliver the chunk body.
- //!
- //! This is used when there is a chunked transfer coding. The
- //! implementation will automatically remove the encoding before
- //! calling this function.
- //!
- //! The function returns the number of bytes consumed from the
- //! input buffer. Any input octets not consumed will be will be
- //! presented on subsequent calls.
- //!
- std::size_t
- on_chunk_body_impl(
- std::uint64_t remain, // The number of bytes remaining in the chunk,
- // including what is being passed here.
- // or zero for the last chunk
- string_view body, // The next piece of the chunk body
- error_code& ec); // The error returned to the caller, if any
-
- /// Called when the complete message is parsed.
- void
- on_finish_impl(error_code& ec);
-
- public:
- derived() = default;
- };
- @endcode
+ or more calls to virtual functions, which the derived class must
+ implement.
+
+ Every virtual function must be provided by the derived class,
+ or else a compilation error will be generated. The implementation
+ will make sure that `ec` is clear before each virtual function
+ is invoked. If a virtual function sets an error, it is propagated
+ out of the parser to the caller.
@tparam isRequest A `bool` indicating whether the parser will be
presented with request or response message.
- @tparam Derived The derived class type. This is part of the
- Curiously Recurring Template Pattern interface.
-
@note If the parser encounters a field value with obs-fold
longer than 4 kilobytes in length, an error is generated.
*/
-template<bool isRequest, class Derived>
+template<bool isRequest>
class basic_parser
: private detail::basic_parser_base
{
- template<bool OtherIsRequest, class OtherDerived>
- friend class basic_parser;
+ std::uint64_t body_limit_ =
+ default_body_limit(is_request{}); // max payload body
+ std::uint64_t len_ = 0; // size of chunk or body
+ std::uint64_t len0_ = 0; // content length if known
+ std::unique_ptr<char[]> buf_; // temp storage
+ std::size_t buf_len_ = 0; // size of buf_
+ std::size_t skip_ = 0; // resume search here
+ std::uint32_t header_limit_ = 8192; // max header size
+ unsigned short status_ = 0; // response status
+ state state_ = state::nothing_yet; // initial state
+ unsigned f_ = 0; // flags
// limit on the size of the stack flat buffer
static std::size_t constexpr max_stack_buffer = 8192;
@@ -219,27 +125,13 @@ class basic_parser
return 8 * 1024 * 1024; // 8MB
}
- std::uint64_t body_limit_ =
- default_body_limit(is_request{}); // max payload body
- std::uint64_t len_ = 0; // size of chunk or body
- std::unique_ptr<char[]> buf_; // temp storage
- std::size_t buf_len_ = 0; // size of buf_
- std::size_t skip_ = 0; // resume search here
- std::uint32_t header_limit_ = 8192; // max header size
- unsigned short status_ = 0; // response status
- state state_ = state::nothing_yet; // initial state
- unsigned f_ = 0; // flags
+ template<bool OtherIsRequest>
+ friend class basic_parser;
protected:
/// Default constructor
basic_parser() = default;
- /// Move constructor
- basic_parser(basic_parser &&) = default;
-
- /// Move assignment
- basic_parser& operator=(basic_parser &&) = default;
-
/** Move constructor
@note
@@ -247,8 +139,10 @@ protected:
After the move, the only valid operation on the
moved-from object is destruction.
*/
- template<class OtherDerived>
- basic_parser(basic_parser<isRequest, OtherDerived>&&);
+ basic_parser(basic_parser &&) = default;
+
+ /// Move assignment
+ basic_parser& operator=(basic_parser &&) = default;
public:
/// `true` if this parser parses requests, `false` for responses.
@@ -256,7 +150,7 @@ public:
std::integral_constant<bool, isRequest>;
/// Destructor
- ~basic_parser() = default;
+ virtual ~basic_parser() = default;
/// Copy constructor
basic_parser(basic_parser const&) = delete;
@@ -264,30 +158,6 @@ public:
/// Copy assignment
basic_parser& operator=(basic_parser const&) = delete;
- /** Returns a reference to this object as a `basic_parser`.
-
- This is used to pass a derived class where a base class is
- expected, to choose a correct function overload when the
- resolution would be ambiguous.
- */
- basic_parser&
- base()
- {
- return *this;
- }
-
- /** Returns a constant reference to this object as a `basic_parser`.
-
- This is used to pass a derived class where a base class is
- expected, to choose a correct function overload when the
- resolution would be ambiguous.
- */
- basic_parser const&
- base() const
- {
- return *this;
- }
-
/// Returns `true` if the parser has received at least one byte of input.
bool
got_some() const
@@ -362,6 +232,18 @@ public:
boost::optional<std::uint64_t>
content_length() const;
+ /** Returns the remaining content length if known
+
+ If the message header specifies a Content-Length,
+ the return value will be the number of bytes remaining
+ in the payload body have not yet been parsed.
+
+ @note The return value is undefined unless
+ @ref is_header_done would return `true`.
+ */
+ boost::optional<std::uint64_t>
+ content_length_remaining() const;
+
/** Returns `true` if the message semantics require an end of file.
Depending on the contents of the header, the parser may
@@ -508,10 +390,10 @@ public:
the parser may not be restarted.
@param buffers An object meeting the requirements of
- @b ConstBufferSequence that represents the next chunk of
+ <em>ConstBufferSequence</em> that represents the next chunk of
message data. If the length of this buffer sequence is
one, the implementation will not allocate additional memory.
- The class @ref beast::flat_buffer is provided as one way to
+ The class @ref beast::basic_flat_buffer is provided as one way to
meet this requirement
@param ec Set to the error, if any occurred.
@@ -526,7 +408,7 @@ public:
#if ! BOOST_BEAST_DOXYGEN
std::size_t
- put(boost::asio::const_buffer const& buffer,
+ put(net::const_buffer buffer,
error_code& ec);
#endif
@@ -540,7 +422,7 @@ public:
This is typically called when a read from the
underlying stream object sets the error code to
- `boost::asio::error::eof`.
+ `net::error::eof`.
@note Only valid after parsing a complete header.
@@ -549,19 +431,203 @@ public:
void
put_eof(error_code& ec);
-private:
- inline
- Derived&
- impl()
- {
- return *static_cast<Derived*>(this);
- }
+protected:
+ /** Called after receiving the request-line.
+
+ This virtual function is invoked after receiving a request-line
+ when parsing HTTP requests.
+ It can only be called when `isRequest == true`.
+
+ @param method The verb enumeration. If the method string is not
+ one of the predefined strings, this value will be @ref verb::unknown.
+
+ @param method_str The unmodified string representing the verb.
+
+ @param target The request-target.
+
+ @param version The HTTP-version. This will be 10 for HTTP/1.0,
+ and 11 for HTTP/1.1.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_request_impl(
+ verb method,
+ string_view method_str,
+ string_view target,
+ int version,
+ error_code& ec) = 0;
+
+ /** Called after receiving the status-line.
+
+ This virtual function is invoked after receiving a status-line
+ when parsing HTTP responses.
+ It can only be called when `isRequest == false`.
+
+ @param code The numeric status code.
+
+ @param reason The reason-phrase. Note that this value is
+ now obsolete, and only provided for historical or diagnostic
+ purposes.
+
+ @param version The HTTP-version. This will be 10 for HTTP/1.0,
+ and 11 for HTTP/1.1.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_response_impl(
+ int code,
+ string_view reason,
+ int version,
+ error_code& ec) = 0;
+
+ /** Called once for each complete field in the HTTP header.
+
+ This virtual function is invoked for each field that is received
+ while parsing an HTTP message.
+
+ @param name The known field enum value. If the name of the field
+ is not recognized, this value will be @ref field::unknown.
+
+ @param name_string The exact name of the field as received from
+ the input, represented as a string.
+
+ @param value A string holding the value of the field.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_field_impl(
+ field name,
+ string_view name_string,
+ string_view value,
+ error_code& ec) = 0;
+
+ /** Called once after the complete HTTP header is received.
+
+ This virtual function is invoked once, after the complete HTTP
+ header is received while parsing a message.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_header_impl(error_code& ec) = 0;
+
+ /** Called once before the body is processed.
+
+ This virtual function is invoked once, before the content body is
+ processed (but after the complete header is received).
+
+ @param content_length A value representing the content length in
+ bytes if the length is known (this can include a zero length).
+ Otherwise, the value will be `boost::none`.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_body_init_impl(
+ boost::optional<std::uint64_t> const& content_length,
+ error_code& ec) = 0;
+
+ /** Called each time additional data is received representing the content body.
+
+ This virtual function is invoked for each piece of the body which is
+ received while parsing of a message. This function is only used when
+ no chunked transfer encoding is present.
+ @param body A string holding the additional body contents. This may
+ contain nulls or unprintable characters.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+
+ @see on_chunk_body_impl
+ */
+ virtual
+ std::size_t
+ on_body_impl(
+ string_view body,
+ error_code& ec) = 0;
+
+ /** Called each time a new chunk header of a chunk encoded body is received.
+
+ This function is invoked each time a new chunk header is received.
+ The function is only used when the chunked transfer encoding is present.
+
+ @param size The size of this chunk, in bytes.
+
+ @param extensions A string containing the entire chunk extensions.
+ This may be empty, indicating no extensions are present.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_chunk_header_impl(
+ std::uint64_t size,
+ string_view extensions,
+ error_code& ec) = 0;
+
+ /** Called each time additional data is received representing part of a body chunk.
+
+ This virtual function is invoked for each piece of the body which is
+ received while parsing of a message. This function is only used when
+ no chunked transfer encoding is present.
+
+ @param remain The number of bytes remaining in this chunk. This includes
+ the contents of passed `body`. If this value is zero, then this represents
+ the final chunk.
+
+ @param body A string holding the additional body contents. This may
+ contain nulls or unprintable characters.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+
+ @return This function should return the number of bytes actually consumed
+ from the `body` value. Any bytes that are not consumed on this call
+ will be presented in a subsequent call.
+
+ @see on_body_impl
+ */
+ virtual
+ std::size_t
+ on_chunk_body_impl(
+ std::uint64_t remain,
+ string_view body,
+ error_code& ec) = 0;
+
+ /** Called once when the complete message is received.
+
+ This virtual function is invoked once, after successfully parsing
+ a complete HTTP message.
+
+ @param ec An output parameter which the function may set to indicate
+ an error. The error will be clear before this function is invoked.
+ */
+ virtual
+ void
+ on_finish_impl(error_code& ec) = 0;
+
+private:
template<class ConstBufferSequence>
std::size_t
- put_from_stack(std::size_t size,
+ put_from_stack(
+ std::size_t size,
ConstBufferSequence const& buffers,
- error_code& ec);
+ error_code& ec);
void
maybe_need_more(
@@ -616,6 +682,9 @@ private:
} // beast
} // boost
+#include <boost/beast/http/impl/basic_parser.hpp>
+#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/http/impl/basic_parser.ipp>
+#endif
#endif
diff --git a/boost/beast/http/buffer_body.hpp b/boost/beast/http/buffer_body.hpp
index bd420d9f54..8988c2323f 100644
--- a/boost/beast/http/buffer_body.hpp
+++ b/boost/beast/http/buffer_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -11,6 +11,7 @@
#define BOOST_BEAST_HTTP_BUFFER_BODY_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/type_traits.hpp>
@@ -22,7 +23,7 @@ namespace boost {
namespace beast {
namespace http {
-/** A @b Body using a caller provided buffer
+/** A <em>Body</em> using a caller provided buffer
Messages using this body type may be serialized and parsed.
To use this class, the caller must initialize the members
@@ -93,10 +94,10 @@ struct buffer_body
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
class reader
{
@@ -113,7 +114,7 @@ struct buffer_body
void
init(boost::optional<std::uint64_t> const&, error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -121,21 +122,19 @@ struct buffer_body
put(ConstBufferSequence const& buffers,
error_code& ec)
{
- using boost::asio::buffer_size;
- using boost::asio::buffer_copy;
if(! body_.data)
{
ec = error::need_buffer;
return 0;
}
auto const bytes_transferred =
- buffer_copy(boost::asio::buffer(
+ net::buffer_copy(net::buffer(
body_.data, body_.size), buffers);
body_.data = static_cast<char*>(
body_.data) + bytes_transferred;
body_.size -= bytes_transferred;
- if(bytes_transferred == buffer_size(buffers))
- ec.assign(0, ec.category());
+ if(bytes_transferred == buffer_bytes(buffers))
+ ec = {};
else
ec = error::need_buffer;
return bytes_transferred;
@@ -144,17 +143,17 @@ struct buffer_body
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer
{
@@ -163,7 +162,7 @@ struct buffer_body
public:
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
explicit
@@ -175,7 +174,7 @@ struct buffer_body
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<
@@ -191,13 +190,13 @@ struct buffer_body
}
else
{
- ec.assign(0, ec.category());
+ ec = {};
}
return boost::none;
}
if(body_.data)
{
- ec.assign(0, ec.category());
+ ec = {};
toggle_ = true;
return {{const_buffers_type{
body_.data, body_.size}, body_.more}};
@@ -205,7 +204,7 @@ struct buffer_body
if(body_.more)
ec = error::need_buffer;
else
- ec.assign(0, ec.category());
+ ec = {};
return boost::none;
}
};
diff --git a/boost/beast/http/chunk_encode.hpp b/boost/beast/http/chunk_encode.hpp
index 4994765fc8..8b8ff651c7 100644
--- a/boost/beast/http/chunk_encode.hpp
+++ b/boost/beast/http/chunk_encode.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -25,14 +25,14 @@ namespace http {
/** A chunked encoding crlf
- This implements a @b ConstBufferSequence holding the CRLF
+ This implements a <em>ConstBufferSequence</em> holding the CRLF
(`"\r\n"`) used as a delimiter in a @em chunk.
To use this class, pass an instance of it to a
stream algorithm as the buffer sequence:
@code
// writes "\r\n"
- boost::asio::write(stream, chunk_crlf{});
+ net::write(stream, chunk_crlf{});
@endcode
@see https://tools.ietf.org/html/rfc7230#section-4.1
@@ -44,27 +44,28 @@ struct chunk_crlf
//-----
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using value_type = implementation_defined;
+ using value_type = __implementation_defined__;
#else
- using value_type = detail::chunk_crlf_iter::value_type;
+ using value_type = net::const_buffer;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
using const_iterator = value_type const*;
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
chunk_crlf(chunk_crlf const&) = default;
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
begin() const
{
- return &detail::chunk_crlf_iter::value;
+ static net::const_buffer const cb{"\r\n", 2};
+ return &cb;
}
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
end() const
{
@@ -76,7 +77,7 @@ struct chunk_crlf
/** A @em chunk header
- This implements a @b ConstBufferSequence representing the
+ This implements a <em>ConstBufferSequence</em> representing the
header of a @em chunk. The serialized format is as follows:
@code
chunk-header = 1*HEXDIG chunk-ext CRLF
@@ -97,7 +98,7 @@ struct chunk_crlf
stream algorithm as the buffer sequence:
@code
// writes "400;x\r\n"
- boost::asio::write(stream, chunk_header{1024, "x"});
+ net::write(stream, chunk_header{1024, "x"});
@endcode
@see https://tools.ietf.org/html/rfc7230#section-4.1
@@ -106,7 +107,7 @@ class chunk_header
{
using view_type = buffers_cat_view<
detail::chunk_size, // chunk-size
- boost::asio::const_buffer, // chunk-extensions
+ net::const_buffer, // chunk-extensions
chunk_crlf>; // CRLF
std::shared_ptr<
@@ -227,31 +228,31 @@ public:
//-----
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using value_type = implementation_defined;
+ using value_type = __implementation_defined__;
#else
using value_type = typename view_type::value_type;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
using const_iterator = typename view_type::const_iterator;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
chunk_header(chunk_header const&) = default;
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
begin() const
{
return view_.begin();
}
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
end() const
{
@@ -263,7 +264,7 @@ public:
/** A @em chunk
- This implements a @b ConstBufferSequence representing
+ This implements a <em>ConstBufferSequence</em> representing
a @em chunk. The serialized format is as follows:
@code
chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
@@ -285,7 +286,7 @@ class chunk_body
{
using view_type = buffers_cat_view<
detail::chunk_size, // chunk-size
- boost::asio::const_buffer, // chunk-extensions
+ net::const_buffer, // chunk-extensions
chunk_crlf, // CRLF
ConstBufferSequence, // chunk-body
chunk_crlf>; // CRLF
@@ -421,28 +422,28 @@ public:
//-----
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using value_type = implementation_defined;
+ using value_type = __implementation_defined__;
#else
using value_type = typename view_type::value_type;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
using const_iterator = typename view_type::const_iterator;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
begin() const
{
return view_.begin();
}
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
end() const
{
@@ -459,7 +460,7 @@ class chunk_last
{
static_assert(
is_fields<Trailer>::value ||
- boost::asio::is_const_buffer_sequence<Trailer>::value,
+ net::is_const_buffer_sequence<Trailer>::value,
"Trailer requirements not met");
using buffers_type = typename
@@ -523,33 +524,33 @@ public:
//-----
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
chunk_last(chunk_last const&) = default;
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using value_type = implementation_defined;
+ using value_type = __implementation_defined__;
#else
using value_type =
typename view_type::value_type;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
using const_iterator =
typename view_type::const_iterator;
#endif
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
begin() const
{
return view_.begin();
}
- /// Required for @b ConstBufferSequence
+ /// Required for <em>ConstBufferSequence</em>
const_iterator
end() const
{
@@ -731,6 +732,6 @@ make_chunk_last(
} // beast
} // boost
-#include <boost/beast/http/impl/chunk_encode.ipp>
+#include <boost/beast/http/impl/chunk_encode.hpp>
#endif
diff --git a/boost/beast/http/detail/basic_parsed_list.hpp b/boost/beast/http/detail/basic_parsed_list.hpp
index 5577fba752..53ce60976d 100644
--- a/boost/beast/http/detail/basic_parsed_list.hpp
+++ b/boost/beast/http/detail/basic_parsed_list.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -36,7 +36,7 @@ public:
/// A constant iterator to a list element.
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
class const_iterator;
#endif
diff --git a/boost/beast/http/detail/basic_parser.hpp b/boost/beast/http/detail/basic_parser.hpp
index 741de6edf0..f4e9083ffa 100644
--- a/boost/beast/http/detail/basic_parser.hpp
+++ b/boost/beast/http/detail/basic_parser.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -12,14 +12,11 @@
#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/detail/cpu_info.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/detail/rfc7230.hpp>
#include <boost/config.hpp>
#include <boost/version.hpp>
-#include <algorithm>
#include <cstddef>
-#include <limits>
#include <utility>
namespace boost {
@@ -35,12 +32,6 @@ struct basic_parser_base
//
static std::size_t constexpr max_obs_fold = 4096;
- template<class T>
- struct is_unsigned_integer:
- std::integral_constant<bool,
- std::numeric_limits<T>::is_integer &&
- ! std::numeric_limits<T>::is_signed> {};
-
enum class state
{
nothing_yet = 0,
@@ -58,63 +49,6 @@ struct basic_parser_base
static
bool
- is_pathchar(char c)
- {
- // VFALCO This looks the same as the one below...
-
- // TEXT = <any OCTET except CTLs, and excluding LWS>
- static bool constexpr tab[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
- };
- return tab[static_cast<unsigned char>(c)];
- }
-
- static
- inline
- bool
- unhex(unsigned char& d, char c)
- {
- static signed char constexpr tab[256] = {
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 16
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 32
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, // 48
- -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 64
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 80
- -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 96
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 112
-
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 128
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 144
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 160
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 176
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 192
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 208
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 224
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 240
- };
- d = static_cast<unsigned char>(
- tab[static_cast<unsigned char>(c)]);
- return d != static_cast<unsigned char>(-1);
- }
-
- static
- bool
is_digit(char c)
{
return static_cast<unsigned char>(c-'0') < 10;
@@ -127,35 +61,16 @@ struct basic_parser_base
return static_cast<unsigned char>(c-32) < 95;
}
- template<class FwdIt>
+ BOOST_BEAST_DECL
static
- FwdIt
- trim_front(FwdIt it, FwdIt const& end)
- {
- while(it != end)
- {
- if(*it != ' ' && *it != '\t')
- break;
- ++it;
- }
- return it;
- }
+ char const*
+ trim_front(char const* it, char const* end);
- template<class RanIt>
+ BOOST_BEAST_DECL
static
- RanIt
+ char const*
trim_back(
- RanIt it, RanIt const& first)
- {
- while(it != first)
- {
- auto const c = it[-1];
- if(c != ' ' && c != '\t')
- break;
- --it;
- }
- return it;
- }
+ char const* it, char const* first);
static
string_view
@@ -167,736 +82,116 @@ struct basic_parser_base
//--------------------------------------------------------------------------
+ BOOST_BEAST_DECL
+ static
+ bool
+ is_pathchar(char c);
+
+ BOOST_BEAST_DECL
+ static
+ bool
+ unhex(unsigned char& d, char c);
+
+ BOOST_BEAST_DECL
static
std::pair<char const*, bool>
find_fast(
char const* buf,
char const* buf_end,
char const* ranges,
- size_t ranges_size)
- {
- bool found = false;
- boost::ignore_unused(buf_end, ranges, ranges_size);
- return {buf, found};
- }
+ size_t ranges_size);
- // VFALCO Can SIMD help this?
+ BOOST_BEAST_DECL
static
char const*
find_eol(
char const* it, char const* last,
- error_code& ec)
- {
- for(;;)
- {
- if(it == last)
- {
- ec.assign(0, ec.category());
- return nullptr;
- }
- if(*it == '\r')
- {
- if(++it == last)
- {
- ec.assign(0, ec.category());
- return nullptr;
- }
- if(*it != '\n')
- {
- ec = error::bad_line_ending;
- return nullptr;
- }
- ec.assign(0, ec.category());
- return ++it;
- }
- // VFALCO Should we handle the legacy case
- // for lines terminated with a single '\n'?
- ++it;
- }
- }
+ error_code& ec);
+ BOOST_BEAST_DECL
static
char const*
- find_eom(char const* p, char const* last)
- {
- for(;;)
- {
- if(p + 4 > last)
- return nullptr;
- if(p[3] != '\n')
- {
- if(p[3] == '\r')
- ++p;
- else
- p += 4;
- }
- else if(p[2] != '\r')
- {
- p += 4;
- }
- else if(p[1] != '\n')
- {
- p += 2;
- }
- else if(p[0] != '\r')
- {
- p += 2;
- }
- else
- {
- return p + 4;
- }
- }
- }
+ find_eom(char const* p, char const* last);
//--------------------------------------------------------------------------
+ BOOST_BEAST_DECL
static
char const*
parse_token_to_eol(
char const* p,
char const* last,
char const*& token_last,
- error_code& ec)
- {
- for(;; ++p)
- {
- if(p >= last)
- {
- ec = error::need_more;
- return p;
- }
- if(BOOST_UNLIKELY(! is_print(*p)))
- if((BOOST_LIKELY(static_cast<
- unsigned char>(*p) < '\040') &&
- BOOST_LIKELY(*p != '\011')) ||
- BOOST_UNLIKELY(*p == '\177'))
- goto found_control;
- }
- found_control:
- if(BOOST_LIKELY(*p == '\r'))
- {
- if(++p >= last)
- {
- ec = error::need_more;
- return last;
- }
- if(*p++ != '\n')
- {
- ec = error::bad_line_ending;
- return last;
- }
- token_last = p - 2;
- }
- #if 0
- // VFALCO This allows `\n` by itself
- // to terminate a line
- else if(*p == '\n')
- {
- token_last = p;
- ++p;
- }
- #endif
- else
- {
- // invalid character
- return nullptr;
- }
- return p;
- }
+ error_code& ec);
- template<class Iter, class T>
+ BOOST_BEAST_DECL
static
- typename std::enable_if<is_unsigned_integer<T>::value, bool>::type
- parse_dec(Iter it, Iter last, T& v)
- {
- if(it == last)
- return false;
- T tmp = 0;
- do
- {
- if((! is_digit(*it)) ||
- tmp > (std::numeric_limits<T>::max)() / 10)
- return false;
- tmp *= 10;
- T const d = *it - '0';
- if((std::numeric_limits<T>::max)() - tmp < d)
- return false;
- tmp += d;
- }
- while(++it != last);
- v = tmp;
- return true;
- }
+ bool
+ parse_dec(char const* it, char const* last, std::uint64_t& v);
- template<class Iter, class T>
+ BOOST_BEAST_DECL
static
- typename std::enable_if<is_unsigned_integer<T>::value, bool>::type
- parse_hex(Iter& it, T& v)
- {
- unsigned char d;
- if(! unhex(d, *it))
- return false;
- T tmp = 0;
- do
- {
- if(tmp > (std::numeric_limits<T>::max)() / 16)
- return false;
- tmp *= 16;
- if((std::numeric_limits<T>::max)() - tmp < d)
- return false;
- tmp += d;
- }
- while(unhex(d, *++it));
- v = tmp;
- return true;
- }
+ bool
+ parse_hex(char const*& it, std::uint64_t& v);
+ BOOST_BEAST_DECL
static
bool
- parse_crlf(char const*& it)
- {
- if( it[0] != '\r' || it[1] != '\n')
- return false;
- it += 2;
- return true;
- }
+ parse_crlf(char const*& it);
+ BOOST_BEAST_DECL
static
void
parse_method(
char const*& it, char const* last,
- string_view& result, error_code& ec)
- {
- // parse token SP
- auto const first = it;
- for(;; ++it)
- {
- if(it + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! detail::is_token_char(*it))
- break;
- }
- if(it + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ')
- {
- ec = error::bad_method;
- return;
- }
- if(it == first)
- {
- // cannot be empty
- ec = error::bad_method;
- return;
- }
- result = make_string(first, it++);
- }
+ string_view& result, error_code& ec);
+ BOOST_BEAST_DECL
static
void
parse_target(
char const*& it, char const* last,
- string_view& result, error_code& ec)
- {
- // parse target SP
- auto const first = it;
- for(;; ++it)
- {
- if(it + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! is_pathchar(*it))
- break;
- }
- if(it + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ')
- {
- ec = error::bad_target;
- return;
- }
- if(it == first)
- {
- // cannot be empty
- ec = error::bad_target;
- return;
- }
- result = make_string(first, it++);
- }
+ string_view& result, error_code& ec);
+ BOOST_BEAST_DECL
static
void
parse_version(
char const*& it, char const* last,
- int& result, error_code& ec)
- {
- if(it + 8 > last)
- {
- ec = error::need_more;
- return;
- }
- if(*it++ != 'H')
- {
- ec = error::bad_version;
- return;
- }
- if(*it++ != 'T')
- {
- ec = error::bad_version;
- return;
- }
- if(*it++ != 'T')
- {
- ec = error::bad_version;
- return;
- }
- if(*it++ != 'P')
- {
- ec = error::bad_version;
- return;
- }
- if(*it++ != '/')
- {
- ec = error::bad_version;
- return;
- }
- if(! is_digit(*it))
- {
- ec = error::bad_version;
- return;
- }
- result = 10 * (*it++ - '0');
- if(*it++ != '.')
- {
- ec = error::bad_version;
- return;
- }
- if(! is_digit(*it))
- {
- ec = error::bad_version;
- return;
- }
- result += *it++ - '0';
- }
+ int& result, error_code& ec);
+ BOOST_BEAST_DECL
static
void
parse_status(
char const*& it, char const* last,
- unsigned short& result, error_code& ec)
- {
- // parse 3(digit) SP
- if(it + 4 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! is_digit(*it))
- {
- ec = error::bad_status;
- return;
- }
- result = 100 * (*it++ - '0');
- if(! is_digit(*it))
- {
- ec = error::bad_status;
- return;
- }
- result += 10 * (*it++ - '0');
- if(! is_digit(*it))
- {
- ec = error::bad_status;
- return;
- }
- result += *it++ - '0';
- if(*it++ != ' ')
- {
- ec = error::bad_status;
- return;
- }
- }
-
+ unsigned short& result, error_code& ec);
+
+ BOOST_BEAST_DECL
+ static
void
parse_reason(
char const*& it, char const* last,
- string_view& result, error_code& ec)
- {
- auto const first = it;
- char const* token_last = nullptr;
- auto p = parse_token_to_eol(
- it, last, token_last, ec);
- if(ec)
- return;
- if(! p)
- {
- ec = error::bad_reason;
- return;
- }
- result = make_string(first, token_last);
- it = p;
- }
+ string_view& result, error_code& ec);
- template<std::size_t N>
+ BOOST_BEAST_DECL
+ static
void
parse_field(
char const*& p,
char const* last,
string_view& name,
string_view& value,
- static_string<N>& buf,
- error_code& ec)
- {
- /* header-field = field-name ":" OWS field-value OWS
-
- field-name = token
- field-value = *( field-content / obs-fold )
- field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
- field-vchar = VCHAR / obs-text
-
- obs-fold = CRLF 1*( SP / HTAB )
- ; obsolete line folding
- ; see Section 3.2.4
-
- token = 1*<any CHAR except CTLs or separators>
- CHAR = <any US-ASCII character (octets 0 - 127)>
- sep = "(" | ")" | "<" | ">" | "@"
- | "," | ";" | ":" | "\" | <">
- | "/" | "[" | "]" | "?" | "="
- | "{" | "}" | SP | HT
- */
- static char const* is_token =
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
- "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
- "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
- // name
- BOOST_ALIGNMENT(16) static const char ranges1[] =
- "\x00 " /* control chars and up to SP */
- "\"\"" /* 0x22 */
- "()" /* 0x28,0x29 */
- ",," /* 0x2c */
- "//" /* 0x2f */
- ":@" /* 0x3a-0x40 */
- "[]" /* 0x5b-0x5d */
- "{\377"; /* 0x7b-0xff */
- auto first = p;
- bool found;
- std::tie(p, found) = find_fast(
- p, last, ranges1, sizeof(ranges1)-1);
- if(! found && p >= last)
- {
- ec = error::need_more;
- return;
- }
- for(;;)
- {
- if(*p == ':')
- break;
- if(! is_token[static_cast<
- unsigned char>(*p)])
- {
- ec = error::bad_field;
- return;
- }
- ++p;
- if(p >= last)
- {
- ec = error::need_more;
- return;
- }
- }
- if(p == first)
- {
- // empty name
- ec = error::bad_field;
- return;
- }
- name = make_string(first, p);
- ++p; // eat ':'
- char const* token_last = nullptr;
- for(;;)
- {
- // eat leading ' ' and '\t'
- for(;;++p)
- {
- if(p + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! (*p == ' ' || *p == '\t'))
- break;
- }
- // parse to CRLF
- first = p;
- p = parse_token_to_eol(p, last, token_last, ec);
- if(ec)
- return;
- if(! p)
- {
- ec = error::bad_value;
- return;
- }
- // Look 1 char past the CRLF to handle obs-fold.
- if(p + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- token_last =
- trim_back(token_last, first);
- if(*p != ' ' && *p != '\t')
- {
- value = make_string(first, token_last);
- return;
- }
- ++p;
- if(token_last != first)
- break;
- }
- buf.resize(0);
- buf.append(first, token_last);
- BOOST_ASSERT(! buf.empty());
- try
- {
- for(;;)
- {
- // eat leading ' ' and '\t'
- for(;;++p)
- {
- if(p + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- if(! (*p == ' ' || *p == '\t'))
- break;
- }
- // parse to CRLF
- first = p;
- p = parse_token_to_eol(p, last, token_last, ec);
- if(ec)
- return;
- if(! p)
- {
- ec = error::bad_value;
- return;
- }
- // Look 1 char past the CRLF to handle obs-fold.
- if(p + 1 > last)
- {
- ec = error::need_more;
- return;
- }
- token_last = trim_back(token_last, first);
- if(first != token_last)
- {
- buf.push_back(' ');
- buf.append(first, token_last);
- }
- if(*p != ' ' && *p != '\t')
- {
- value = {buf.data(), buf.size()};
- return;
- }
- ++p;
- }
- }
- catch(std::length_error const&)
- {
- ec = error::header_limit;
- return;
- }
- }
+ static_string<max_obs_fold>& buf,
+ error_code& ec);
+ BOOST_BEAST_DECL
+ static
void
parse_chunk_extensions(
char const*& it,
char const* last,
- error_code& ec)
- {
- /*
- chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
- BWS = *( SP / HTAB ) ; "Bad White Space"
- chunk-ext-name = token
- chunk-ext-val = token / quoted-string
- token = 1*tchar
- quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
- qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
- quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
- obs-text = %x80-FF
-
- https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4667
- */
- loop:
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ' && *it != '\t' && *it != ';')
- return;
- // BWS
- if(*it == ' ' || *it == '\t')
- {
- for(;;)
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ' && *it != '\t')
- break;
- }
- }
- // ';'
- if(*it != ';')
- {
- ec = error::bad_chunk_extension;
- return;
- }
- semi:
- ++it; // skip ';'
- // BWS
- for(;;)
- {
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ' && *it != '\t')
- break;
- ++it;
- }
- // chunk-ext-name
- if(! detail::is_token_char(*it))
- {
- ec = error::bad_chunk_extension;
- return;
- }
- for(;;)
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(! detail::is_token_char(*it))
- break;
- }
- // BWS [ ";" / "=" ]
- {
- bool bws;
- if(*it == ' ' || *it == '\t')
- {
- for(;;)
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ' && *it != '\t')
- break;
- }
- bws = true;
- }
- else
- {
- bws = false;
- }
- if(*it == ';')
- goto semi;
- if(*it != '=')
- {
- if(bws)
- ec = error::bad_chunk_extension;
- return;
- }
- ++it; // skip '='
- }
- // BWS
- for(;;)
- {
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it != ' ' && *it != '\t')
- break;
- ++it;
- }
- // chunk-ext-val
- if(*it != '"')
- {
- // token
- if(! detail::is_token_char(*it))
- {
- ec = error::bad_chunk_extension;
- return;
- }
- for(;;)
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(! detail::is_token_char(*it))
- break;
- }
- }
- else
- {
- // quoted-string
- for(;;)
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- if(*it == '"')
- break;
- if(*it == '\\')
- {
- ++it;
- if(it == last)
- {
- ec = error::need_more;
- return;
- }
- }
- }
- ++it;
- }
- goto loop;
- }
+ error_code& ec);
};
} // detail
@@ -904,4 +199,8 @@ struct basic_parser_base
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/http/detail/basic_parser.ipp>
+#endif
+
#endif
diff --git a/boost/beast/http/detail/basic_parser.ipp b/boost/beast/http/detail/basic_parser.ipp
new file mode 100644
index 0000000000..934d0dc505
--- /dev/null
+++ b/boost/beast/http/detail/basic_parser.ipp
@@ -0,0 +1,848 @@
+//
+// Copyright (c) 2016-2019 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_DETAIL_BASIC_PARSER_IPP
+#define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_IPP
+
+#include <boost/beast/http/detail/basic_parser.hpp>
+#include <limits>
+
+namespace boost {
+namespace beast {
+namespace http {
+namespace detail {
+
+char const*
+basic_parser_base::
+trim_front(char const* it, char const* end)
+{
+ while(it != end)
+ {
+ if(*it != ' ' && *it != '\t')
+ break;
+ ++it;
+ }
+ return it;
+}
+
+char const*
+basic_parser_base::
+trim_back(
+ char const* it, char const* first)
+{
+ while(it != first)
+ {
+ auto const c = it[-1];
+ if(c != ' ' && c != '\t')
+ break;
+ --it;
+ }
+ return it;
+}
+
+bool
+basic_parser_base::
+is_pathchar(char c)
+{
+ // VFALCO This looks the same as the one below...
+
+ // TEXT = <any OCTET except CTLs, and excluding LWS>
+ static bool constexpr tab[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
+ };
+ return tab[static_cast<unsigned char>(c)];
+}
+
+bool
+basic_parser_base::
+unhex(unsigned char& d, char c)
+{
+ static signed char constexpr tab[256] = {
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 16
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 32
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, // 48
+ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 64
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 80
+ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 96
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 112
+
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 128
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 144
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 160
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 176
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 192
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 208
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 224
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // 240
+ };
+ d = static_cast<unsigned char>(
+ tab[static_cast<unsigned char>(c)]);
+ return d != static_cast<unsigned char>(-1);
+}
+
+//--------------------------------------------------------------------------
+
+std::pair<char const*, bool>
+basic_parser_base::
+find_fast(
+ char const* buf,
+ char const* buf_end,
+ char const* ranges,
+ size_t ranges_size)
+{
+ bool found = false;
+ boost::ignore_unused(buf_end, ranges, ranges_size);
+ return {buf, found};
+}
+
+// VFALCO Can SIMD help this?
+char const*
+basic_parser_base::
+find_eol(
+ char const* it, char const* last,
+ error_code& ec)
+{
+ for(;;)
+ {
+ if(it == last)
+ {
+ ec = {};
+ return nullptr;
+ }
+ if(*it == '\r')
+ {
+ if(++it == last)
+ {
+ ec = {};
+ return nullptr;
+ }
+ if(*it != '\n')
+ {
+ ec = error::bad_line_ending;
+ return nullptr;
+ }
+ ec = {};
+ return ++it;
+ }
+ // VFALCO Should we handle the legacy case
+ // for lines terminated with a single '\n'?
+ ++it;
+ }
+}
+
+bool
+basic_parser_base::
+parse_dec(char const* it, char const* last, std::uint64_t& v)
+{
+ if(it == last)
+ return false;
+ std::uint64_t tmp = 0;
+ do
+ {
+ if((! is_digit(*it)) ||
+ tmp > (std::numeric_limits<std::uint64_t>::max)() / 10)
+ return false;
+ tmp *= 10;
+ std::uint64_t const d = *it - '0';
+ if((std::numeric_limits<std::uint64_t>::max)() - tmp < d)
+ return false;
+ tmp += d;
+ }
+ while(++it != last);
+ v = tmp;
+ return true;
+}
+
+bool
+basic_parser_base::
+parse_hex(char const*& it, std::uint64_t& v)
+{
+ unsigned char d;
+ if(! unhex(d, *it))
+ return false;
+ std::uint64_t tmp = 0;
+ do
+ {
+ if(tmp > (std::numeric_limits<std::uint64_t>::max)() / 16)
+ return false;
+ tmp *= 16;
+ if((std::numeric_limits<std::uint64_t>::max)() - tmp < d)
+ return false;
+ tmp += d;
+ }
+ while(unhex(d, *++it));
+ v = tmp;
+ return true;
+}
+
+char const*
+basic_parser_base::
+find_eom(char const* p, char const* last)
+{
+ for(;;)
+ {
+ if(p + 4 > last)
+ return nullptr;
+ if(p[3] != '\n')
+ {
+ if(p[3] == '\r')
+ ++p;
+ else
+ p += 4;
+ }
+ else if(p[2] != '\r')
+ {
+ p += 4;
+ }
+ else if(p[1] != '\n')
+ {
+ p += 2;
+ }
+ else if(p[0] != '\r')
+ {
+ p += 2;
+ }
+ else
+ {
+ return p + 4;
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+
+char const*
+basic_parser_base::
+parse_token_to_eol(
+ char const* p,
+ char const* last,
+ char const*& token_last,
+ error_code& ec)
+{
+ for(;; ++p)
+ {
+ if(p >= last)
+ {
+ ec = error::need_more;
+ return p;
+ }
+ if(BOOST_UNLIKELY(! is_print(*p)))
+ if((BOOST_LIKELY(static_cast<
+ unsigned char>(*p) < '\040') &&
+ BOOST_LIKELY(*p != 9)) ||
+ BOOST_UNLIKELY(*p == 127))
+ goto found_control;
+ }
+found_control:
+ if(BOOST_LIKELY(*p == '\r'))
+ {
+ if(++p >= last)
+ {
+ ec = error::need_more;
+ return last;
+ }
+ if(*p++ != '\n')
+ {
+ ec = error::bad_line_ending;
+ return last;
+ }
+ token_last = p - 2;
+ }
+#if 0
+ // VFALCO This allows `\n` by itself
+ // to terminate a line
+ else if(*p == '\n')
+ {
+ token_last = p;
+ ++p;
+ }
+#endif
+ else
+ {
+ // invalid character
+ return nullptr;
+ }
+ return p;
+}
+
+bool
+basic_parser_base::
+parse_crlf(char const*& it)
+{
+ if( it[0] != '\r' || it[1] != '\n')
+ return false;
+ it += 2;
+ return true;
+}
+
+void
+basic_parser_base::
+parse_method(
+ char const*& it, char const* last,
+ string_view& result, error_code& ec)
+{
+ // parse token SP
+ auto const first = it;
+ for(;; ++it)
+ {
+ if(it + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! detail::is_token_char(*it))
+ break;
+ }
+ if(it + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ')
+ {
+ ec = error::bad_method;
+ return;
+ }
+ if(it == first)
+ {
+ // cannot be empty
+ ec = error::bad_method;
+ return;
+ }
+ result = make_string(first, it++);
+}
+
+void
+basic_parser_base::
+parse_target(
+ char const*& it, char const* last,
+ string_view& result, error_code& ec)
+{
+ // parse target SP
+ auto const first = it;
+ for(;; ++it)
+ {
+ if(it + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! is_pathchar(*it))
+ break;
+ }
+ if(it + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ')
+ {
+ ec = error::bad_target;
+ return;
+ }
+ if(it == first)
+ {
+ // cannot be empty
+ ec = error::bad_target;
+ return;
+ }
+ result = make_string(first, it++);
+}
+
+void
+basic_parser_base::
+parse_version(
+ char const*& it, char const* last,
+ int& result, error_code& ec)
+{
+ if(it + 8 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it++ != 'H')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(*it++ != 'T')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(*it++ != 'T')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(*it++ != 'P')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(*it++ != '/')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(! is_digit(*it))
+ {
+ ec = error::bad_version;
+ return;
+ }
+ result = 10 * (*it++ - '0');
+ if(*it++ != '.')
+ {
+ ec = error::bad_version;
+ return;
+ }
+ if(! is_digit(*it))
+ {
+ ec = error::bad_version;
+ return;
+ }
+ result += *it++ - '0';
+}
+
+void
+basic_parser_base::
+parse_status(
+ char const*& it, char const* last,
+ unsigned short& result, error_code& ec)
+{
+ // parse 3(digit) SP
+ if(it + 4 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! is_digit(*it))
+ {
+ ec = error::bad_status;
+ return;
+ }
+ result = 100 * (*it++ - '0');
+ if(! is_digit(*it))
+ {
+ ec = error::bad_status;
+ return;
+ }
+ result += 10 * (*it++ - '0');
+ if(! is_digit(*it))
+ {
+ ec = error::bad_status;
+ return;
+ }
+ result += *it++ - '0';
+ if(*it++ != ' ')
+ {
+ ec = error::bad_status;
+ return;
+ }
+}
+
+void
+basic_parser_base::
+parse_reason(
+ char const*& it, char const* last,
+ string_view& result, error_code& ec)
+{
+ auto const first = it;
+ char const* token_last = nullptr;
+ auto p = parse_token_to_eol(
+ it, last, token_last, ec);
+ if(ec)
+ return;
+ if(! p)
+ {
+ ec = error::bad_reason;
+ return;
+ }
+ result = make_string(first, token_last);
+ it = p;
+}
+
+void
+basic_parser_base::
+parse_field(
+ char const*& p,
+ char const* last,
+ string_view& name,
+ string_view& value,
+ static_string<max_obs_fold>& buf,
+ error_code& ec)
+{
+/* header-field = field-name ":" OWS field-value OWS
+
+ field-name = token
+ field-value = *( field-content / obs-fold )
+ field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+ field-vchar = VCHAR / obs-text
+
+ obs-fold = CRLF 1*( SP / HTAB )
+ ; obsolete line folding
+ ; see Section 3.2.4
+
+ token = 1*<any CHAR except CTLs or separators>
+ CHAR = <any US-ASCII character (octets 0 - 127)>
+ sep = "(" | ")" | "<" | ">" | "@"
+ | "," | ";" | ":" | "\" | <">
+ | "/" | "[" | "]" | "?" | "="
+ | "{" | "}" | SP | HT
+*/
+ static char const* is_token =
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
+ "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
+ "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+ // name
+ BOOST_ALIGNMENT(16) static const char ranges1[] =
+ "\x00 " /* control chars and up to SP */
+ "\"\"" /* 0x22 */
+ "()" /* 0x28,0x29 */
+ ",," /* 0x2c */
+ "//" /* 0x2f */
+ ":@" /* 0x3a-0x40 */
+ "[]" /* 0x5b-0x5d */
+ "{\377"; /* 0x7b-0xff */
+ auto first = p;
+ bool found;
+ std::tie(p, found) = find_fast(
+ p, last, ranges1, sizeof(ranges1)-1);
+ if(! found && p >= last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ for(;;)
+ {
+ if(*p == ':')
+ break;
+ if(! is_token[static_cast<
+ unsigned char>(*p)])
+ {
+ ec = error::bad_field;
+ return;
+ }
+ ++p;
+ if(p >= last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ }
+ if(p == first)
+ {
+ // empty name
+ ec = error::bad_field;
+ return;
+ }
+ name = make_string(first, p);
+ ++p; // eat ':'
+ char const* token_last = nullptr;
+ for(;;)
+ {
+ // eat leading ' ' and '\t'
+ for(;;++p)
+ {
+ if(p + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! (*p == ' ' || *p == '\t'))
+ break;
+ }
+ // parse to CRLF
+ first = p;
+ p = parse_token_to_eol(p, last, token_last, ec);
+ if(ec)
+ return;
+ if(! p)
+ {
+ ec = error::bad_value;
+ return;
+ }
+ // Look 1 char past the CRLF to handle obs-fold.
+ if(p + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ token_last =
+ trim_back(token_last, first);
+ if(*p != ' ' && *p != '\t')
+ {
+ value = make_string(first, token_last);
+ return;
+ }
+ ++p;
+ if(token_last != first)
+ break;
+ }
+ buf.resize(0);
+ buf.append(first, token_last);
+ BOOST_ASSERT(! buf.empty());
+#ifndef BOOST_NO_EXCEPTIONS
+ try
+#endif
+ {
+ for(;;)
+ {
+ // eat leading ' ' and '\t'
+ for(;;++p)
+ {
+ if(p + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! (*p == ' ' || *p == '\t'))
+ break;
+ }
+ // parse to CRLF
+ first = p;
+ p = parse_token_to_eol(p, last, token_last, ec);
+ if(ec)
+ return;
+ if(! p)
+ {
+ ec = error::bad_value;
+ return;
+ }
+ // Look 1 char past the CRLF to handle obs-fold.
+ if(p + 1 > last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ token_last = trim_back(token_last, first);
+ if(first != token_last)
+ {
+ buf.push_back(' ');
+ buf.append(first, token_last);
+ }
+ if(*p != ' ' && *p != '\t')
+ {
+ value = {buf.data(), buf.size()};
+ return;
+ }
+ ++p;
+ }
+ }
+#ifndef BOOST_NO_EXCEPTIONS
+ catch(std::length_error const&)
+ {
+ ec = error::header_limit;
+ return;
+ }
+#endif
+}
+
+
+void
+basic_parser_base::
+parse_chunk_extensions(
+ char const*& it,
+ char const* last,
+ error_code& ec)
+{
+/*
+ chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
+ BWS = *( SP / HTAB ) ; "Bad White Space"
+ chunk-ext-name = token
+ chunk-ext-val = token / quoted-string
+ token = 1*tchar
+ quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
+ qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
+ quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
+ obs-text = %x80-FF
+
+ https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4667
+*/
+loop:
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ' && *it != '\t' && *it != ';')
+ return;
+ // BWS
+ if(*it == ' ' || *it == '\t')
+ {
+ for(;;)
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ' && *it != '\t')
+ break;
+ }
+ }
+ // ';'
+ if(*it != ';')
+ {
+ ec = error::bad_chunk_extension;
+ return;
+ }
+semi:
+ ++it; // skip ';'
+ // BWS
+ for(;;)
+ {
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ' && *it != '\t')
+ break;
+ ++it;
+ }
+ // chunk-ext-name
+ if(! detail::is_token_char(*it))
+ {
+ ec = error::bad_chunk_extension;
+ return;
+ }
+ for(;;)
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! detail::is_token_char(*it))
+ break;
+ }
+ // BWS [ ";" / "=" ]
+ {
+ bool bws;
+ if(*it == ' ' || *it == '\t')
+ {
+ for(;;)
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ' && *it != '\t')
+ break;
+ }
+ bws = true;
+ }
+ else
+ {
+ bws = false;
+ }
+ if(*it == ';')
+ goto semi;
+ if(*it != '=')
+ {
+ if(bws)
+ ec = error::bad_chunk_extension;
+ return;
+ }
+ ++it; // skip '='
+ }
+ // BWS
+ for(;;)
+ {
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it != ' ' && *it != '\t')
+ break;
+ ++it;
+ }
+ // chunk-ext-val
+ if(*it != '"')
+ {
+ // token
+ if(! detail::is_token_char(*it))
+ {
+ ec = error::bad_chunk_extension;
+ return;
+ }
+ for(;;)
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(! detail::is_token_char(*it))
+ break;
+ }
+ }
+ else
+ {
+ // quoted-string
+ for(;;)
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ if(*it == '"')
+ break;
+ if(*it == '\\')
+ {
+ ++it;
+ if(it == last)
+ {
+ ec = error::need_more;
+ return;
+ }
+ }
+ }
+ ++it;
+ }
+ goto loop;
+}
+
+} // detail
+} // http
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/http/detail/chunk_encode.hpp b/boost/beast/http/detail/chunk_encode.hpp
index 87ac9ec41e..fe38e7a6c8 100644
--- a/boost/beast/http/detail/chunk_encode.hpp
+++ b/boost/beast/http/detail/chunk_encode.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,7 +10,6 @@
#ifndef BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
#define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
-#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/http/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <algorithm>
@@ -26,15 +25,15 @@ namespace detail {
struct chunk_extensions
{
virtual ~chunk_extensions() = default;
- virtual boost::asio::const_buffer str() = 0;
+ virtual net::const_buffer str() = 0;
};
-
+
template<class ChunkExtensions>
struct chunk_extensions_impl : chunk_extensions
{
ChunkExtensions ext_;
- chunk_extensions_impl(ChunkExtensions&& ext)
+ chunk_extensions_impl(ChunkExtensions&& ext) noexcept
: ext_(std::move(ext))
{
}
@@ -44,7 +43,7 @@ struct chunk_extensions_impl : chunk_extensions
{
}
- boost::asio::const_buffer
+ net::const_buffer
str() override
{
auto const s = ext_.str();
@@ -88,7 +87,7 @@ class chunk_size
struct sequence
{
- boost::asio::const_buffer b;
+ net::const_buffer b;
char data[1 + 2 * sizeof(std::size_t)];
explicit
@@ -104,7 +103,7 @@ class chunk_size
std::shared_ptr<sequence> sp_;
public:
- using value_type = boost::asio::const_buffer;
+ using value_type = net::const_buffer;
using const_iterator = value_type const*;
@@ -136,34 +135,37 @@ public:
/// Returns a buffer sequence holding a CRLF for chunk encoding
inline
-boost::asio::const_buffer
+net::const_buffer const&
chunk_crlf()
{
- return {"\r\n", 2};
+ static net::const_buffer const cb{"\r\n", 2};
+ return cb;
}
/// Returns a buffer sequence holding a final chunk header
inline
-boost::asio::const_buffer
+net::const_buffer const&
chunk_last()
{
- return {"0\r\n", 3};
+ static net::const_buffer const cb{"0\r\n", 3};
+ return cb;
}
//------------------------------------------------------------------------------
+#if 0
template<class = void>
struct chunk_crlf_iter_type
{
class value_type
{
char const s[2] = {'\r', '\n'};
-
+
public:
value_type() = default;
operator
- boost::asio::const_buffer() const
+ net::const_buffer() const
{
return {s, sizeof(s)};
}
@@ -176,44 +178,19 @@ typename chunk_crlf_iter_type<T>::value_type
chunk_crlf_iter_type<T>::value;
using chunk_crlf_iter = chunk_crlf_iter_type<void>;
+#endif
//------------------------------------------------------------------------------
-template<class = void>
-struct chunk_size0_iter_type
-{
- class value_type
- {
- char const s[3] = {'0', '\r', '\n'};
-
- public:
- value_type() = default;
-
- operator
- boost::asio::const_buffer() const
- {
- return {s, sizeof(s)};
- }
- };
- static value_type value;
-};
-
-template<class T>
-typename chunk_size0_iter_type<T>::value_type
-chunk_size0_iter_type<T>::value;
-
-using chunk_size0_iter = chunk_size0_iter_type<void>;
-
struct chunk_size0
{
- using value_type = chunk_size0_iter::value_type;
-
+ using value_type = net::const_buffer;
using const_iterator = value_type const*;
const_iterator
begin() const
{
- return &chunk_size0_iter::value;
+ return &chunk_last();
}
const_iterator
diff --git a/boost/beast/http/detail/rfc7230.hpp b/boost/beast/http/detail/rfc7230.hpp
index afe35691ae..99f4af05e1 100644
--- a/boost/beast/http/detail/rfc7230.hpp
+++ b/boost/beast/http/detail/rfc7230.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -19,300 +19,54 @@ namespace beast {
namespace http {
namespace detail {
-inline
+BOOST_BEAST_DECL
bool
-is_digit(char c)
-{
- return c >= '0' && c <= '9';
-}
+is_digit(char c);
-inline
+BOOST_BEAST_DECL
char
-is_alpha(char c)
-{
- static char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 80
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 112
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
+is_alpha(char c);
-inline
+BOOST_BEAST_DECL
char
-is_text(char c)
-{
- // TEXT = <any OCTET except CTLs, but including LWS>
- static char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
+is_text(char c);
-inline
+BOOST_BEAST_DECL
char
-is_token_char(char c)
-{
- /*
- tchar = "!" | "#" | "$" | "%" | "&" |
- "'" | "*" | "+" | "-" | "." |
- "^" | "_" | "`" | "|" | "~" |
- DIGIT | ALPHA
- */
- static char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
+is_token_char(char c);
-inline
+BOOST_BEAST_DECL
char
-is_qdchar(char c)
-{
- /*
- qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
- */
- static char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 80
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
+is_qdchar(char c);
-inline
+BOOST_BEAST_DECL
char
-is_qpchar(char c)
-{
- /*
- quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
- obs-text = %x80-FF
- */
- static char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
+is_qpchar(char c);
+
// converts to lower case,
// returns 0 if not a valid text char
//
-inline
+BOOST_BEAST_DECL
char
-to_value_char(char c)
-{
- // TEXT = <any OCTET except CTLs, but including LWS>
- static unsigned char constexpr tab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
- 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return static_cast<char>(tab[static_cast<unsigned char>(c)]);
-}
+to_value_char(char c);
// VFALCO TODO Make this return unsigned?
-inline
+BOOST_BEAST_DECL
std::int8_t
-unhex(char c)
-{
- static signed char constexpr tab[] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240
- };
- BOOST_STATIC_ASSERT(sizeof(tab) == 256);
- return tab[static_cast<unsigned char>(c)];
-}
-
-template<class FwdIt>
-inline
-void
-skip_ows(FwdIt& it, FwdIt const& end)
-{
- while(it != end)
- {
- if(*it != ' ' && *it != '\t')
- break;
- ++it;
- }
-}
+unhex(char c);
-template<class RanIt>
-inline
+BOOST_BEAST_DECL
void
-skip_ows_rev(
- RanIt& it, RanIt const& first)
-{
- while(it != first)
- {
- auto const c = it[-1];
- if(c != ' ' && c != '\t')
- break;
- --it;
- }
-}
-
-// obs-fold = CRLF 1*( SP / HTAB )
-// return `false` on parse error
-//
-template<class FwdIt>
-inline
-bool
-skip_obs_fold(
- FwdIt& it, FwdIt const& last)
-{
- for(;;)
- {
- if(*it != '\r')
- return true;
- if(++it == last)
- return false;
- if(*it != '\n')
- return false;
- if(++it == last)
- return false;
- if(*it != ' ' && *it != '\t')
- return false;
- for(;;)
- {
- if(++it == last)
- return true;
- if(*it != ' ' && *it != '\t')
- return true;
- }
- }
-}
+skip_ows(char const*& it, char const* end);
-template<class FwdIt>
+BOOST_BEAST_DECL
void
-skip_token(FwdIt& it, FwdIt const& last)
-{
- while(it != last && is_token_char(*it))
- ++it;
-}
+skip_token(char const*& it, char const* last);
-inline
+BOOST_BEAST_DECL
string_view
-trim(string_view s)
-{
- auto first = s.begin();
- auto last = s.end();
- skip_ows(first, last);
- while(first != last)
- {
- auto const c = *std::prev(last);
- if(c != ' ' && c != '\t')
- break;
- --last;
- }
- if(first == last)
- return {};
- return {&*first,
- static_cast<std::size_t>(last - first)};
-}
+trim(string_view s);
struct param_iter
{
@@ -329,94 +83,11 @@ struct param_iter
return first == it;
}
- template<class = void>
+ BOOST_BEAST_DECL
void
increment();
};
-template<class>
-void
-param_iter::
-increment()
-{
-/*
- param-list = *( OWS ";" OWS param )
- param = token OWS [ "=" OWS ( token / quoted-string ) ]
- quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
- qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
- quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
- obs-text = %x80-FF
-*/
- auto const err =
- [&]
- {
- it = first;
- };
- v.first = {};
- v.second = {};
- detail::skip_ows(it, last);
- first = it;
- if(it == last)
- return err();
- if(*it != ';')
- return err();
- ++it;
- detail::skip_ows(it, last);
- if(it == last)
- return err();
- // param
- if(! detail::is_token_char(*it))
- return err();
- auto const p0 = it;
- skip_token(++it, last);
- auto const p1 = it;
- v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
- detail::skip_ows(it, last);
- if(it == last)
- return;
- if(*it == ';')
- return;
- if(*it != '=')
- return err();
- ++it;
- detail::skip_ows(it, last);
- if(it == last)
- return;
- if(*it == '"')
- {
- // quoted-string
- auto const p2 = it;
- ++it;
- for(;;)
- {
- if(it == last)
- return err();
- auto c = *it++;
- if(c == '"')
- break;
- if(detail::is_qdchar(c))
- continue;
- if(c != '\\')
- return err();
- if(it == last)
- return err();
- c = *it++;
- if(! detail::is_qpchar(c))
- return err();
- }
- v.second = { &*p2, static_cast<std::size_t>(it - p2) };
- }
- else
- {
- // token
- if(! detail::is_token_char(*it))
- return err();
- auto const p2 = it;
- skip_token(++it, last);
- v.second = { &*p2, static_cast<std::size_t>(it - p2) };
- }
-}
-
/*
#token = [ ( "," / token ) *( OWS "," [ OWS token ] ) ]
*/
@@ -424,44 +95,10 @@ struct opt_token_list_policy
{
using value_type = string_view;
+ BOOST_BEAST_DECL
bool
operator()(value_type& v,
- char const*& it, string_view s) const
- {
- v = {};
- auto need_comma = it != s.data();
- for(;;)
- {
- detail::skip_ows(it, (s.data() + s.size()));
- if(it == (s.data() + s.size()))
- {
- it = nullptr;
- return true;
- }
- auto const c = *it;
- if(detail::is_token_char(c))
- {
- if(need_comma)
- return false;
- auto const p0 = it;
- for(;;)
- {
- ++it;
- if(it == (s.data() + s.size()))
- break;
- if(! detail::is_token_char(*it))
- break;
- }
- v = string_view{p0,
- static_cast<std::size_t>(it - p0)};
- return true;
- }
- if(c != ',')
- return false;
- need_comma = false;
- ++it;
- }
- }
+ char const*& it, string_view s) const;
};
} // detail
@@ -469,5 +106,9 @@ struct opt_token_list_policy
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/http/detail/rfc7230.ipp>
+#endif
+
#endif
diff --git a/boost/beast/http/detail/rfc7230.ipp b/boost/beast/http/detail/rfc7230.ipp
new file mode 100644
index 0000000000..612eaf9a02
--- /dev/null
+++ b/boost/beast/http/detail/rfc7230.ipp
@@ -0,0 +1,388 @@
+//
+// Copyright (c) 2016-2019 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_DETAIL_RFC7230_IPP
+#define BOOST_BEAST_HTTP_DETAIL_RFC7230_IPP
+
+#include <boost/beast/core/string.hpp>
+#include <iterator>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace http {
+namespace detail {
+
+bool
+is_digit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+char
+is_alpha(char c)
+{
+ static char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 80
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 112
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+char
+is_text(char c)
+{
+ // TEXT = <any OCTET except CTLs, but including LWS>
+ static char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+char
+is_token_char(char c)
+{
+ /*
+ tchar = "!" | "#" | "$" | "%" | "&" |
+ "'" | "*" | "+" | "-" | "." |
+ "^" | "_" | "`" | "|" | "~" |
+ DIGIT | ALPHA
+ */
+ static char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+char
+is_qdchar(char c)
+{
+ /*
+ qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
+ */
+ static char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 80
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+char
+is_qpchar(char c)
+{
+ /*
+ quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
+ obs-text = %x80-FF
+ */
+ static char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+// converts to lower case,
+// returns 0 if not a valid text char
+//
+char
+to_value_char(char c)
+{
+ // TEXT = <any OCTET except CTLs, but including LWS>
+ static unsigned char constexpr tab[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
+ 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return static_cast<char>(tab[static_cast<unsigned char>(c)]);
+}
+
+// VFALCO TODO Make this return unsigned?
+std::int8_t
+unhex(char c)
+{
+ static signed char constexpr tab[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240
+ };
+ BOOST_STATIC_ASSERT(sizeof(tab) == 256);
+ return tab[static_cast<unsigned char>(c)];
+}
+
+void
+skip_ows(char const*& it, char const* end)
+{
+ while(it != end)
+ {
+ if(*it != ' ' && *it != '\t')
+ break;
+ ++it;
+ }
+}
+
+void
+skip_token(char const*& it, char const* last)
+{
+ while(it != last && is_token_char(*it))
+ ++it;
+}
+
+string_view
+trim(string_view s)
+{
+ auto first = s.begin();
+ auto last = s.end();
+ skip_ows(first, last);
+ while(first != last)
+ {
+ auto const c = *std::prev(last);
+ if(c != ' ' && c != '\t')
+ break;
+ --last;
+ }
+ if(first == last)
+ return {};
+ return {&*first,
+ static_cast<std::size_t>(last - first)};
+}
+
+
+BOOST_BEAST_DECL
+void
+param_iter::
+increment()
+{
+/*
+ param-list = *( OWS ";" OWS param )
+ param = token OWS [ "=" OWS ( token / quoted-string ) ]
+ quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
+ qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
+ quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
+ obs-text = %x80-FF
+*/
+ auto const err =
+ [&]
+ {
+ it = first;
+ };
+ v.first = {};
+ v.second = {};
+ detail::skip_ows(it, last);
+ first = it;
+ if(it == last)
+ return err();
+ if(*it != ';')
+ return err();
+ ++it;
+ detail::skip_ows(it, last);
+ if(it == last)
+ return err();
+ // param
+ if(! detail::is_token_char(*it))
+ return err();
+ auto const p0 = it;
+ skip_token(++it, last);
+ auto const p1 = it;
+ v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
+ detail::skip_ows(it, last);
+ if(it == last)
+ return;
+ if(*it == ';')
+ return;
+ if(*it != '=')
+ return err();
+ ++it;
+ detail::skip_ows(it, last);
+ if(it == last)
+ return;
+ if(*it == '"')
+ {
+ // quoted-string
+ auto const p2 = it;
+ ++it;
+ for(;;)
+ {
+ if(it == last)
+ return err();
+ auto c = *it++;
+ if(c == '"')
+ break;
+ if(detail::is_qdchar(c))
+ continue;
+ if(c != '\\')
+ return err();
+ if(it == last)
+ return err();
+ c = *it++;
+ if(! detail::is_qpchar(c))
+ return err();
+ }
+ v.second = { &*p2, static_cast<std::size_t>(it - p2) };
+ }
+ else
+ {
+ // token
+ if(! detail::is_token_char(*it))
+ return err();
+ auto const p2 = it;
+ skip_token(++it, last);
+ v.second = { &*p2, static_cast<std::size_t>(it - p2) };
+ }
+}
+
+bool
+opt_token_list_policy::operator()(value_type& v,
+ char const*& it, string_view s) const
+{
+ v = {};
+ auto need_comma = it != s.data();
+ for(;;)
+ {
+ detail::skip_ows(it, (s.data() + s.size()));
+ if(it == (s.data() + s.size()))
+ {
+ it = nullptr;
+ return true;
+ }
+ auto const c = *it;
+ if(detail::is_token_char(c))
+ {
+ if(need_comma)
+ return false;
+ auto const p0 = it;
+ for(;;)
+ {
+ ++it;
+ if(it == (s.data() + s.size()))
+ break;
+ if(! detail::is_token_char(*it))
+ break;
+ }
+ v = string_view{p0,
+ static_cast<std::size_t>(it - p0)};
+ return true;
+ }
+ if(c != ',')
+ return false;
+ need_comma = false;
+ ++it;
+ }
+}
+
+} // detail
+} // http
+} // beast
+} // boost
+
+#endif // BOOST_BEAST_HTTP_DETAIL_RFC7230_IPP
+
diff --git a/boost/beast/http/detail/type_traits.hpp b/boost/beast/http/detail/type_traits.hpp
index b849446b0f..1da4c4e414 100644
--- a/boost/beast/http/detail/type_traits.hpp
+++ b/boost/beast/http/detail/type_traits.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -19,12 +19,12 @@ namespace beast {
namespace http {
template<bool isRequest, class Fields>
-struct header;
+class header;
template<bool, class, class>
-struct message;
+class message;
-template<bool isRequest,class Body, class Fields>
+template<bool isRequest, class Body, class Fields>
class parser;
namespace detail {
@@ -80,7 +80,7 @@ struct has_value_type<T, beast::detail::void_t<
typename T::value_type
> > : std::true_type {};
-/** Determine if a @b Body type has a size
+/** Determine if a <em>Body</em> type has a size
This metafunction is equivalent to `std::true_type` if
Body contains a static member function called `size`.
diff --git a/boost/beast/http/dynamic_body.hpp b/boost/beast/http/dynamic_body.hpp
index 9c3df8a1d2..a55fff45ef 100644
--- a/boost/beast/http/dynamic_body.hpp
+++ b/boost/beast/http/dynamic_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -19,7 +19,7 @@ namespace http {
/** A dynamic message body represented by a @ref multi_buffer
- Meets the requirements of @b Body.
+ Meets the requirements of <em>Body</em>.
*/
using dynamic_body = basic_dynamic_body<multi_buffer>;
diff --git a/boost/beast/http/empty_body.hpp b/boost/beast/http/empty_body.hpp
index d56c14b4ef..40ea24614b 100644
--- a/boost/beast/http/empty_body.hpp
+++ b/boost/beast/http/empty_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -19,7 +19,7 @@ namespace boost {
namespace beast {
namespace http {
-/** An empty @b Body
+/** An empty <em>Body</em>
This body is used to represent messages which do not have a
message body. If this body is used with a parser, and the
@@ -54,10 +54,10 @@ struct empty_body
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
struct reader
{
@@ -70,7 +70,7 @@ struct empty_body
void
init(boost::optional<std::uint64_t> const&, error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -85,22 +85,22 @@ struct empty_body
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
struct writer
{
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
explicit
@@ -111,13 +111,13 @@ struct empty_body
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
return boost::none;
}
};
diff --git a/boost/beast/http/error.hpp b/boost/beast/http/error.hpp
index b3d9fb1188..d0c287ebc9 100644
--- a/boost/beast/http/error.hpp
+++ b/boost/beast/http/error.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -23,7 +23,7 @@ enum class error
/** The end of the stream was reached.
This error is returned when attempting to read HTTP data,
- and the stream returns the error `boost::asio::error::eof`
+ and the stream returns the error `net::error::eof`
before any octets corresponding to a new HTTP message have
been received.
*/
@@ -51,7 +51,7 @@ enum class error
octets into a message container which has the
@ref empty_body body type.
- @see @ref empty_body
+ @see empty_body
*/
unexpected_body,
@@ -144,13 +144,25 @@ enum class error
bad_chunk_extension,
/// An obs-fold exceeded an internal limit.
- bad_obs_fold
+ bad_obs_fold,
+
+ /** The parser is stale.
+
+ This happens when attempting to re-use a parser that has
+ already completed parsing a message. Programs must construct
+ a new parser for each message. This can be easily done by
+ storing the parser in an boost or std::optional container.
+ */
+ stale_parser
};
} // http
} // beast
} // boost
+#include <boost/beast/http/impl/error.hpp>
+#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/http/impl/error.ipp>
+#endif
#endif
diff --git a/boost/beast/http/field.hpp b/boost/beast/http/field.hpp
index 09d9dfffdf..69eb253fdf 100644
--- a/boost/beast/http/field.hpp
+++ b/boost/beast/http/field.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -380,6 +380,7 @@ enum class field : unsigned short
@param f The field to convert
*/
+BOOST_BEAST_DECL
string_view
to_string(field f);
@@ -390,6 +391,7 @@ to_string(field f);
@return The corresponding field, or @ref field::unknown
if no known field matches.
*/
+BOOST_BEAST_DECL
field
string_to_field(string_view s);
@@ -405,6 +407,8 @@ operator<<(std::ostream& os, field f)
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/http/impl/field.ipp>
+#endif
#endif
diff --git a/boost/beast/http/fields.hpp b/boost/beast/http/fields.hpp
index 8d526867dc..927191d755 100644
--- a/boost/beast/http/fields.hpp
+++ b/boost/beast/http/fields.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -45,10 +45,9 @@ namespace http {
is iterated the fields are presented in the order of insertion, with
fields having the same name following each other consecutively.
- Meets the requirements of @b Fields
+ Meets the requirements of <em>Fields</em>
- @tparam Allocator The allocator to use. This must meet the
- requirements of @b Allocator.
+ @tparam Allocator The allocator to use.
*/
template<class Allocator>
class basic_fields
@@ -85,7 +84,7 @@ public:
char*
data() const;
- boost::asio::const_buffer
+ net::const_buffer
buffer() const;
protected:
@@ -117,7 +116,7 @@ public:
The case-comparison operation is defined only for low-ASCII characters.
*/
#if BOOST_BEAST_DOXYGEN
- using key_compare = implementation_defined;
+ using key_compare = __implementation_defined__;
#else
struct key_compare : beast::iless
#endif
@@ -164,7 +163,7 @@ public:
/// The algorithm used to serialize the header
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer;
#endif
@@ -277,7 +276,7 @@ public:
public:
/// A constant iterator to the field sequence.
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
using const_iterator = typename list_t::const_iterator;
#endif
@@ -768,6 +767,6 @@ using fields = basic_fields<std::allocator<char>>;
} // beast
} // boost
-#include <boost/beast/http/impl/fields.ipp>
+#include <boost/beast/http/impl/fields.hpp>
#endif
diff --git a/boost/beast/http/file_body.hpp b/boost/beast/http/file_body.hpp
index 42e7a15330..a78d7901de 100644
--- a/boost/beast/http/file_body.hpp
+++ b/boost/beast/http/file_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -30,6 +30,8 @@ using file_body = basic_file_body<file>;
} // beast
} // boost
-#include <boost/beast/http/impl/file_body_win32.ipp>
+#ifndef BOOST_BEAST_NO_FILE_BODY_WIN32
+#include <boost/beast/http/impl/file_body_win32.hpp>
+#endif
#endif
diff --git a/boost/beast/http/impl/basic_parser.hpp b/boost/beast/http/impl/basic_parser.hpp
new file mode 100644
index 0000000000..e25be7ce08
--- /dev/null
+++ b/boost/beast/http/impl/basic_parser.hpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2016-2019 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_IMPL_BASIC_PARSER_HPP
+#define BOOST_BEAST_HTTP_IMPL_BASIC_PARSER_HPP
+
+#include <boost/beast/core/buffer_traits.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/make_unique.hpp>
+
+namespace boost {
+namespace beast {
+namespace http {
+
+template<bool isRequest>
+template<class ConstBufferSequence>
+std::size_t
+basic_parser<isRequest>::
+put(ConstBufferSequence const& buffers,
+ error_code& ec)
+{
+ static_assert(net::is_const_buffer_sequence<
+ ConstBufferSequence>::value,
+ "ConstBufferSequence type requirements not met");
+ auto const p = net::buffer_sequence_begin(buffers);
+ auto const last = net::buffer_sequence_end(buffers);
+ if(p == last)
+ {
+ ec = {};
+ return 0;
+ }
+ if(std::next(p) == last)
+ {
+ // single buffer
+ return put(net::const_buffer(*p), ec);
+ }
+ auto const size = buffer_bytes(buffers);
+ if(size <= max_stack_buffer)
+ return put_from_stack(size, buffers, ec);
+ if(size > buf_len_)
+ {
+ // reallocate
+ buf_ = boost::make_unique_noinit<char[]>(size);
+ buf_len_ = size;
+ }
+ // flatten
+ net::buffer_copy(net::buffer(
+ buf_.get(), buf_len_), buffers);
+ return put(net::const_buffer{
+ buf_.get(), buf_len_}, ec);
+}
+
+template<bool isRequest>
+template<class ConstBufferSequence>
+std::size_t
+basic_parser<isRequest>::
+put_from_stack(std::size_t size,
+ ConstBufferSequence const& buffers,
+ error_code& ec)
+{
+ char buf[max_stack_buffer];
+ net::buffer_copy(net::mutable_buffer(
+ buf, sizeof(buf)), buffers);
+ return put(net::const_buffer{
+ buf, size}, ec);
+}
+
+} // http
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/http/impl/basic_parser.ipp b/boost/beast/http/impl/basic_parser.ipp
index 7a46092861..99947ae1f2 100644
--- a/boost/beast/http/impl/basic_parser.ipp
+++ b/boost/beast/http/impl/basic_parser.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,14 +10,14 @@
#ifndef BOOST_BEAST_HTTP_IMPL_BASIC_PARSER_IPP
#define BOOST_BEAST_HTTP_IMPL_BASIC_PARSER_IPP
+#include <boost/beast/http/basic_parser.hpp>
+#include <boost/beast/http/error.hpp>
+#include <boost/beast/http/rfc7230.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/static_string.hpp>
-#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/core/detail/config.hpp>
-#include <boost/beast/http/error.hpp>
-#include <boost/beast/http/rfc7230.hpp>
#include <boost/asio/buffer.hpp>
-#include <boost/make_unique.hpp>
#include <algorithm>
#include <utility>
@@ -25,26 +25,9 @@ namespace boost {
namespace beast {
namespace http {
-template<bool isRequest, class Derived>
-template<class OtherDerived>
-basic_parser<isRequest, Derived>::
-basic_parser(basic_parser<
- isRequest, OtherDerived>&& other)
- : body_limit_(other.body_limit_)
- , len_(other.len_)
- , buf_(std::move(other.buf_))
- , buf_len_(other.buf_len_)
- , skip_(other.skip_)
- , header_limit_(other.header_limit_)
- , status_(other.status_)
- , state_(other.state_)
- , f_(other.f_)
-{
-}
-
-template<bool isRequest, class Derived>
+template<bool isRequest>
bool
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
keep_alive() const
{
BOOST_ASSERT(is_header_done());
@@ -61,20 +44,31 @@ keep_alive() const
return (f_ & flagNeedEOF) == 0;
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
boost::optional<std::uint64_t>
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
content_length() const
{
BOOST_ASSERT(is_header_done());
if(! (f_ & flagContentLength))
return boost::none;
+ return len0_;
+}
+
+template<bool isRequest>
+boost::optional<std::uint64_t>
+basic_parser<isRequest>::
+content_length_remaining() const
+{
+ BOOST_ASSERT(is_header_done());
+ if(! (f_ & flagContentLength))
+ return boost::none;
return len_;
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
skip(bool v)
{
BOOST_ASSERT(! got_some());
@@ -84,59 +78,18 @@ skip(bool v)
f_ &= ~flagSkipBody;
}
-template<bool isRequest, class Derived>
-template<class ConstBufferSequence>
+template<bool isRequest>
std::size_t
-basic_parser<isRequest, Derived>::
-put(ConstBufferSequence const& buffers,
- error_code& ec)
-{
- static_assert(boost::asio::is_const_buffer_sequence<
- ConstBufferSequence>::value,
- "ConstBufferSequence requirements not met");
- using boost::asio::buffer_copy;
- using boost::asio::buffer_size;
- auto const p = boost::asio::buffer_sequence_begin(buffers);
- auto const last = boost::asio::buffer_sequence_end(buffers);
- if(p == last)
- {
- ec.assign(0, ec.category());
- return 0;
- }
- if(std::next(p) == last)
- {
- // single buffer
- return put(boost::asio::const_buffer(*p), ec);
- }
- auto const size = buffer_size(buffers);
- if(size <= max_stack_buffer)
- return put_from_stack(size, buffers, ec);
- if(size > buf_len_)
- {
- // reallocate
- buf_ = boost::make_unique_noinit<char[]>(size);
- buf_len_ = size;
- }
- // flatten
- buffer_copy(boost::asio::buffer(
- buf_.get(), buf_len_), buffers);
- return put(boost::asio::const_buffer{
- buf_.get(), buf_len_}, ec);
-}
-
-template<bool isRequest, class Derived>
-std::size_t
-basic_parser<isRequest, Derived>::
-put(boost::asio::const_buffer const& buffer,
+basic_parser<isRequest>::
+put(net::const_buffer buffer,
error_code& ec)
{
BOOST_ASSERT(state_ != state::complete);
- using boost::asio::buffer_size;
auto p = static_cast<char const*>(buffer.data());
auto n = buffer.size();
auto const p0 = p;
auto const p1 = p0 + n;
- ec.assign(0, ec.category());
+ ec = {};
loop:
switch(state_)
{
@@ -207,7 +160,7 @@ loop:
case state::body0:
BOOST_ASSERT(! skip_);
- impl().on_body_init_impl(content_length(), ec);
+ this->on_body_init_impl(content_length(), ec);
if(ec)
goto done;
state_ = state::body;
@@ -222,7 +175,7 @@ loop:
case state::body_to_eof0:
BOOST_ASSERT(! skip_);
- impl().on_body_init_impl(content_length(), ec);
+ this->on_body_init_impl(content_length(), ec);
if(ec)
goto done;
state_ = state::body_to_eof;
@@ -236,7 +189,7 @@ loop:
break;
case state::chunk_header0:
- impl().on_body_init_impl(content_length(), ec);
+ this->on_body_init_impl(content_length(), ec);
if(ec)
goto done;
state_ = state::chunk_header;
@@ -255,7 +208,7 @@ loop:
break;
case state::complete:
- ec.assign(0, ec.category());
+ ec = {};
goto done;
}
if(p < p1 && ! is_done() && eager())
@@ -267,9 +220,9 @@ done:
return static_cast<std::size_t>(p - p0);
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
put_eof(error_code& ec)
{
BOOST_ASSERT(got_some());
@@ -286,35 +239,19 @@ put_eof(error_code& ec)
ec = error::partial_message;
return;
}
- ec.assign(0, ec.category());
+ ec = {};
return;
}
- impl().on_finish_impl(ec);
+ ec = {};
+ this->on_finish_impl(ec);
if(ec)
return;
state_ = state::complete;
}
-template<bool isRequest, class Derived>
-template<class ConstBufferSequence>
-std::size_t
-basic_parser<isRequest, Derived>::
-put_from_stack(std::size_t size,
- ConstBufferSequence const& buffers,
- error_code& ec)
-{
- char buf[max_stack_buffer];
- using boost::asio::buffer;
- using boost::asio::buffer_copy;
- buffer_copy(buffer(buf, sizeof(buf)), buffers);
- return put(boost::asio::const_buffer{
- buf, size}, ec);
-}
-
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
maybe_need_more(
char const* p, std::size_t n,
error_code& ec)
@@ -344,10 +281,9 @@ maybe_need_more(
skip_ = 0;
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_start_line(
char const*& in, char const* last,
error_code& ec, std::true_type)
@@ -393,7 +329,7 @@ parse_start_line(
if(version >= 11)
f_ |= flagHTTP11;
- impl().on_request_impl(string_to_verb(method),
+ this->on_request_impl(string_to_verb(method),
method, target, version, ec);
if(ec)
return;
@@ -402,10 +338,9 @@ parse_start_line(
state_ = state::fields;
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_start_line(
char const*& in, char const* last,
error_code& ec, std::false_type)
@@ -452,7 +387,7 @@ parse_start_line(
if(version >= 11)
f_ |= flagHTTP11;
- impl().on_response_impl(
+ this->on_response_impl(
status_, reason, version, ec);
if(ec)
return;
@@ -461,9 +396,9 @@ parse_start_line(
state_ = state::fields;
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_fields(char const*& in,
char const* last, error_code& ec)
{
@@ -493,17 +428,16 @@ parse_fields(char const*& in,
do_field(f, value, ec);
if(ec)
return;
- impl().on_field_impl(f, name, value, ec);
+ this->on_field_impl(f, name, value, ec);
if(ec)
return;
in = p;
}
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
finish_header(error_code& ec, std::true_type)
{
// RFC 7230 section 3.3
@@ -538,24 +472,25 @@ finish_header(error_code& ec, std::true_type)
else
{
len_ = 0;
+ len0_ = 0;
state_ = state::complete;
}
- impl().on_header_impl(ec);
+ ec = {};
+ this->on_header_impl(ec);
if(ec)
return;
if(state_ == state::complete)
{
- impl().on_finish_impl(ec);
+ this->on_finish_impl(ec);
if(ec)
return;
}
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
finish_header(error_code& ec, std::false_type)
{
// RFC 7230 section 3.3
@@ -600,25 +535,26 @@ finish_header(error_code& ec, std::false_type)
state_ = state::body_to_eof0;
}
- impl().on_header_impl(ec);
+ ec = {};
+ this->on_header_impl(ec);
if(ec)
return;
if(state_ == state::complete)
{
- impl().on_finish_impl(ec);
+ this->on_finish_impl(ec);
if(ec)
return;
}
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_body(char const*& p,
std::size_t n, error_code& ec)
{
- n = impl().on_body_impl(string_view{p,
+ ec = {};
+ n = this->on_body_impl(string_view{p,
beast::detail::clamp(len_, n)}, ec);
p += n;
len_ -= n;
@@ -626,16 +562,15 @@ parse_body(char const*& p,
return;
if(len_ > 0)
return;
- impl().on_finish_impl(ec);
+ this->on_finish_impl(ec);
if(ec)
return;
state_ = state::complete;
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_body_to_eof(char const*& p,
std::size_t n, error_code& ec)
{
@@ -645,15 +580,16 @@ parse_body_to_eof(char const*& p,
return;
}
body_limit_ = body_limit_ - n;
- n = impl().on_body_impl(string_view{p, n}, ec);
+ ec = {};
+ n = this->on_body_impl(string_view{p, n}, ec);
p += n;
if(ec)
return;
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_chunk_header(char const*& p0,
std::size_t n, error_code& ec)
{
@@ -729,7 +665,7 @@ parse_chunk_header(char const*& p0,
return;
}
auto const ext = make_string(start, p);
- impl().on_chunk_header_impl(size, ext, ec);
+ this->on_chunk_header_impl(size, ext, ec);
if(ec)
return;
len_ = size;
@@ -772,7 +708,7 @@ parse_chunk_header(char const*& p0,
return;
}
auto const ext = make_string(start, p);
- impl().on_chunk_header_impl(0, ext, ec);
+ this->on_chunk_header_impl(0, ext, ec);
if(ec)
return;
p = eol;
@@ -782,20 +718,20 @@ parse_chunk_header(char const*& p0,
BOOST_ASSERT(p == eom);
p0 = eom;
- impl().on_finish_impl(ec);
+ this->on_finish_impl(ec);
if(ec)
return;
state_ = state::complete;
}
-template<bool isRequest, class Derived>
-inline
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
parse_chunk_body(char const*& p,
std::size_t n, error_code& ec)
{
- n = impl().on_chunk_body_impl(
+ ec = {};
+ n = this->on_chunk_body_impl(
len_, string_view{p,
beast::detail::clamp(len_, n)}, ec);
p += n;
@@ -804,9 +740,9 @@ parse_chunk_body(char const*& p,
state_ = state::chunk_header;
}
-template<bool isRequest, class Derived>
+template<bool isRequest>
void
-basic_parser<isRequest, Derived>::
+basic_parser<isRequest>::
do_field(field f,
string_view value, error_code& ec)
{
@@ -841,7 +777,7 @@ do_field(field f,
continue;
}
}
- ec.assign(0, ec.category());
+ ec = {};
return;
}
@@ -870,8 +806,9 @@ do_field(field f,
return;
}
- ec.assign(0, ec.category());
+ ec = {};
len_ = v;
+ len0_ = v;
f_ |= flagContentLength;
return;
}
@@ -893,7 +830,7 @@ do_field(field f,
return;
}
- ec.assign(0, ec.category());
+ ec = {};
auto const v = token_list{value};
auto const p = std::find_if(v.begin(), v.end(),
[&](typename token_list::value_type const& s)
@@ -912,14 +849,19 @@ do_field(field f,
// Upgrade
if(f == field::upgrade)
{
- ec.assign(0, ec.category());
+ ec = {};
f_ |= flagUpgrade;
return;
}
- ec.assign(0, ec.category());
+ ec = {};
}
+#ifdef BOOST_BEAST_SOURCE
+template class http::basic_parser<true>;
+template class http::basic_parser<false>;
+#endif
+
} // http
} // beast
} // boost
diff --git a/boost/beast/http/impl/chunk_encode.ipp b/boost/beast/http/impl/chunk_encode.hpp
index 51296041f7..0272e3abb3 100644
--- a/boost/beast/http/impl/chunk_encode.ipp
+++ b/boost/beast/http/impl/chunk_encode.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,9 +7,10 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_IPP
-#define BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_HPP
+#define BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_HPP
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/varint.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/detail/rfc7230.hpp>
@@ -24,7 +25,7 @@ chunk_header::
chunk_header(std::size_t size)
: view_(
size,
- boost::asio::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
chunk_crlf{})
{
BOOST_ASSERT(size > 0);
@@ -37,7 +38,7 @@ chunk_header(
string_view extensions)
: view_(
size,
- boost::asio::const_buffer{
+ net::const_buffer{
extensions.data(), extensions.size()},
chunk_crlf{})
{
@@ -89,8 +90,8 @@ template<class ConstBufferSequence>
chunk_body<ConstBufferSequence>::
chunk_body(ConstBufferSequence const& buffers)
: view_(
- boost::asio::buffer_size(buffers),
- boost::asio::const_buffer{nullptr, 0},
+ buffer_bytes(buffers),
+ net::const_buffer{nullptr, 0},
chunk_crlf{},
buffers,
chunk_crlf{})
@@ -103,8 +104,8 @@ chunk_body(
ConstBufferSequence const& buffers,
string_view extensions)
: view_(
- boost::asio::buffer_size(buffers),
- boost::asio::const_buffer{
+ buffer_bytes(buffers),
+ net::const_buffer{
extensions.data(), extensions.size()},
chunk_crlf{},
buffers,
@@ -122,7 +123,7 @@ chunk_body(
typename std::decay<ChunkExtensions>::type>>(
std::forward<ChunkExtensions>(extensions)))
, view_(
- boost::asio::buffer_size(buffers),
+ buffer_bytes(buffers),
exts_->str(),
chunk_crlf{},
buffers,
@@ -141,7 +142,7 @@ chunk_body(
typename std::decay<ChunkExtensions>::type>>(allocator,
std::forward<ChunkExtensions>(extensions)))
, view_(
- boost::asio::buffer_size(buffers),
+ buffer_bytes(buffers),
exts_->str(),
chunk_crlf{},
buffers,
@@ -387,7 +388,7 @@ do_parse(FwdIt it, FwdIt last, error_code& ec)
loop:
if(it == last)
{
- ec.assign(0, ec.category());
+ ec = {};
return it;
}
// BWS
@@ -680,7 +681,6 @@ insert(string_view name, string_view value)
}
template<class Allocator>
-inline
auto
basic_chunk_extensions<Allocator>::
begin() const ->
@@ -690,7 +690,6 @@ begin() const ->
}
template<class Allocator>
-inline
auto
basic_chunk_extensions<Allocator>::
end() const ->
diff --git a/boost/beast/http/impl/error.hpp b/boost/beast/http/impl/error.hpp
new file mode 100644
index 0000000000..b4efaa05ca
--- /dev/null
+++ b/boost/beast/http/impl/error.hpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016-2019 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_IMPL_ERROR_HPP
+#define BOOST_BEAST_HTTP_IMPL_ERROR_HPP
+
+#include <type_traits>
+
+namespace boost {
+namespace system {
+template<>
+struct is_error_code_enum<::boost::beast::http::error>
+{
+ static bool const value = true;
+};
+} // system
+} // boost
+
+namespace boost {
+namespace beast {
+namespace http {
+
+BOOST_BEAST_DECL
+error_code
+make_error_code(error ev);
+
+} // http
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/http/impl/error.ipp b/boost/beast/http/impl/error.ipp
index b6320cf4c9..e0167b308e 100644
--- a/boost/beast/http/impl/error.ipp
+++ b/boost/beast/http/impl/error.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,18 +10,10 @@
#ifndef BOOST_BEAST_HTTP_IMPL_ERROR_IPP
#define BOOST_BEAST_HTTP_IMPL_ERROR_IPP
+#include <boost/beast/http/error.hpp>
#include <type_traits>
namespace boost {
-
-namespace system {
-template<>
-struct is_error_code_enum<beast::http::error>
-{
- static bool const value = true;
-};
-} // system
-
namespace beast {
namespace http {
namespace detail {
@@ -63,6 +55,7 @@ public:
case error::bad_chunk: return "bad chunk";
case error::bad_chunk_extension: return "bad chunk extension";
case error::bad_obs_fold: return "bad obs-fold";
+ case error::stale_parser: return "stale parser";
default:
return "beast.http error";
@@ -96,7 +89,6 @@ public:
} // detail
-inline
error_code
make_error_code(error ev)
{
diff --git a/boost/beast/http/impl/field.ipp b/boost/beast/http/impl/field.ipp
index b61a0ba8a2..46af6f8552 100644
--- a/boost/beast/http/impl/field.ipp
+++ b/boost/beast/http/impl/field.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,11 +10,10 @@
#ifndef BOOST_BEAST_HTTP_IMPL_FIELD_IPP
#define BOOST_BEAST_HTTP_IMPL_FIELD_IPP
-#include <boost/beast/core/string.hpp>
+#include <boost/beast/http/field.hpp>
#include <algorithm>
#include <array>
-#include <unordered_map>
-#include <vector>
+#include <cstring>
#include <boost/assert.hpp>
namespace boost {
@@ -28,58 +27,66 @@ struct field_table
using array_type =
std::array<string_view, 353>;
- struct hash
+ // Strings are converted to lowercase
+ static
+ std::uint32_t
+ digest(string_view s)
{
- std::size_t
- operator()(string_view s) const
+ std::uint32_t r = 0;
+ std::size_t n = s.size();
+ unsigned char const* p =reinterpret_cast<
+ unsigned char const*>(s.data());
+ while(n >= 4)
{
- auto const n = s.size();
- return
- beast::detail::ascii_tolower(s[0]) *
- beast::detail::ascii_tolower(s[n/2]) ^
- beast::detail::ascii_tolower(s[n-1]); // hist[] = 331, 10, max_load_factor = 0.15f
+ std::uint32_t v;
+ std::memcpy(&v, p, 4);
+ r = r * 5 + ( v | 0x20202020 );
+ p += 4;
+ n -= 4;
}
- };
+ while( n > 0 )
+ {
+ r = r * 5 + ( *p | 0x20 );
+ ++p;
+ --n;
+ }
+ return r;
+ }
- struct iequal
+ // This comparison is case-insensitive, and the
+ // strings must contain only valid http field characters.
+ static
+ bool
+ equals(string_view lhs, string_view rhs)
{
- // assumes inputs have equal length
- bool
- operator()(
- string_view lhs,
- string_view rhs) const
+ using Int = std::uint32_t; // or std::size_t
+ auto n = lhs.size();
+ if(n != rhs.size())
+ return false;
+ auto p1 = lhs.data();
+ auto p2 = rhs.data();
+ auto constexpr S = sizeof(Int);
+ auto constexpr Mask = static_cast<Int>(
+ 0xDFDFDFDFDFDFDFDF & ~Int{0});
+ for(; n >= S; p1 += S, p2 += S, n -= S)
{
- auto p1 = lhs.data();
- auto p2 = rhs.data();
- auto pend = p1 + lhs.size();
- char a, b;
- while(p1 < pend)
- {
- a = *p1++;
- b = *p2++;
- if(a != b)
- goto slow;
- }
- return true;
-
- while(p1 < pend)
- {
- slow:
- if( beast::detail::ascii_tolower(a) !=
- beast::detail::ascii_tolower(b))
- return false;
- a = *p1++;
- b = *p2++;
- }
- return true;
+ Int v1, v2;
+ std::memcpy( &v1, p1, S );
+ std::memcpy( &v2, p2, S );
+ if((v1 ^ v2) & Mask)
+ return false;
}
- };
-
- using map_type = std::unordered_map<
- string_view, field, hash, iequal>;
+ for(; n; ++p1, ++p2, --n)
+ if(( *p1 ^ *p2) & 0xDF)
+ return false;
+ return true;
+ }
array_type by_name_;
- std::vector<map_type> by_size_;
+
+ enum { N = 5155 };
+ unsigned char map_[ N ][ 2 ] = {};
+
/*
From:
@@ -442,58 +449,43 @@ struct field_table
"Xref"
}})
{
- // find the longest field length
- std::size_t high = 0;
- for(auto const& s : by_name_)
- if(high < s.size())
- high = s.size();
- // build by_size map
- // skip field::unknown
- by_size_.resize(high + 1);
- for(auto& map : by_size_)
- map.max_load_factor(.15f);
- for(std::size_t i = 1;
- i < by_name_.size(); ++i)
+ for(std::size_t i = 1, n = 256; i < n; ++i)
{
- auto const& s = by_name_[i];
- by_size_[s.size()].emplace(
- s, static_cast<field>(i));
+ auto sv = by_name_[ i ];
+ auto h = digest(sv);
+ auto j = h % N;
+ BOOST_ASSERT(map_[j][0] == 0);
+ map_[j][0] = static_cast<unsigned char>(i);
}
-#if 0
- // This snippet calculates the performance
- // of the hash function and map settings
+ for(std::size_t i = 256, n = by_name_.size(); i < n; ++i)
{
- std::vector<std::size_t> hist;
- for(auto const& map : by_size_)
- {
- for(std::size_t i = 0; i < map.bucket_count(); ++i)
- {
- auto const n = map.bucket_size(i);
- if(n > 0)
- {
- if(hist.size() < n)
- hist.resize(n);
- ++hist[n-1];
- }
- }
- }
+ auto sv = by_name_[i];
+ auto h = digest(sv);
+ auto j = h % N;
+ BOOST_ASSERT(map_[j][1] == 0);
+ map_[j][1] = static_cast<unsigned char>(i - 255);
}
-#endif
}
field
string_to_field(string_view s) const
{
- if(s.size() >= by_size_.size())
+ auto h = digest(s);
+ auto j = h % N;
+ int i = map_[j][0];
+ string_view s2 = by_name_[i];
+ if(i != 0 && equals(s, s2))
+ return static_cast<field>(i);
+ i = map_[j][1];
+ if(i == 0)
return field::unknown;
- auto const& map = by_size_[s.size()];
- if(map.empty())
- return field::unknown;
- auto it = map.find(s);
- if(it == map.end())
- return field::unknown;
- return it->second;
+ i += 255;
+ s2 = by_name_[i];
+
+ if(equals(s, s2))
+ return static_cast<field>(i);
+ return field::unknown;
}
//
@@ -522,7 +514,7 @@ struct field_table
}
};
-inline
+BOOST_BEAST_DECL
field_table const&
get_field_table()
{
@@ -530,7 +522,7 @@ get_field_table()
return tab;
}
-template<class = void>
+BOOST_BEAST_DECL
string_view
to_string(field f)
{
@@ -541,14 +533,12 @@ to_string(field f)
} // detail
-inline
string_view
to_string(field f)
{
return detail::to_string(f);
}
-inline
field
string_to_field(string_view s)
{
diff --git a/boost/beast/http/impl/fields.ipp b/boost/beast/http/impl/fields.hpp
index f34a8e7471..9616af829c 100644
--- a/boost/beast/http/impl/fields.ipp
+++ b/boost/beast/http/impl/fields.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,13 +7,14 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
-#define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_FIELDS_HPP
+#define BOOST_BEAST_HTTP_IMPL_FIELDS_HPP
#include <boost/beast/core/buffers_cat.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/static_string.hpp>
#include <boost/beast/core/detail/buffers_ref.hpp>
+#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/http/verb.hpp>
#include <boost/beast/http/rfc7230.hpp>
#include <boost/beast/http/status.hpp>
@@ -44,7 +45,7 @@ public:
{
iter_type it_;
- using value_type = boost::asio::const_buffer;
+ using value_type = net::const_buffer;
using pointer = value_type const*;
using reference = value_type const;
using difference_type = std::ptrdiff_t;
@@ -144,9 +145,9 @@ public:
};
using view_type = buffers_cat_view<
- boost::asio::const_buffer,
- boost::asio::const_buffer,
- boost::asio::const_buffer,
+ net::const_buffer,
+ net::const_buffer,
+ net::const_buffer,
field_range,
chunk_crlf>;
@@ -179,9 +180,9 @@ writer(basic_fields const& f)
: f_(f)
{
view_.emplace(
- boost::asio::const_buffer{nullptr, 0},
- boost::asio::const_buffer{nullptr, 0},
- boost::asio::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
field_range(f_.list_.begin(), f_.list_.end()),
chunk_crlf());
}
@@ -219,11 +220,11 @@ writer(basic_fields const& f,
buf_[10]= '\n';
view_.emplace(
- boost::asio::const_buffer{sv.data(), sv.size()},
- boost::asio::const_buffer{
+ net::const_buffer{sv.data(), sv.size()},
+ net::const_buffer{
f_.target_or_reason_.data(),
f_.target_or_reason_.size()},
- boost::asio::const_buffer{buf_, 11},
+ net::const_buffer{buf_, 11},
field_range(f_.list_.begin(), f_.list_.end()),
chunk_crlf());
}
@@ -261,9 +262,9 @@ writer(basic_fields const& f,
sv = obsolete_reason(static_cast<status>(code));
view_.emplace(
- boost::asio::const_buffer{buf_, 13},
- boost::asio::const_buffer{sv.data(), sv.size()},
- boost::asio::const_buffer{"\r\n", 2},
+ net::const_buffer{buf_, 13},
+ net::const_buffer{sv.data(), sv.size()},
+ net::const_buffer{"\r\n", 2},
field_range(f_.list_.begin(), f_.list_.end()),
chunk_crlf{});
}
@@ -282,12 +283,12 @@ data() const
}
template<class Allocator>
-boost::asio::const_buffer
+net::const_buffer
basic_fields<Allocator>::
value_type::
buffer() const
{
- return boost::asio::const_buffer{data(),
+ return net::const_buffer{data(),
static_cast<std::size_t>(off_) + len_ + 2};
}
@@ -1018,7 +1019,8 @@ set_chunked_impl(bool value)
itt = next;
}
static_string<max_static_buffer> buf;
- if(it->value().size() <= buf.size() + 9)
+ if(! beast::detail::sum_exceeds(
+ it->value().size(), 9u, buf.max_size()))
{
buf.append(it->value().data(), it->value().size());
buf.append(", chunked", 9);
@@ -1048,6 +1050,7 @@ set_chunked_impl(bool value)
// filter "chunked"
if(it == end())
return;
+#ifndef BOOST_NO_EXCEPTIONS
try
{
static_string<max_static_buffer> buf;
@@ -1062,6 +1065,7 @@ set_chunked_impl(bool value)
erase(field::transfer_encoding);
}
catch(std::length_error const&)
+#endif
{
#ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
@@ -1108,6 +1112,7 @@ set_keep_alive_impl(
{
// VFALCO What about Proxy-Connection ?
auto const value = (*this)[field::connection];
+#ifndef BOOST_NO_EXCEPTIONS
try
{
static_string<max_static_buffer> buf;
@@ -1119,6 +1124,7 @@ set_keep_alive_impl(
set(field::connection, buf);
}
catch(std::length_error const&)
+#endif
{
#ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
@@ -1168,7 +1174,7 @@ new_element(field name,
auto const p = alloc_traits::allocate(a,
(sizeof(element) + off + len + 2 + sizeof(align_type) - 1) /
sizeof(align_type));
- return *(new(p) element(name, sname, value));
+ return *(::new(p) element(name, sname, value));
}
template<class Allocator>
diff --git a/boost/beast/http/impl/file_body_win32.ipp b/boost/beast/http/impl/file_body_win32.hpp
index 6357cf4983..fc74c49772 100644
--- a/boost/beast/http/impl/file_body_win32.ipp
+++ b/boost/beast/http/impl/file_body_win32.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,22 +7,18 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_IPP
-#define BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_HPP
+#define BOOST_BEAST_HTTP_IMPL_FILE_BODY_WIN32_HPP
#if BOOST_BEAST_USE_WIN32_FILE
+#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/bind_handler.hpp>
-#include <boost/beast/core/type_traits.hpp>
+#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/http/serializer.hpp>
-#include <boost/asio/associated_allocator.hpp>
-#include <boost/asio/associated_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_stream_socket.hpp>
-#include <boost/asio/executor_work_guard.hpp>
-#include <boost/asio/handler_continuation_hook.hpp>
-#include <boost/asio/handler_invoke_hook.hpp>
#include <boost/asio/windows/overlapped_ptr.hpp>
#include <boost/make_unique.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
@@ -36,7 +32,7 @@ namespace beast {
namespace http {
namespace detail {
-template<class, class, bool, class>
+template<class, class, bool, class, class>
class write_some_win32_op;
} // detail
@@ -56,14 +52,15 @@ struct basic_file_body<file_win32>
friend class reader;
friend struct basic_file_body<file_win32>;
- template<class, class, bool, class>
+ template<class, class, bool, class, class>
friend class detail::write_some_win32_op;
template<
- class Protocol, bool isRequest, class Fields>
+ class Protocol, class Executor,
+ bool isRequest, class Fields>
friend
std::size_t
write_some(
- boost::asio::basic_stream_socket<Protocol>& sock,
+ net::basic_stream_socket<Protocol, Executor>& sock,
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr,
error_code& ec);
@@ -105,14 +102,15 @@ struct basic_file_body<file_win32>
class writer
{
- template<class, class, bool, class>
+ template<class, class, bool, class, class>
friend class detail::write_some_win32_op;
template<
- class Protocol, bool isRequest, class Fields>
+ class Protocol, class Executor,
+ bool isRequest, class Fields>
friend
std::size_t
write_some(
- boost::asio::basic_stream_socket<Protocol>& sock,
+ net::basic_stream_socket<Protocol, Executor>& sock,
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr,
error_code& ec);
@@ -123,7 +121,7 @@ struct basic_file_body<file_win32>
public:
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
writer(header<isRequest, Fields>&, value_type& b)
@@ -145,7 +143,7 @@ struct basic_file_body<file_win32>
beast::detail::clamp(body_.last_ - pos_));
if(n == 0)
{
- ec.assign(0, ec.category());
+ ec = {};
return boost::none;
}
auto const nread = body_.file_.read(buf_, n, ec);
@@ -153,7 +151,7 @@ struct basic_file_body<file_win32>
return boost::none;
BOOST_ASSERT(nread != 0);
pos_ += nread;
- ec.assign(0, ec.category());
+ ec = {};
return {{
{buf_, nread}, // buffer to return.
pos_ < body_.last_}}; // `true` if there are more buffers.
@@ -182,7 +180,7 @@ struct basic_file_body<file_win32>
// VFALCO We could reserve space in the file
boost::ignore_unused(content_length);
BOOST_ASSERT(body_.file_.is_open());
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -191,21 +189,21 @@ struct basic_file_body<file_win32>
error_code& ec)
{
std::size_t nwritten = 0;
- for(auto buffer : beast::detail::buffers_range(buffers))
+ for(auto buffer : beast::buffers_range_ref(buffers))
{
nwritten += body_.file_.write(
buffer.data(), buffer.size(), ec);
if(ec)
return nwritten;
}
- ec.assign(0, ec.category());
+ ec = {};
return nwritten;
}
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
@@ -280,7 +278,6 @@ reset(file_win32&& file, error_code& ec)
namespace detail {
template<class Unsigned>
-inline
boost::winapi::DWORD_
lowPart(Unsigned n)
{
@@ -290,7 +287,6 @@ lowPart(Unsigned n)
}
template<class Unsigned>
-inline
boost::winapi::DWORD_
highPart(Unsigned n, std::true_type)
{
@@ -300,7 +296,6 @@ highPart(Unsigned n, std::true_type)
}
template<class Unsigned>
-inline
boost::winapi::DWORD_
highPart(Unsigned, std::false_type)
{
@@ -308,7 +303,6 @@ highPart(Unsigned, std::false_type)
}
template<class Unsigned>
-inline
boost::winapi::DWORD_
highPart(Unsigned n)
{
@@ -333,165 +327,144 @@ public:
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
template<
- class Protocol, class Handler,
- bool isRequest, class Fields>
+ class Protocol, class Executor,
+ bool isRequest, class Fields,
+ class Handler>
class write_some_win32_op
+ : public beast::async_base<Handler, Executor>
{
- boost::asio::basic_stream_socket<Protocol>& sock_;
- boost::asio::executor_work_guard<decltype(std::declval<
- boost::asio::basic_stream_socket<Protocol>&>().get_executor())> wg_;
+ net::basic_stream_socket<
+ Protocol, Executor>& sock_;
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr_;
std::size_t bytes_transferred_ = 0;
- Handler h_;
bool header_ = false;
public:
- write_some_win32_op(write_some_win32_op&&) = default;
- write_some_win32_op(write_some_win32_op const&) = delete;
-
- template<class DeducedHandler>
+ template<class Handler_>
write_some_win32_op(
- DeducedHandler&& h,
- boost::asio::basic_stream_socket<Protocol>& s,
+ Handler_&& h,
+ net::basic_stream_socket<
+ Protocol, Executor>& s,
serializer<isRequest,
basic_file_body<file_win32>,Fields>& sr)
- : sock_(s)
- , wg_(sock_.get_executor())
+ : async_base<
+ Handler, Executor>(
+ std::forward<Handler_>(h),
+ s.get_executor())
+ , sock_(s)
, sr_(sr)
- , h_(std::forward<DeducedHandler>(h))
- {
- }
-
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
{
- return (boost::asio::get_associated_allocator)(h_);
+ (*this)();
}
- using executor_type =
- boost::asio::associated_executor_t<Handler, decltype(std::declval<
- boost::asio::basic_stream_socket<Protocol>&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
+ void
+ operator()()
{
- return (boost::asio::get_associated_executor)(
- h_, sock_.get_executor());
+ if(! sr_.is_header_done())
+ {
+ header_ = true;
+ sr_.split(true);
+ return detail::async_write_some_impl(
+ sock_, sr_, std::move(*this));
+ }
+ if(sr_.get().chunked())
+ {
+ return detail::async_write_some_impl(
+ sock_, sr_, std::move(*this));
+ }
+ auto& w = sr_.writer_impl();
+ boost::winapi::DWORD_ const nNumberOfBytesToWrite =
+ static_cast<boost::winapi::DWORD_>(
+ (std::min<std::uint64_t>)(
+ (std::min<std::uint64_t>)(w.body_.last_ - w.pos_, sr_.limit()),
+ (std::numeric_limits<boost::winapi::DWORD_>::max)()));
+ net::windows::overlapped_ptr overlapped{
+ sock_.get_executor(), std::move(*this)};
+ // Note that we have moved *this, so we cannot access
+ // the handler since it is now moved-from. We can still
+ // access simple things like references and built-in types.
+ auto& ov = *overlapped.get();
+ ov.Offset = lowPart(w.pos_);
+ ov.OffsetHigh = highPart(w.pos_);
+ auto const bSuccess = ::TransmitFile(
+ sock_.native_handle(),
+ sr_.get().body().file_.native_handle(),
+ nNumberOfBytesToWrite,
+ 0,
+ overlapped.get(),
+ nullptr,
+ 0);
+ auto const dwError = boost::winapi::GetLastError();
+ if(! bSuccess && dwError !=
+ boost::winapi::ERROR_IO_PENDING_)
+ {
+ // VFALCO This needs review, is 0 the right number?
+ // completed immediately (with error?)
+ overlapped.complete(error_code{static_cast<int>(dwError),
+ system_category()}, 0);
+ return;
+ }
+ overlapped.release();
}
void
- operator()();
-
- void
operator()(
error_code ec,
- std::size_t bytes_transferred = 0);
-
- friend
- bool asio_handler_is_continuation(write_some_win32_op* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- std::addressof(op->h_));
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, write_some_win32_op* op)
+ std::size_t bytes_transferred = 0)
{
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
+ bytes_transferred_ += bytes_transferred;
+ if(! ec)
+ {
+ if(header_)
+ {
+ header_ = false;
+ return (*this)();
+ }
+ auto& w = sr_.writer_impl();
+ w.pos_ += bytes_transferred;
+ BOOST_ASSERT(w.pos_ <= w.body_.last_);
+ if(w.pos_ >= w.body_.last_)
+ {
+ sr_.next(ec, null_lambda{});
+ BOOST_ASSERT(! ec);
+ BOOST_ASSERT(sr_.is_done());
+ }
+ }
+ this->complete_now(ec, bytes_transferred_);
}
};
-template<
- class Protocol, class Handler,
- bool isRequest, class Fields>
-void
-write_some_win32_op<
- Protocol, Handler, isRequest, Fields>::
-operator()()
+struct run_write_some_win32_op
{
- if(! sr_.is_header_done())
- {
- header_ = true;
- sr_.split(true);
- return detail::async_write_some_impl(
- sock_, sr_, std::move(*this));
- }
- if(sr_.get().chunked())
- {
- return detail::async_write_some_impl(
- sock_, sr_, std::move(*this));
- }
- auto& w = sr_.writer_impl();
- boost::winapi::DWORD_ const nNumberOfBytesToWrite =
- static_cast<boost::winapi::DWORD_>(
- (std::min<std::uint64_t>)(
- (std::min<std::uint64_t>)(w.body_.last_ - w.pos_, sr_.limit()),
- (std::numeric_limits<boost::winapi::DWORD_>::max)()));
- boost::asio::windows::overlapped_ptr overlapped{
- sock_.get_executor().context(), std::move(*this)};
- // Note that we have moved *this, so we cannot access
- // the handler since it is now moved-from. We can still
- // access simple things like references and built-in types.
- auto& ov = *overlapped.get();
- ov.Offset = lowPart(w.pos_);
- ov.OffsetHigh = highPart(w.pos_);
- auto const bSuccess = ::TransmitFile(
- sock_.native_handle(),
- sr_.get().body().file_.native_handle(),
- nNumberOfBytesToWrite,
- 0,
- overlapped.get(),
- nullptr,
- 0);
- auto const dwError = boost::winapi::GetLastError();
- if(! bSuccess && dwError !=
- boost::winapi::ERROR_IO_PENDING_)
- {
- // VFALCO This needs review, is 0 the right number?
- // completed immediately (with error?)
- overlapped.complete(error_code{static_cast<int>(dwError),
- system_category()}, 0);
- return;
- }
- overlapped.release();
-}
-
-template<
- class Protocol, class Handler,
- bool isRequest, class Fields>
-void
-write_some_win32_op<
- Protocol, Handler, isRequest, Fields>::
-operator()(
- error_code ec, std::size_t bytes_transferred)
-{
- bytes_transferred_ += bytes_transferred;
- if(! ec)
+ template<
+ class Protocol, class Executor,
+ bool isRequest, class Fields,
+ class WriteHandler>
+ void
+ operator()(
+ WriteHandler&& h,
+ net::basic_stream_socket<
+ Protocol, Executor>* s,
+ serializer<isRequest,
+ basic_file_body<file_win32>, Fields>* sr)
{
- if(header_)
- {
- header_ = false;
- return (*this)();
- }
- auto& w = sr_.writer_impl();
- w.pos_ += bytes_transferred;
- BOOST_ASSERT(w.pos_ <= w.body_.last_);
- if(w.pos_ >= w.body_.last_)
- {
- sr_.next(ec, null_lambda{});
- BOOST_ASSERT(! ec);
- BOOST_ASSERT(sr_.is_done());
- }
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_some_win32_op<
+ Protocol, Executor,
+ isRequest, Fields,
+ typename std::decay<WriteHandler>::type>(
+ std::forward<WriteHandler>(h), *s, *sr);
}
- h_(ec, bytes_transferred_);
-}
+};
#endif
@@ -499,10 +472,13 @@ operator()(
//------------------------------------------------------------------------------
-template<class Protocol, bool isRequest, class Fields>
+template<
+ class Protocol, class Executor,
+ bool isRequest, class Fields>
std::size_t
write_some(
- boost::asio::basic_stream_socket<Protocol>& sock,
+ net::basic_stream_socket<
+ Protocol, Executor>& sock,
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr,
error_code& ec)
@@ -552,7 +528,7 @@ write_some(
BOOST_ASSERT(w.pos_ <= w.body_.last_);
if(w.pos_ < w.body_.last_)
{
- ec.assign(0, ec.category());
+ ec = {};
}
else
{
@@ -566,26 +542,24 @@ write_some(
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
template<
- class Protocol,
+ class Protocol, class Executor,
bool isRequest, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_some(
- boost::asio::basic_stream_socket<Protocol>& sock,
+ net::basic_stream_socket<
+ Protocol, Executor>& sock,
serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr,
WriteHandler&& handler)
-{
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_some_win32_op<
- Protocol,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- isRequest, Fields>{
- std::move(init.completion_handler), sock, sr}();
- return init.result.get();
+{
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ detail::run_write_some_win32_op{},
+ handler,
+ &sock,
+ &sr);
}
#endif
diff --git a/boost/beast/http/impl/message.ipp b/boost/beast/http/impl/message.hpp
index a2a10402f9..805d01f09a 100644
--- a/boost/beast/http/impl/message.ipp
+++ b/boost/beast/http/impl/message.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,8 +7,8 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_MESSAGE_IPP
-#define BOOST_BEAST_HTTP_IMPL_MESSAGE_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP
+#define BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
@@ -30,7 +30,6 @@ header(Arg1&& arg1, ArgN&&... argn)
}
template<class Fields>
-inline
verb
header<true, Fields>::
method() const
@@ -73,7 +72,6 @@ method_string(string_view s)
}
template<class Fields>
-inline
string_view
header<true, Fields>::
target() const
@@ -82,7 +80,6 @@ target() const
}
template<class Fields>
-inline
void
header<true, Fields>::
target(string_view s)
@@ -116,7 +113,6 @@ header(Arg1&& arg1, ArgN&&... argn)
}
template<class Fields>
-inline
status
header<false, Fields>::
result() const
@@ -126,7 +122,6 @@ result() const
}
template<class Fields>
-inline
void
header<false, Fields>::
result(status v)
@@ -135,7 +130,6 @@ result(status v)
}
template<class Fields>
-inline
void
header<false, Fields>::
result(unsigned v)
@@ -148,7 +142,6 @@ result(unsigned v)
}
template<class Fields>
-inline
unsigned
header<false, Fields>::
result_int() const
@@ -168,7 +161,6 @@ reason() const
}
template<class Fields>
-inline
void
header<false, Fields>::
reason(string_view s)
@@ -295,7 +287,7 @@ message(std::piecewise_construct_t,
std::tuple<BodyArgs...> body_args)
: message(std::piecewise_construct,
body_args,
- beast::detail::make_index_sequence<
+ mp11::make_index_sequence<
sizeof...(BodyArgs)>{})
{
}
@@ -309,9 +301,9 @@ message(std::piecewise_construct_t,
: message(std::piecewise_construct,
body_args,
fields_args,
- beast::detail::make_index_sequence<
+ mp11::make_index_sequence<
sizeof...(BodyArgs)>{},
- beast::detail::make_index_sequence<
+ mp11::make_index_sequence<
sizeof...(FieldsArgs)>{})
{
}
diff --git a/boost/beast/http/impl/parser.ipp b/boost/beast/http/impl/parser.hpp
index 45bef1c6ac..066ac5fea1 100644
--- a/boost/beast/http/impl/parser.ipp
+++ b/boost/beast/http/impl/parser.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,8 +7,8 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_PARSER_IPP
-#define BOOST_BEAST_HTTP_IMPL_PARSER_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_PARSER_HPP
+#define BOOST_BEAST_HTTP_IMPL_PARSER_HPP
#include <boost/throw_exception.hpp>
#include <stdexcept>
@@ -42,7 +42,7 @@ parser<isRequest, Body, Allocator>::
parser(
parser<isRequest, OtherBody, Allocator>&& other,
Args&&... args)
- : base_type(std::move(other))
+ : basic_parser<isRequest>(std::move(other))
, m_(other.release(), std::forward<Args>(args)...)
, rd_(m_.base(), m_.body())
{
diff --git a/boost/beast/http/impl/read.hpp b/boost/beast/http/impl/read.hpp
new file mode 100644
index 0000000000..faea67eb25
--- /dev/null
+++ b/boost/beast/http/impl/read.hpp
@@ -0,0 +1,559 @@
+//
+// Copyright (c) 2016-2019 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_IMPL_READ_HPP
+#define BOOST_BEAST_HTTP_IMPL_READ_HPP
+
+#include <boost/beast/http/type_traits.hpp>
+#include <boost/beast/http/error.hpp>
+#include <boost/beast/http/parser.hpp>
+#include <boost/beast/http/read.hpp>
+#include <boost/beast/core/async_base.hpp>
+#include <boost/beast/core/stream_traits.hpp>
+#include <boost/beast/core/detail/read.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace beast {
+namespace http {
+
+namespace detail {
+
+// The default maximum number of bytes to transfer in a single operation.
+std::size_t constexpr default_max_transfer_size = 65536;
+
+template<
+ class DynamicBuffer,
+ bool isRequest,
+ class Condition>
+std::size_t
+parse_until(
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ error_code& ec,
+ Condition cond)
+{
+ if(ec == net::error::eof)
+ {
+ if(parser.got_some())
+ {
+ // Caller sees EOF on next read
+ ec = {};
+ parser.put_eof(ec);
+ BOOST_ASSERT(ec || parser.is_done());
+ }
+ else
+ {
+ ec = error::end_of_stream;
+ }
+ return 0;
+ }
+ if(ec)
+ {
+ // Upgrade the error if we have a partial message.
+ // This causes SSL short reads (and every other error)
+ // to be converted into something else, allowing the
+ // caller to distinguish an SSL short read which
+ // represents a safe connection closure, versus
+ // a closure with data loss.
+ if(parser.got_some() && ! parser.is_done())
+ ec = error::partial_message;
+ return 0;
+ }
+ if(parser.is_done())
+ return 0;
+ if(buffer.size() > 0)
+ {
+ auto const bytes_used =
+ parser.put(buffer.data(), ec);
+ // total = total + bytes_used; // VFALCO Can't do this in a condition
+ buffer.consume(bytes_used);
+ if(ec == http::error::need_more)
+ {
+ if(buffer.size() >= buffer.max_size())
+ {
+ ec = http::error::buffer_overflow;
+ return 0;
+ }
+ ec = {};
+ }
+ else if(ec || cond())
+ {
+ return 0;
+ }
+ }
+ return default_max_transfer_size;
+}
+
+// predicate is true on any forward parser progress
+template<bool isRequest>
+struct read_some_condition
+{
+ basic_parser<isRequest>& parser;
+
+ template<class DynamicBuffer>
+ std::size_t
+ operator()(error_code& ec, std::size_t,
+ DynamicBuffer& buffer)
+ {
+ return detail::parse_until(
+ buffer, parser, ec,
+ []
+ {
+ return true;
+ });
+ }
+};
+
+// predicate is true when parser header is complete
+template<bool isRequest>
+struct read_header_condition
+{
+ basic_parser<isRequest>& parser;
+
+ template<class DynamicBuffer>
+ std::size_t
+ operator()(error_code& ec, std::size_t,
+ DynamicBuffer& buffer)
+ {
+ return detail::parse_until(
+ buffer, parser, ec,
+ [this]
+ {
+ return parser.is_header_done();
+ });
+ }
+};
+
+// predicate is true when parser message is complete
+template<bool isRequest>
+struct read_all_condition
+{
+ basic_parser<isRequest>& parser;
+
+ template<class DynamicBuffer>
+ std::size_t
+ operator()(error_code& ec, std::size_t,
+ DynamicBuffer& buffer)
+ {
+ return detail::parse_until(
+ buffer, parser, ec,
+ [this]
+ {
+ return parser.is_done();
+ });
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template<
+ class Stream, class DynamicBuffer,
+ bool isRequest, class Body, class Allocator,
+ class Handler>
+class read_msg_op
+ : public beast::stable_async_base<
+ Handler, beast::executor_type<Stream>>
+ , public net::coroutine
+{
+ using parser_type =
+ parser<isRequest, Body, Allocator>;
+
+ using message_type =
+ typename parser_type::value_type;
+
+ struct data
+ {
+ Stream& s;
+ message_type& m;
+ parser_type p;
+
+ data(
+ Stream& s_,
+ message_type& m_)
+ : s(s_)
+ , m(m_)
+ , p(std::move(m))
+ {
+ }
+ };
+
+ data& d_;
+
+public:
+ template<class Handler_>
+ read_msg_op(
+ Handler_&& h,
+ Stream& s,
+ DynamicBuffer& b,
+ message_type& m)
+ : stable_async_base<
+ Handler, beast::executor_type<Stream>>(
+ std::forward<Handler_>(h), s.get_executor())
+ , d_(beast::allocate_stable<data>(
+ *this, s, m))
+ {
+ http::async_read(d_.s, b, d_.p, std::move(*this));
+ }
+
+ void
+ operator()(
+ error_code ec,
+ std::size_t bytes_transferred)
+ {
+ if(! ec)
+ d_.m = d_.p.release();
+ this->complete_now(ec, bytes_transferred);
+ }
+};
+
+struct run_read_msg_op
+{
+ template<
+ class ReadHandler,
+ class AsyncReadStream,
+ class DynamicBuffer,
+ bool isRequest, class Body, class Allocator>
+ void
+ operator()(
+ ReadHandler&& h,
+ AsyncReadStream* s,
+ DynamicBuffer* b,
+ message<isRequest, Body,
+ basic_fields<Allocator>>* m)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<ReadHandler,
+ void(error_code, std::size_t)>::value,
+ "ReadHandler type requirements not met");
+
+ read_msg_op<
+ AsyncReadStream,
+ DynamicBuffer,
+ isRequest, Body, Allocator,
+ typename std::decay<ReadHandler>::type>(
+ std::forward<ReadHandler>(h), *s, *b, *m);
+ }
+};
+
+} // detail
+
+//------------------------------------------------------------------------------
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read_some(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ error_code ec;
+ auto const bytes_transferred =
+ http::read_some(stream, buffer, parser, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(system_error{ec});
+ return bytes_transferred;
+}
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read_some(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ error_code& ec)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ return beast::detail::read(stream, buffer,
+ detail::read_some_condition<
+ isRequest>{parser}, ec);
+}
+
+template<
+ class AsyncReadStream,
+ class DynamicBuffer,
+ bool isRequest,
+ class ReadHandler>
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+async_read_some(
+ AsyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ ReadHandler&& handler)
+{
+ return beast::detail::async_read(
+ stream,
+ buffer,
+ detail::read_some_condition<
+ isRequest>{parser},
+ std::forward<ReadHandler>(handler));
+}
+
+//------------------------------------------------------------------------------
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read_header(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ error_code ec;
+ auto const bytes_transferred =
+ http::read_header(stream, buffer, parser, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(system_error{ec});
+ return bytes_transferred;
+}
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read_header(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ error_code& ec)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ parser.eager(false);
+ return beast::detail::read(stream, buffer,
+ detail::read_header_condition<
+ isRequest>{parser}, ec);
+}
+
+template<
+ class AsyncReadStream,
+ class DynamicBuffer,
+ bool isRequest,
+ class ReadHandler>
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+async_read_header(
+ AsyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ ReadHandler&& handler)
+{
+ parser.eager(false);
+ return beast::detail::async_read(
+ stream,
+ buffer,
+ detail::read_header_condition<
+ isRequest>{parser},
+ std::forward<ReadHandler>(handler));
+}
+
+//------------------------------------------------------------------------------
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ error_code ec;
+ auto const bytes_transferred =
+ http::read(stream, buffer, parser, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(system_error{ec});
+ return bytes_transferred;
+}
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest>
+std::size_t
+read(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ error_code& ec)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ parser.eager(true);
+ return beast::detail::read(stream, buffer,
+ detail::read_all_condition<
+ isRequest>{parser}, ec);
+}
+
+template<
+ class AsyncReadStream,
+ class DynamicBuffer,
+ bool isRequest,
+ class ReadHandler>
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+async_read(
+ AsyncReadStream& stream,
+ DynamicBuffer& buffer,
+ basic_parser<isRequest>& parser,
+ ReadHandler&& handler)
+{
+ static_assert(
+ is_async_read_stream<AsyncReadStream>::value,
+ "AsyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ parser.eager(true);
+ return beast::detail::async_read(
+ stream,
+ buffer,
+ detail::read_all_condition<
+ isRequest>{parser},
+ std::forward<ReadHandler>(handler));
+}
+
+//------------------------------------------------------------------------------
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest, class Body, class Allocator>
+std::size_t
+read(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ message<isRequest, Body, basic_fields<Allocator>>& msg)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ static_assert(is_body<Body>::value,
+ "Body type requirements not met");
+ static_assert(is_body_reader<Body>::value,
+ "BodyReader type requirements not met");
+ error_code ec;
+ auto const bytes_transferred =
+ http::read(stream, buffer, msg, ec);
+ if(ec)
+ BOOST_THROW_EXCEPTION(system_error{ec});
+ return bytes_transferred;
+}
+
+template<
+ class SyncReadStream,
+ class DynamicBuffer,
+ bool isRequest, class Body, class Allocator>
+std::size_t
+read(
+ SyncReadStream& stream,
+ DynamicBuffer& buffer,
+ message<isRequest, Body, basic_fields<Allocator>>& msg,
+ error_code& ec)
+{
+ static_assert(
+ is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ static_assert(is_body<Body>::value,
+ "Body type requirements not met");
+ static_assert(is_body_reader<Body>::value,
+ "BodyReader type requirements not met");
+ parser<isRequest, Body, Allocator> p(std::move(msg));
+ p.eager(true);
+ auto const bytes_transferred =
+ http::read(stream, buffer, p, ec);
+ if(ec)
+ return bytes_transferred;
+ msg = p.release();
+ return bytes_transferred;
+}
+
+template<
+ class AsyncReadStream,
+ class DynamicBuffer,
+ bool isRequest, class Body, class Allocator,
+ class ReadHandler>
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
+async_read(
+ AsyncReadStream& stream,
+ DynamicBuffer& buffer,
+ message<isRequest, Body, basic_fields<Allocator>>& msg,
+ ReadHandler&& handler)
+{
+ static_assert(
+ is_async_read_stream<AsyncReadStream>::value,
+ "AsyncReadStream type requirements not met");
+ static_assert(
+ net::is_dynamic_buffer<DynamicBuffer>::value,
+ "DynamicBuffer type requirements not met");
+ static_assert(is_body<Body>::value,
+ "Body type requirements not met");
+ static_assert(is_body_reader<Body>::value,
+ "BodyReader type requirements not met");
+ return net::async_initiate<
+ ReadHandler,
+ void(error_code, std::size_t)>(
+ detail::run_read_msg_op{},
+ handler, &stream, &buffer, &msg);
+}
+
+} // http
+} // beast
+} // boost
+
+#endif
diff --git a/boost/beast/http/impl/read.ipp b/boost/beast/http/impl/read.ipp
deleted file mode 100644
index 42ce175d8c..0000000000
--- a/boost/beast/http/impl/read.ipp
+++ /dev/null
@@ -1,857 +0,0 @@
-//
-// 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_IMPL_READ_IPP_HPP
-#define BOOST_BEAST_HTTP_IMPL_READ_IPP_HPP
-
-#include <boost/beast/http/type_traits.hpp>
-#include <boost/beast/http/error.hpp>
-#include <boost/beast/http/parser.hpp>
-#include <boost/beast/http/read.hpp>
-#include <boost/beast/core/bind_handler.hpp>
-#include <boost/beast/core/handler_ptr.hpp>
-#include <boost/beast/core/read_size.hpp>
-#include <boost/beast/core/type_traits.hpp>
-#include <boost/beast/core/detail/buffer.hpp>
-#include <boost/asio/associated_allocator.hpp>
-#include <boost/asio/associated_executor.hpp>
-#include <boost/asio/coroutine.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/executor_work_guard.hpp>
-#include <boost/asio/handler_continuation_hook.hpp>
-#include <boost/asio/handler_invoke_hook.hpp>
-#include <boost/asio/post.hpp>
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/optional.hpp>
-#include <boost/throw_exception.hpp>
-
-namespace boost {
-namespace beast {
-namespace http {
-
-namespace detail {
-
-//------------------------------------------------------------------------------
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Derived, class Handler>
-class read_some_op
- : public boost::asio::coroutine
-{
- Stream& s_;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg_;
- DynamicBuffer& b_;
- basic_parser<isRequest, Derived>& p_;
- std::size_t bytes_transferred_ = 0;
- Handler h_;
- bool cont_ = false;
-
-public:
- read_some_op(read_some_op&&) = default;
- read_some_op(read_some_op const&) = delete;
-
- template<class DeducedHandler>
- read_some_op(DeducedHandler&& h, Stream& s,
- DynamicBuffer& b, basic_parser<isRequest, Derived>& p)
- : s_(s)
- , wg_(s_.get_executor())
- , b_(b)
- , p_(p)
- , h_(std::forward<DeducedHandler>(h))
- {
- }
-
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
- {
- return (boost::asio::get_associated_allocator)(h_);
- }
-
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
- {
- return (boost::asio::get_associated_executor)(
- h_, s_.get_executor());
- }
-
- void
- operator()(
- error_code ec,
- std::size_t bytes_transferred = 0,
- bool cont = true);
-
- friend
- bool asio_handler_is_continuation(read_some_op* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return op->cont_ ? true :
- asio_handler_is_continuation(
- std::addressof(op->h_));
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, read_some_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
- }
-};
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Derived, class Handler>
-void
-read_some_op<Stream, DynamicBuffer,
- isRequest, Derived, Handler>::
-operator()(
- error_code ec,
- std::size_t bytes_transferred,
- bool cont)
-{
- cont_ = cont;
- BOOST_ASIO_CORO_REENTER(*this)
- {
- if(b_.size() == 0)
- goto do_read;
- for(;;)
- {
- // parse
- {
- auto const used = p_.put(b_.data(), ec);
- bytes_transferred_ += used;
- b_.consume(used);
- }
- if(ec != http::error::need_more)
- break;
-
- do_read:
- BOOST_ASIO_CORO_YIELD
- {
- // VFALCO This was read_size_or_throw
- auto const size = read_size(b_, 65536);
- if(size == 0)
- {
- ec = error::buffer_overflow;
- goto upcall;
- }
- auto const mb =
- beast::detail::dynamic_buffer_prepare(
- b_, size, ec, error::buffer_overflow);
- if(ec)
- goto upcall;
- s_.async_read_some(*mb, std::move(*this));
- }
- if(ec == boost::asio::error::eof)
- {
- BOOST_ASSERT(bytes_transferred == 0);
- if(p_.got_some())
- {
- // caller sees EOF on next read
- ec.assign(0, ec.category());
- p_.put_eof(ec);
- if(ec)
- goto upcall;
- BOOST_ASSERT(p_.is_done());
- goto upcall;
- }
- ec = error::end_of_stream;
- break;
- }
- if(ec)
- break;
- b_.commit(bytes_transferred);
- }
-
- upcall:
- if(! cont_)
- {
- BOOST_ASIO_CORO_YIELD
- boost::asio::post(
- s_.get_executor(),
- bind_handler(std::move(*this),
- ec, bytes_transferred_));
- }
- h_(ec, bytes_transferred_);
- }
-}
-
-//------------------------------------------------------------------------------
-
-struct parser_is_done
-{
- template<bool isRequest, class Derived>
- bool
- operator()(basic_parser<
- isRequest, Derived> const& p) const
- {
- return p.is_done();
- }
-};
-
-struct parser_is_header_done
-{
- template<bool isRequest, class Derived>
- bool
- operator()(basic_parser<
- isRequest, Derived> const& p) const
- {
- return p.is_header_done();
- }
-};
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Derived, class Condition,
- class Handler>
-class read_op
- : public boost::asio::coroutine
-{
- Stream& s_;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg_;
- DynamicBuffer& b_;
- basic_parser<isRequest, Derived>& p_;
- std::size_t bytes_transferred_ = 0;
- Handler h_;
- bool cont_ = false;
-
-public:
- read_op(read_op&&) = default;
- read_op(read_op const&) = delete;
-
- template<class DeducedHandler>
- read_op(DeducedHandler&& h, Stream& s,
- DynamicBuffer& b, basic_parser<isRequest,
- Derived>& p)
- : s_(s)
- , wg_(s_.get_executor())
- , b_(b)
- , p_(p)
- , h_(std::forward<DeducedHandler>(h))
- {
- }
-
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
- {
- return (boost::asio::get_associated_allocator)(h_);
- }
-
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
- {
- return (boost::asio::get_associated_executor)(
- h_, s_.get_executor());
- }
-
- void
- operator()(
- error_code ec,
- std::size_t bytes_transferred = 0,
- bool cont = true);
-
- friend
- bool asio_handler_is_continuation(read_op* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return op->cont_ ? true :
- asio_handler_is_continuation(
- std::addressof(op->h_));
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, read_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
- }
-};
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Derived, class Condition,
- class Handler>
-void
-read_op<Stream, DynamicBuffer,
- isRequest, Derived, Condition, Handler>::
-operator()(
- error_code ec,
- std::size_t bytes_transferred,
- bool cont)
-{
- cont_ = cont;
- BOOST_ASIO_CORO_REENTER(*this)
- {
- if(Condition{}(p_))
- {
- BOOST_ASIO_CORO_YIELD
- boost::asio::post(s_.get_executor(),
- bind_handler(std::move(*this), ec));
- goto upcall;
- }
- for(;;)
- {
- BOOST_ASIO_CORO_YIELD
- async_read_some(
- s_, b_, p_, std::move(*this));
- if(ec)
- goto upcall;
- bytes_transferred_ += bytes_transferred;
- if(Condition{}(p_))
- goto upcall;
- }
- upcall:
- h_(ec, bytes_transferred_);
- }
-}
-
-//------------------------------------------------------------------------------
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Body, class Allocator,
- class Handler>
-class read_msg_op
- : public boost::asio::coroutine
-{
- using parser_type =
- parser<isRequest, Body, Allocator>;
-
- using message_type =
- typename parser_type::value_type;
-
- struct data
- {
- Stream& s;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg;
- DynamicBuffer& b;
- message_type& m;
- parser_type p;
- std::size_t bytes_transferred = 0;
- bool cont = false;
-
- data(Handler const&, Stream& s_,
- DynamicBuffer& b_, message_type& m_)
- : s(s_)
- , wg(s.get_executor())
- , b(b_)
- , m(m_)
- , p(std::move(m))
- {
- p.eager(true);
- }
- };
-
- handler_ptr<data, Handler> d_;
-
-public:
- read_msg_op(read_msg_op&&) = default;
- read_msg_op(read_msg_op const&) = delete;
-
- template<class DeducedHandler, class... Args>
- read_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
- : d_(std::forward<DeducedHandler>(h),
- s, std::forward<Args>(args)...)
- {
- }
-
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
- {
- return (boost::asio::get_associated_allocator)(d_.handler());
- }
-
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
- {
- return (boost::asio::get_associated_executor)(
- d_.handler(), d_->s.get_executor());
- }
-
- void
- operator()(
- error_code ec,
- std::size_t bytes_transferred = 0,
- bool cont = true);
-
- friend
- bool asio_handler_is_continuation(read_msg_op* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return op->d_->cont ? true :
- asio_handler_is_continuation(
- std::addressof(op->d_.handler()));
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, read_msg_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->d_.handler()));
- }
-};
-
-template<class Stream, class DynamicBuffer,
- bool isRequest, class Body, class Allocator,
- class Handler>
-void
-read_msg_op<Stream, DynamicBuffer,
- isRequest, Body, Allocator, Handler>::
-operator()(
- error_code ec,
- std::size_t bytes_transferred,
- bool cont)
-{
- auto& d = *d_;
- d.cont = cont;
- BOOST_ASIO_CORO_REENTER(*this)
- {
- for(;;)
- {
- BOOST_ASIO_CORO_YIELD
- async_read_some(
- d.s, d.b, d.p, std::move(*this));
- if(ec)
- goto upcall;
- d.bytes_transferred +=
- bytes_transferred;
- if(d.p.is_done())
- {
- d.m = d.p.release();
- goto upcall;
- }
- }
- upcall:
- bytes_transferred = d.bytes_transferred;
- {
- auto wg = std::move(d.wg);
- d_.invoke(ec, bytes_transferred);
- }
- }
-}
-
-} // detail
-
-//------------------------------------------------------------------------------
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read_some(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- BOOST_ASSERT(! parser.is_done());
- error_code ec;
- auto const bytes_transferred =
- read_some(stream, buffer, parser, ec);
- if(ec)
- BOOST_THROW_EXCEPTION(system_error{ec});
- return bytes_transferred;
-}
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read_some(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- error_code& ec)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- BOOST_ASSERT(! parser.is_done());
- std::size_t bytes_transferred = 0;
- if(buffer.size() == 0)
- goto do_read;
- for(;;)
- {
- // invoke parser
- {
- auto const n = parser.put(buffer.data(), ec);
- bytes_transferred += n;
- buffer.consume(n);
- if(! ec)
- break;
- if(ec != http::error::need_more)
- break;
- }
- do_read:
- auto const size = read_size(buffer, 65536);
- if(size == 0)
- {
- ec = error::buffer_overflow;
- break;
- }
- auto const mb =
- beast::detail::dynamic_buffer_prepare(
- buffer, size, ec, error::buffer_overflow);
- if(ec)
- break;
- auto const n = stream.read_some(*mb, ec);
- if(ec == boost::asio::error::eof)
- {
- BOOST_ASSERT(n == 0);
- if(parser.got_some())
- {
- // caller sees EOF on next read
- parser.put_eof(ec);
- if(ec)
- break;
- BOOST_ASSERT(parser.is_done());
- break;
- }
- ec = error::end_of_stream;
- break;
- }
- if(ec)
- break;
- buffer.commit(n);
- }
- return bytes_transferred;
-}
-
-template<
- class AsyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived,
- class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
-async_read_some(
- AsyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- ReadHandler&& handler)
-{
- static_assert(is_async_read_stream<AsyncReadStream>::value,
- "AsyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- BOOST_ASSERT(! parser.is_done());
- BOOST_BEAST_HANDLER_INIT(
- ReadHandler, void(error_code, std::size_t));
- detail::read_some_op<AsyncReadStream,
- DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void(error_code, std::size_t))>{
- std::move(init.completion_handler), stream, buffer, parser}(
- {}, 0, false);
- return init.result.get();
-}
-
-//------------------------------------------------------------------------------
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read_header(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- error_code ec;
- auto const bytes_transferred =
- read_header(stream, buffer, parser, ec);
- if(ec)
- BOOST_THROW_EXCEPTION(system_error{ec});
- return bytes_transferred;
-}
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read_header(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- error_code& ec)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- parser.eager(false);
- if(parser.is_header_done())
- {
- ec.assign(0, ec.category());
- return 0;
- }
- std::size_t bytes_transferred = 0;
- do
- {
- bytes_transferred += read_some(
- stream, buffer, parser, ec);
- if(ec)
- return bytes_transferred;
- }
- while(! parser.is_header_done());
- return bytes_transferred;
-}
-
-template<
- class AsyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived,
- class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
-async_read_header(
- AsyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- ReadHandler&& handler)
-{
- static_assert(is_async_read_stream<AsyncReadStream>::value,
- "AsyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- parser.eager(false);
- BOOST_BEAST_HANDLER_INIT(
- ReadHandler, void(error_code, std::size_t));
- detail::read_op<AsyncReadStream, DynamicBuffer,
- isRequest, Derived, detail::parser_is_header_done,
- BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
- std::move(init.completion_handler), stream,
- buffer, parser}({}, 0, false);
- return init.result.get();
-}
-
-//------------------------------------------------------------------------------
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- error_code ec;
- auto const bytes_transferred =
- read(stream, buffer, parser, ec);
- if(ec)
- BOOST_THROW_EXCEPTION(system_error{ec});
- return bytes_transferred;
-}
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived>
-std::size_t
-read(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- error_code& ec)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- parser.eager(true);
- if(parser.is_done())
- {
- ec.assign(0, ec.category());
- return 0;
- }
- std::size_t bytes_transferred = 0;
- do
- {
- bytes_transferred += read_some(
- stream, buffer, parser, ec);
- if(ec)
- return bytes_transferred;
- }
- while(! parser.is_done());
- return bytes_transferred;
-}
-
-template<
- class AsyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Derived,
- class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
-async_read(
- AsyncReadStream& stream,
- DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
- ReadHandler&& handler)
-{
- static_assert(is_async_read_stream<AsyncReadStream>::value,
- "AsyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- parser.eager(true);
- BOOST_BEAST_HANDLER_INIT(
- ReadHandler, void(error_code, std::size_t));
- detail::read_op<AsyncReadStream, DynamicBuffer,
- isRequest, Derived, detail::parser_is_done,
- BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
- std::move(init.completion_handler), stream, buffer, parser}(
- {}, 0, false);
- return init.result.get();
-}
-
-//------------------------------------------------------------------------------
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Body, class Allocator>
-std::size_t
-read(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- message<isRequest, Body, basic_fields<Allocator>>& msg)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- static_assert(is_body<Body>::value,
- "Body requirements not met");
- static_assert(is_body_reader<Body>::value,
- "BodyReader requirements not met");
- error_code ec;
- auto const bytes_transferred =
- read(stream, buffer, msg, ec);
- if(ec)
- BOOST_THROW_EXCEPTION(system_error{ec});
- return bytes_transferred;
-}
-
-template<
- class SyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Body, class Allocator>
-std::size_t
-read(
- SyncReadStream& stream,
- DynamicBuffer& buffer,
- message<isRequest, Body, basic_fields<Allocator>>& msg,
- error_code& ec)
-{
- static_assert(is_sync_read_stream<SyncReadStream>::value,
- "SyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- static_assert(is_body<Body>::value,
- "Body requirements not met");
- static_assert(is_body_reader<Body>::value,
- "BodyReader requirements not met");
- parser<isRequest, Body, Allocator> p{std::move(msg)};
- p.eager(true);
- auto const bytes_transferred =
- read(stream, buffer, p.base(), ec);
- if(ec)
- return bytes_transferred;
- msg = p.release();
- return bytes_transferred;
-}
-
-template<
- class AsyncReadStream,
- class DynamicBuffer,
- bool isRequest, class Body, class Allocator,
- class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
-async_read(
- AsyncReadStream& stream,
- DynamicBuffer& buffer,
- message<isRequest, Body, basic_fields<Allocator>>& msg,
- ReadHandler&& handler)
-{
- static_assert(is_async_read_stream<AsyncReadStream>::value,
- "AsyncReadStream requirements not met");
- static_assert(
- boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
- "DynamicBuffer requirements not met");
- static_assert(is_body<Body>::value,
- "Body requirements not met");
- static_assert(is_body_reader<Body>::value,
- "BodyReader requirements not met");
- BOOST_BEAST_HANDLER_INIT(
- ReadHandler, void(error_code, std::size_t));
- detail::read_msg_op<
- AsyncReadStream,
- DynamicBuffer,
- isRequest, Body, Allocator,
- BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void(error_code, std::size_t))>{
- std::move(init.completion_handler), stream, buffer, msg}(
- {}, 0, false);
- return init.result.get();
-}
-
-} // http
-} // beast
-} // boost
-
-#endif
diff --git a/boost/beast/http/impl/rfc7230.hpp b/boost/beast/http/impl/rfc7230.hpp
new file mode 100644
index 0000000000..11e424b4d1
--- /dev/null
+++ b/boost/beast/http/impl/rfc7230.hpp
@@ -0,0 +1,423 @@
+//
+// Copyright (c) 2016-2019 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_IMPL_RFC7230_HPP
+#define BOOST_BEAST_HTTP_IMPL_RFC7230_HPP
+
+#include <boost/beast/http/detail/rfc7230.hpp>
+#include <iterator>
+
+namespace boost {
+namespace beast {
+namespace http {
+
+class param_list::const_iterator
+{
+ using iter_type = string_view::const_iterator;
+
+ std::string s_;
+ detail::param_iter pi_;
+
+public:
+ using value_type = param_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::input_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.pi_.it == pi_.it &&
+ other.pi_.last == pi_.last &&
+ other.pi_.first == pi_.first;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return pi_.v;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class param_list;
+
+ const_iterator(iter_type first, iter_type last)
+ {
+ pi_.it = first;
+ pi_.first = first;
+ pi_.last = last;
+ increment();
+ }
+
+ BOOST_BEAST_DECL
+ static
+ std::string
+ unquote(string_view sr);
+
+ BOOST_BEAST_DECL
+ void
+ increment();
+};
+
+inline
+auto
+param_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+param_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+param_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+param_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+//------------------------------------------------------------------------------
+
+class ext_list::const_iterator
+{
+ ext_list::value_type v_;
+ iter_type it_;
+ iter_type first_;
+ iter_type last_;
+
+public:
+ using value_type = ext_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.it_ == it_ &&
+ other.first_ == first_ &&
+ other.last_ == last_;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return v_;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class ext_list;
+
+ const_iterator(iter_type begin, iter_type end)
+ {
+ it_ = begin;
+ first_ = begin;
+ last_ = end;
+ increment();
+ }
+
+ BOOST_BEAST_DECL
+ void
+ increment();
+};
+
+inline
+auto
+ext_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+template<class T>
+auto
+ext_list::
+find(T const& s) ->
+ const_iterator
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return iequals(s, v.first);
+ });
+}
+
+template<class T>
+bool
+ext_list::
+exists(T const& s)
+{
+ return find(s) != end();
+}
+
+
+//------------------------------------------------------------------------------
+
+class token_list::const_iterator
+{
+ token_list::value_type v_;
+ iter_type it_;
+ iter_type first_;
+ iter_type last_;
+
+public:
+ using value_type = token_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.it_ == it_ &&
+ other.first_ == first_ &&
+ other.last_ == last_;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return v_;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class token_list;
+
+ const_iterator(iter_type begin, iter_type end)
+ {
+ it_ = begin;
+ first_ = begin;
+ last_ = end;
+ increment();
+ }
+
+ BOOST_BEAST_DECL
+ void
+ increment();
+};
+
+inline
+auto
+token_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+token_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+token_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+token_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+template<class T>
+bool
+token_list::
+exists(T const& s)
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return iequals(s, v);
+ }
+ ) != end();
+}
+
+template<class Policy>
+bool
+validate_list(detail::basic_parsed_list<
+ Policy> const& list)
+{
+ auto const last = list.end();
+ auto it = list.begin();
+ if(it.error())
+ return false;
+ while(it != last)
+ {
+ ++it;
+ if(it.error())
+ return false;
+ if(it == last)
+ break;
+ }
+ return true;
+}
+
+} // http
+} // beast
+} // boost
+
+#ifdef BOOST_BEAST_HEADER_ONLY
+#include <boost/beast/http/impl/rfc7230.ipp>
+#endif
+
+#endif
+
diff --git a/boost/beast/http/impl/rfc7230.ipp b/boost/beast/http/impl/rfc7230.ipp
index 96ec902ceb..cf60cefa36 100644
--- a/boost/beast/http/impl/rfc7230.ipp
+++ b/boost/beast/http/impl/rfc7230.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,129 +10,13 @@
#ifndef BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
#define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
-#include <boost/beast/http/detail/rfc7230.hpp>
-#include <iterator>
+#include <boost/beast/http/rfc7230.hpp>
namespace boost {
namespace beast {
namespace http {
-class param_list::const_iterator
-{
- using iter_type = string_view::const_iterator;
-
- std::string s_;
- detail::param_iter pi_;
-
-public:
- using value_type = param_list::value_type;
- using pointer = value_type const*;
- using reference = value_type const&;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
-
- const_iterator() = default;
-
- bool
- operator==(const_iterator const& other) const
- {
- return
- other.pi_.it == pi_.it &&
- other.pi_.last == pi_.last &&
- other.pi_.first == pi_.first;
- }
-
- bool
- operator!=(const_iterator const& other) const
- {
- return !(*this == other);
- }
-
- reference
- operator*() const
- {
- return pi_.v;
- }
-
- pointer
- operator->() const
- {
- return &*(*this);
- }
-
- const_iterator&
- operator++()
- {
- increment();
- return *this;
- }
-
- const_iterator
- operator++(int)
- {
- auto temp = *this;
- ++(*this);
- return temp;
- }
-
-private:
- friend class param_list;
-
- const_iterator(iter_type first, iter_type last)
- {
- pi_.it = first;
- pi_.first = first;
- pi_.last = last;
- increment();
- }
-
- template<class = void>
- static
- std::string
- unquote(string_view sr);
-
- template<class = void>
- void
- increment();
-};
-
-inline
-auto
-param_list::
-begin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-param_list::
-end() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-
-inline
-auto
-param_list::
-cbegin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-param_list::
-cend() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-template<class>
std::string
param_list::const_iterator::
unquote(string_view sr)
@@ -151,7 +35,6 @@ unquote(string_view sr)
return s;
}
-template<class>
void
param_list::const_iterator::
increment()
@@ -172,140 +55,6 @@ increment()
}
}
-//------------------------------------------------------------------------------
-
-class ext_list::const_iterator
-{
- ext_list::value_type v_;
- iter_type it_;
- iter_type first_;
- iter_type last_;
-
-public:
- using value_type = ext_list::value_type;
- using pointer = value_type const*;
- using reference = value_type const&;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
-
- const_iterator() = default;
-
- bool
- operator==(const_iterator const& other) const
- {
- return
- other.it_ == it_ &&
- other.first_ == first_ &&
- other.last_ == last_;
- }
-
- bool
- operator!=(const_iterator const& other) const
- {
- return !(*this == other);
- }
-
- reference
- operator*() const
- {
- return v_;
- }
-
- pointer
- operator->() const
- {
- return &*(*this);
- }
-
- const_iterator&
- operator++()
- {
- increment();
- return *this;
- }
-
- const_iterator
- operator++(int)
- {
- auto temp = *this;
- ++(*this);
- return temp;
- }
-
-private:
- friend class ext_list;
-
- const_iterator(iter_type begin, iter_type end)
- {
- it_ = begin;
- first_ = begin;
- last_ = end;
- increment();
- }
-
- template<class = void>
- void
- increment();
-};
-
-inline
-auto
-ext_list::
-begin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-ext_list::
-end() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-
-inline
-auto
-ext_list::
-cbegin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-ext_list::
-cend() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-
-template<class T>
-auto
-ext_list::
-find(T const& s) ->
- const_iterator
-{
- return std::find_if(begin(), end(),
- [&s](value_type const& v)
- {
- return iequals(s, v.first);
- });
-}
-
-template<class T>
-bool
-ext_list::
-exists(T const& s)
-{
- return find(s) != end();
-}
-
-template<class>
void
ext_list::const_iterator::
increment()
@@ -316,7 +65,7 @@ increment()
param-list = *( OWS ";" OWS param )
param = token OWS "=" OWS ( token / quoted-string )
- chunked;a=b;i=j,gzip;windowBits=12
+ chunked;a=b;i=j;gzip;windowBits=12
x,y
,,,,,chameleon
*/
@@ -350,6 +99,8 @@ increment()
}
v_.first = string_view{&*p0,
static_cast<std::size_t>(it_ - p0)};
+ if (it_ == last_)
+ return;
detail::param_iter pi;
pi.it = it_;
pi.first = it_;
@@ -372,119 +123,6 @@ increment()
}
}
-//------------------------------------------------------------------------------
-
-class token_list::const_iterator
-{
- token_list::value_type v_;
- iter_type it_;
- iter_type first_;
- iter_type last_;
-
-public:
- using value_type = token_list::value_type;
- using pointer = value_type const*;
- using reference = value_type const&;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
-
- const_iterator() = default;
-
- bool
- operator==(const_iterator const& other) const
- {
- return
- other.it_ == it_ &&
- other.first_ == first_ &&
- other.last_ == last_;
- }
-
- bool
- operator!=(const_iterator const& other) const
- {
- return !(*this == other);
- }
-
- reference
- operator*() const
- {
- return v_;
- }
-
- pointer
- operator->() const
- {
- return &*(*this);
- }
-
- const_iterator&
- operator++()
- {
- increment();
- return *this;
- }
-
- const_iterator
- operator++(int)
- {
- auto temp = *this;
- ++(*this);
- return temp;
- }
-
-private:
- friend class token_list;
-
- const_iterator(iter_type begin, iter_type end)
- {
- it_ = begin;
- first_ = begin;
- last_ = end;
- increment();
- }
-
- template<class = void>
- void
- increment();
-};
-
-inline
-auto
-token_list::
-begin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-token_list::
-end() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-
-inline
-auto
-token_list::
-cbegin() const ->
- const_iterator
-{
- return const_iterator{s_.begin(), s_.end()};
-}
-
-inline
-auto
-token_list::
-cend() const ->
- const_iterator
-{
- return const_iterator{s_.end(), s_.end()};
-}
-
-template<class>
void
token_list::const_iterator::
increment()
@@ -531,42 +169,8 @@ increment()
}
}
-template<class T>
-bool
-token_list::
-exists(T const& s)
-{
- return std::find_if(begin(), end(),
- [&s](value_type const& v)
- {
- return iequals(s, v);
- }
- ) != end();
-}
-
-template<class Policy>
-bool
-validate_list(detail::basic_parsed_list<
- Policy> const& list)
-{
- auto const last = list.end();
- auto it = list.begin();
- if(it.error())
- return false;
- while(it != last)
- {
- ++it;
- if(it.error())
- return false;
- if(it == last)
- break;
- }
- return true;
-}
-
} // http
} // beast
} // boost
-#endif
-
+#endif // BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
diff --git a/boost/beast/http/impl/serializer.ipp b/boost/beast/http/impl/serializer.hpp
index b9e7d26bdb..39efb482d0 100644
--- a/boost/beast/http/impl/serializer.ipp
+++ b/boost/beast/http/impl/serializer.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,9 +7,10 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_SERIALIZER_IPP
-#define BOOST_BEAST_HTTP_IMPL_SERIALIZER_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
+#define BOOST_BEAST_HTTP_IMPL_SERIALIZER_HPP
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/buffers_ref.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/status.hpp>
@@ -70,7 +71,6 @@ void
serializer<isRequest, Body, Fields>::
next(error_code& ec, Visit&& visit)
{
- using boost::asio::buffer_size;
switch(s_)
{
case do_construct:
@@ -165,21 +165,21 @@ next(error_code& ec, Visit&& visit)
v_.template emplace<7>(
boost::in_place_init,
fwr_->get(),
- buffer_size(result->first),
- boost::asio::const_buffer{nullptr, 0},
+ buffer_bytes(result->first),
+ net::const_buffer{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{},
detail::chunk_last(),
- boost::asio::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
chunk_crlf{});
goto go_all_c;
}
v_.template emplace<4>(
boost::in_place_init,
fwr_->get(),
- buffer_size(result->first),
- boost::asio::const_buffer{nullptr, 0},
+ buffer_bytes(result->first),
+ net::const_buffer{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{});
@@ -217,20 +217,20 @@ next(error_code& ec, Visit&& visit)
// do it all in one buffer
v_.template emplace<6>(
boost::in_place_init,
- buffer_size(result->first),
- boost::asio::const_buffer{nullptr, 0},
+ buffer_bytes(result->first),
+ net::const_buffer{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{},
detail::chunk_last(),
- boost::asio::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
chunk_crlf{});
goto go_body_final_c;
}
v_.template emplace<5>(
boost::in_place_init,
- buffer_size(result->first),
- boost::asio::const_buffer{nullptr, 0},
+ buffer_bytes(result->first),
+ net::const_buffer{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{});
@@ -261,7 +261,7 @@ next(error_code& ec, Visit&& visit)
v_.template emplace<8>(
boost::in_place_init,
detail::chunk_last(),
- boost::asio::const_buffer{nullptr, 0},
+ net::const_buffer{nullptr, 0},
chunk_crlf{});
s_ = do_final_c + 1;
BOOST_FALLTHROUGH;
@@ -289,14 +289,13 @@ void
serializer<isRequest, Body, Fields>::
consume(std::size_t n)
{
- using boost::asio::buffer_size;
switch(s_)
{
case do_header:
BOOST_ASSERT(
- n <= buffer_size(v_.template get<2>()));
+ n <= buffer_bytes(v_.template get<2>()));
v_.template get<2>().consume(n);
- if(buffer_size(v_.template get<2>()) > 0)
+ if(buffer_bytes(v_.template get<2>()) > 0)
break;
header_done_ = true;
v_.reset();
@@ -307,9 +306,9 @@ consume(std::size_t n)
case do_header_only:
BOOST_ASSERT(
- n <= buffer_size(v_.template get<1>()));
+ n <= buffer_bytes(v_.template get<1>()));
v_.template get<1>().consume(n);
- if(buffer_size(v_.template get<1>()) > 0)
+ if(buffer_bytes(v_.template get<1>()) > 0)
break;
fwr_ = boost::none;
header_done_ = true;
@@ -321,9 +320,9 @@ consume(std::size_t n)
case do_body + 2:
{
BOOST_ASSERT(
- n <= buffer_size(v_.template get<3>()));
+ n <= buffer_bytes(v_.template get<3>()));
v_.template get<3>().consume(n);
- if(buffer_size(v_.template get<3>()) > 0)
+ if(buffer_bytes(v_.template get<3>()) > 0)
break;
v_.reset();
if(! more_)
@@ -336,9 +335,9 @@ consume(std::size_t n)
case do_header_c:
BOOST_ASSERT(
- n <= buffer_size(v_.template get<4>()));
+ n <= buffer_bytes(v_.template get<4>()));
v_.template get<4>().consume(n);
- if(buffer_size(v_.template get<4>()) > 0)
+ if(buffer_bytes(v_.template get<4>()) > 0)
break;
header_done_ = true;
v_.reset();
@@ -351,9 +350,9 @@ consume(std::size_t n)
case do_header_only_c:
{
BOOST_ASSERT(
- n <= buffer_size(v_.template get<1>()));
+ n <= buffer_bytes(v_.template get<1>()));
v_.template get<1>().consume(n);
- if(buffer_size(v_.template get<1>()) > 0)
+ if(buffer_bytes(v_.template get<1>()) > 0)
break;
fwr_ = boost::none;
header_done_ = true;
@@ -368,9 +367,9 @@ consume(std::size_t n)
case do_body_c + 2:
BOOST_ASSERT(
- n <= buffer_size(v_.template get<5>()));
+ n <= buffer_bytes(v_.template get<5>()));
v_.template get<5>().consume(n);
- if(buffer_size(v_.template get<5>()) > 0)
+ if(buffer_bytes(v_.template get<5>()) > 0)
break;
v_.reset();
if(more_)
@@ -382,9 +381,9 @@ consume(std::size_t n)
case do_body_final_c:
{
BOOST_ASSERT(
- n <= buffer_size(v_.template get<6>()));
+ n <= buffer_bytes(v_.template get<6>()));
v_.template get<6>().consume(n);
- if(buffer_size(v_.template get<6>()) > 0)
+ if(buffer_bytes(v_.template get<6>()) > 0)
break;
v_.reset();
s_ = do_complete;
@@ -394,9 +393,9 @@ consume(std::size_t n)
case do_all_c:
{
BOOST_ASSERT(
- n <= buffer_size(v_.template get<7>()));
+ n <= buffer_bytes(v_.template get<7>()));
v_.template get<7>().consume(n);
- if(buffer_size(v_.template get<7>()) > 0)
+ if(buffer_bytes(v_.template get<7>()) > 0)
break;
header_done_ = true;
v_.reset();
@@ -405,9 +404,9 @@ consume(std::size_t n)
}
case do_final_c + 1:
- BOOST_ASSERT(buffer_size(v_.template get<8>()));
+ BOOST_ASSERT(buffer_bytes(v_.template get<8>()));
v_.template get<8>().consume(n);
- if(buffer_size(v_.template get<8>()) > 0)
+ if(buffer_bytes(v_.template get<8>()) > 0)
break;
v_.reset();
goto go_complete;
diff --git a/boost/beast/http/impl/status.ipp b/boost/beast/http/impl/status.ipp
index 7d37919423..2a61acd5c9 100644
--- a/boost/beast/http/impl/status.ipp
+++ b/boost/beast/http/impl/status.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,15 +10,13 @@
#ifndef BOOST_BEAST_HTTP_IMPL_STATUS_IPP
#define BOOST_BEAST_HTTP_IMPL_STATUS_IPP
-#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/http/status.hpp>
#include <boost/throw_exception.hpp>
namespace boost {
namespace beast {
namespace http {
-namespace detail {
-template<class = void>
status
int_to_status(unsigned v)
{
@@ -107,9 +105,30 @@ int_to_status(unsigned v)
return status::unknown;
}
-template<class = void>
+status_class
+to_status_class(unsigned v)
+{
+ switch(v / 100)
+ {
+ case 1: return status_class::informational;
+ case 2: return status_class::successful;
+ case 3: return status_class::redirection;
+ case 4: return status_class::client_error;
+ case 5: return status_class::server_error;
+ default:
+ break;
+ }
+ return status_class::unknown;
+}
+
+status_class
+to_status_class(status v)
+{
+ return to_status_class(static_cast<int>(v));
+}
+
string_view
-status_to_string(unsigned v)
+obsolete_reason(status v)
{
switch(static_cast<status>(v))
{
@@ -190,55 +209,6 @@ status_to_string(unsigned v)
return "<unknown-status>";
}
-template<class = void>
-status_class
-to_status_class(unsigned v)
-{
- switch(v / 100)
- {
- case 1: return status_class::informational;
- case 2: return status_class::successful;
- case 3: return status_class::redirection;
- case 4: return status_class::client_error;
- case 5: return status_class::server_error;
- default:
- break;
- }
- return status_class::unknown;
-}
-
-} // detail
-
-inline
-status
-int_to_status(unsigned v)
-{
- return detail::int_to_status(v);
-}
-
-inline
-status_class
-to_status_class(unsigned v)
-{
- return detail::to_status_class(v);
-}
-
-inline
-status_class
-to_status_class(status v)
-{
- return to_status_class(static_cast<int>(v));
-}
-
-inline
-string_view
-obsolete_reason(status v)
-{
- return detail::status_to_string(
- static_cast<unsigned>(v));
-}
-
-inline
std::ostream&
operator<<(std::ostream& os, status v)
{
diff --git a/boost/beast/http/impl/verb.ipp b/boost/beast/http/impl/verb.ipp
index 36a1734c33..20ef47c551 100644
--- a/boost/beast/http/impl/verb.ipp
+++ b/boost/beast/http/impl/verb.ipp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,7 +10,7 @@
#ifndef BOOST_BEAST_HTTP_IMPL_VERB_IPP
#define BOOST_BEAST_HTTP_IMPL_VERB_IPP
-#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/http/verb.hpp>
#include <boost/throw_exception.hpp>
#include <stdexcept>
@@ -18,12 +18,8 @@ namespace boost {
namespace beast {
namespace http {
-namespace detail {
-
-template<class = void>
-inline
string_view
-verb_to_string(verb v)
+to_string(verb v)
{
switch(v)
{
@@ -74,7 +70,6 @@ verb_to_string(verb v)
BOOST_THROW_EXCEPTION(std::invalid_argument{"unknown verb"});
}
-template<class = void>
verb
string_to_verb(string_view v)
{
@@ -314,22 +309,6 @@ string_to_verb(string_view v)
return verb::unknown;
}
-} // detail
-
-inline
-string_view
-to_string(verb v)
-{
- return detail::verb_to_string(v);
-}
-
-inline
-verb
-string_to_verb(string_view s)
-{
- return detail::string_to_verb(s);
-}
-
} // http
} // beast
} // boost
diff --git a/boost/beast/http/impl/write.ipp b/boost/beast/http/impl/write.hpp
index bbada07024..5636ce92f8 100644
--- a/boost/beast/http/impl/write.ipp
+++ b/boost/beast/http/impl/write.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -7,21 +7,16 @@
// Official repository: https://github.com/boostorg/beast
//
-#ifndef BOOST_BEAST_HTTP_IMPL_WRITE_IPP
-#define BOOST_BEAST_HTTP_IMPL_WRITE_IPP
+#ifndef BOOST_BEAST_HTTP_IMPL_WRITE_HPP
+#define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
#include <boost/beast/http/type_traits.hpp>
+#include <boost/beast/core/async_base.hpp>
#include <boost/beast/core/bind_handler.hpp>
+#include <boost/beast/core/buffers_range.hpp>
#include <boost/beast/core/ostream.hpp>
-#include <boost/beast/core/handler_ptr.hpp>
-#include <boost/beast/core/type_traits.hpp>
-#include <boost/beast/core/detail/config.hpp>
-#include <boost/asio/associated_allocator.hpp>
-#include <boost/asio/associated_executor.hpp>
+#include <boost/beast/core/stream_traits.hpp>
#include <boost/asio/coroutine.hpp>
-#include <boost/asio/executor_work_guard.hpp>
-#include <boost/asio/handler_continuation_hook.hpp>
-#include <boost/asio/handler_invoke_hook.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/write.hpp>
#include <boost/optional.hpp>
@@ -35,15 +30,15 @@ namespace http {
namespace detail {
template<
- class Stream, class Handler,
+ class Handler,
+ class Stream,
bool isRequest, class Body, class Fields>
class write_some_op
+ : public beast::async_base<
+ Handler, beast::executor_type<Stream>>
{
Stream& s_;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg_;
serializer<isRequest,Body, Fields>& sr_;
- Handler h_;
class lambda
{
@@ -60,122 +55,74 @@ class write_some_op
template<class ConstBufferSequence>
void
- operator()(error_code& ec,
+ operator()(
+ error_code& ec,
ConstBufferSequence const& buffers)
{
invoked = true;
- ec.assign(0, ec.category());
- return op_.s_.async_write_some(
+ ec = {};
+ op_.s_.async_write_some(
buffers, std::move(op_));
}
};
public:
- write_some_op(write_some_op&&) = default;
- write_some_op(write_some_op const&) = delete;
-
- template<class DeducedHandler>
- write_some_op(DeducedHandler&& h, Stream& s,
- serializer<isRequest, Body, Fields>& sr)
- : s_(s)
- , wg_(s_.get_executor())
+ template<class Handler_>
+ write_some_op(
+ Handler_&& h,
+ Stream& s,
+ serializer<isRequest, Body, Fields>& sr)
+ : async_base<
+ Handler, beast::executor_type<Stream>>(
+ std::forward<Handler_>(h), s.get_executor())
+ , s_(s)
, sr_(sr)
- , h_(std::forward<DeducedHandler>(h))
{
+ (*this)();
}
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
+ void
+ operator()()
{
- return (boost::asio::get_associated_allocator)(h_);
- }
-
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
+ error_code ec;
+ if(! sr_.is_done())
+ {
+ lambda f{*this};
+ sr_.next(ec, f);
+ if(ec)
+ {
+ BOOST_ASSERT(! f.invoked);
+ return net::post(
+ s_.get_executor(),
+ beast::bind_front_handler(
+ std::move(*this), ec, 0));
+ }
+ if(f.invoked)
+ {
+ // *this is now moved-from,
+ return;
+ }
+ // What else could it be?
+ BOOST_ASSERT(sr_.is_done());
+ }
- executor_type
- get_executor() const noexcept
- {
- return (boost::asio::get_associated_executor)(
- h_, s_.get_executor());
+ return net::post(
+ s_.get_executor(),
+ beast::bind_front_handler(
+ std::move(*this), ec, 0));
}
void
- operator()();
-
- void
operator()(
error_code ec,
- std::size_t bytes_transferred);
-
- friend
- bool asio_handler_is_continuation(write_some_op* op)
+ std::size_t bytes_transferred)
{
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- std::addressof(op->h_));
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, write_some_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
+ if(! ec)
+ sr_.consume(bytes_transferred);
+ this->complete_now(ec, bytes_transferred);
}
};
-template<
- class Stream, class Handler,
- bool isRequest, class Body, class Fields>
-void
-write_some_op<
- Stream, Handler, isRequest, Body, Fields>::
-operator()()
-{
- error_code ec;
- if(! sr_.is_done())
- {
- lambda f{*this};
- sr_.next(ec, f);
- if(ec)
- {
- BOOST_ASSERT(! f.invoked);
- return boost::asio::post(
- s_.get_executor(),
- bind_handler(std::move(*this), ec, 0));
- }
- if(f.invoked)
- {
- // *this has been moved from,
- // cannot access members here.
- return;
- }
- // What else could it be?
- BOOST_ASSERT(sr_.is_done());
- }
- return boost::asio::post(
- s_.get_executor(),
- bind_handler(std::move(*this), ec, 0));
-}
-
-template<
- class Stream, class Handler,
- bool isRequest, class Body, class Fields>
-void
-write_some_op<
- Stream, Handler, isRequest, Body, Fields>::
-operator()(
- error_code ec, std::size_t bytes_transferred)
-{
- if(! ec)
- sr_.consume(bytes_transferred);
- h_(ec, bytes_transferred);
-}
-
//------------------------------------------------------------------------------
struct serializer_is_header_done
@@ -205,221 +152,235 @@ struct serializer_is_done
//------------------------------------------------------------------------------
template<
- class Stream, class Handler, class Predicate,
+ class Handler,
+ class Stream,
+ class Predicate,
bool isRequest, class Body, class Fields>
-class write_op : public boost::asio::coroutine
+class write_op
+ : public beast::async_base<
+ Handler, beast::executor_type<Stream>>
+ , public net::coroutine
{
Stream& s_;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg_;
serializer<isRequest, Body, Fields>& sr_;
std::size_t bytes_transferred_ = 0;
- Handler h_;
- bool cont_;
public:
- write_op(write_op&&) = default;
- write_op(write_op const&) = delete;
-
- template<class DeducedHandler>
- write_op(DeducedHandler&& h, Stream& s,
- serializer<isRequest, Body, Fields>& sr)
- : s_(s)
- , wg_(s_.get_executor())
+ template<class Handler_>
+ write_op(
+ Handler_&& h,
+ Stream& s,
+ serializer<isRequest, Body, Fields>& sr)
+ : async_base<
+ Handler, beast::executor_type<Stream>>(
+ std::forward<Handler_>(h), s.get_executor())
+ , s_(s)
, sr_(sr)
- , h_(std::forward<DeducedHandler>(h))
- , cont_([&]
- {
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- std::addressof(h_));
- }())
{
- }
-
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
- {
- return (boost::asio::get_associated_allocator)(h_);
- }
-
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
- {
- return (boost::asio::get_associated_executor)(
- h_, s_.get_executor());
+ (*this)();
}
void
operator()(
error_code ec = {},
- std::size_t bytes_transferred = 0);
-
- friend
- bool asio_handler_is_continuation(write_op* op)
- {
- return op->cont_;
- }
-
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, write_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
- }
-};
-
-template<
- class Stream, class Handler, class Predicate,
- bool isRequest, class Body, class Fields>
-void
-write_op<Stream, Handler, Predicate,
- isRequest, Body, Fields>::
-operator()(
- error_code ec,
- std::size_t bytes_transferred)
-{
- BOOST_ASIO_CORO_REENTER(*this)
+ std::size_t bytes_transferred = 0)
{
- if(Predicate{}(sr_))
+ BOOST_ASIO_CORO_REENTER(*this)
{
- BOOST_ASIO_CORO_YIELD
- boost::asio::post(
- s_.get_executor(),
- bind_handler(std::move(*this)));
- goto upcall;
- }
- for(;;)
- {
- BOOST_ASIO_CORO_YIELD
- beast::http::async_write_some(
- s_, sr_, std::move(*this));
- bytes_transferred_ += bytes_transferred;
- if(ec)
- goto upcall;
if(Predicate{}(sr_))
- break;
- cont_ = true;
+ {
+ BOOST_ASIO_CORO_YIELD
+ net::post(
+ s_.get_executor(),
+ std::move(*this));
+ goto upcall;
+ }
+ for(;;)
+ {
+ BOOST_ASIO_CORO_YIELD
+ beast::http::async_write_some(
+ s_, sr_, std::move(*this));
+ bytes_transferred_ += bytes_transferred;
+ if(ec)
+ goto upcall;
+ if(Predicate{}(sr_))
+ break;
+ }
+ upcall:
+ this->complete_now(ec, bytes_transferred_);
}
- upcall:
- h_(ec, bytes_transferred_);
}
-}
+};
//------------------------------------------------------------------------------
-template<class Stream, class Handler,
+template<
+ class Handler,
+ class Stream,
bool isRequest, class Body, class Fields>
class write_msg_op
+ : public beast::stable_async_base<
+ Handler, beast::executor_type<Stream>>
{
- struct data
- {
- Stream& s;
- boost::asio::executor_work_guard<decltype(
- std::declval<Stream&>().get_executor())> wg;
- serializer<isRequest, Body, Fields> sr;
-
- data(Handler const&, Stream& s_, message<
- isRequest, Body, Fields>& m_)
- : s(s_)
- , wg(s.get_executor())
- , sr(m_)
- {
- }
-
- data(Handler const&, Stream& s_, message<
- isRequest, Body, Fields> const& m_)
- : s(s_)
- , wg(s.get_executor())
- , sr(m_)
- {
- }
- };
-
- handler_ptr<data, Handler> d_;
+ Stream& s_;
+ serializer<isRequest, Body, Fields>& sr_;
public:
- write_msg_op(write_msg_op&&) = default;
- write_msg_op(write_msg_op const&) = delete;
-
- template<class DeducedHandler, class... Args>
- write_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
- : d_(std::forward<DeducedHandler>(h),
- s, std::forward<Args>(args)...)
- {
+ template<
+ class Handler_,
+ class... Args>
+ write_msg_op(
+ Handler_&& h,
+ Stream& s,
+ Args&&... args)
+ : stable_async_base<
+ Handler, beast::executor_type<Stream>>(
+ std::forward<Handler_>(h), s.get_executor())
+ , s_(s)
+ , sr_(beast::allocate_stable<
+ serializer<isRequest, Body, Fields>>(
+ *this, std::forward<Args>(args)...))
+ {
+ (*this)();
}
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
-
- allocator_type
- get_allocator() const noexcept
+ void
+ operator()()
{
- return (boost::asio::get_associated_allocator)(d_.handler());
+ async_write(s_, sr_, std::move(*this));
}
- using executor_type = boost::asio::associated_executor_t<
- Handler, decltype(std::declval<Stream&>().get_executor())>;
-
- executor_type
- get_executor() const noexcept
+ void
+ operator()(
+ error_code ec, std::size_t bytes_transferred)
{
- return (boost::asio::get_associated_executor)(
- d_.handler(), d_->s.get_executor());
+ this->complete_now(ec, bytes_transferred);
}
+};
- void
- operator()();
-
+struct run_write_some_op
+{
+ template<
+ class WriteHandler,
+ class Stream,
+ bool isRequest, class Body, class Fields>
void
operator()(
- error_code ec, std::size_t bytes_transferred);
-
- friend
- bool asio_handler_is_continuation(write_msg_op* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- std::addressof(op->d_.handler()));
+ WriteHandler&& h,
+ Stream* s,
+ serializer<isRequest, Body, Fields>* sr)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_some_op<
+ typename std::decay<WriteHandler>::type,
+ Stream,
+ isRequest, Body, Fields>(
+ std::forward<WriteHandler>(h), *s, *sr);
}
+};
- template<class Function>
- friend
- void asio_handler_invoke(Function&& f, write_msg_op* op)
- {
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->d_.handler()));
+struct run_write_op
+{
+ template<
+ class WriteHandler,
+ class Stream,
+ class Predicate,
+ bool isRequest, class Body, class Fields>
+ void
+ operator()(
+ WriteHandler&& h,
+ Stream* s,
+ Predicate const&,
+ serializer<isRequest, Body, Fields>* sr)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_op<
+ typename std::decay<WriteHandler>::type,
+ Stream,
+ Predicate,
+ isRequest, Body, Fields>(
+ std::forward<WriteHandler>(h), *s, *sr);
}
};
-template<class Stream, class Handler,
- bool isRequest, class Body, class Fields>
-void
-write_msg_op<
- Stream, Handler, isRequest, Body, Fields>::
-operator()()
+struct run_write_msg_op
{
- auto& d = *d_;
- return async_write(d.s, d.sr, std::move(*this));
-}
+ template<
+ class WriteHandler,
+ class Stream,
+ bool isRequest, class Body, class Fields,
+ class... Args>
+ void
+ operator()(
+ WriteHandler&& h,
+ Stream* s,
+ message<isRequest, Body, Fields>* m,
+ std::false_type,
+ Args&&... args)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_msg_op<
+ typename std::decay<WriteHandler>::type,
+ Stream,
+ isRequest, Body, Fields>(
+ std::forward<WriteHandler>(h), *s, *m,
+ std::forward<Args>(args)...);
+ }
-template<class Stream, class Handler,
- bool isRequest, class Body, class Fields>
-void
-write_msg_op<
- Stream, Handler, isRequest, Body, Fields>::
-operator()(error_code ec, std::size_t bytes_transferred)
-{
- auto wg = std::move(d_->wg);
- d_.invoke(ec, bytes_transferred);
-}
+ template<
+ class WriteHandler,
+ class Stream,
+ bool isRequest, class Body, class Fields,
+ class... Args>
+ void
+ operator()(
+ WriteHandler&& h,
+ Stream* s,
+ message<isRequest, Body, Fields> const* m,
+ std::true_type,
+ Args&&... args)
+ {
+ // If you get an error on the following line it means
+ // that your handler does not meet the documented type
+ // requirements for the handler.
+
+ static_assert(
+ beast::detail::is_invocable<WriteHandler,
+ void(error_code, std::size_t)>::value,
+ "WriteHandler type requirements not met");
+
+ write_msg_op<
+ typename std::decay<WriteHandler>::type,
+ Stream,
+ isRequest, Body, Fields>(
+ std::forward<WriteHandler>(h), *s, *m,
+ std::forward<Args>(args)...);
+ }
+};
//------------------------------------------------------------------------------
@@ -470,7 +431,7 @@ public:
ConstBufferSequence const& buffers)
{
invoked = true;
- bytes_transferred = boost::asio::write(
+ bytes_transferred = net::write(
stream_, buffers, ec);
}
};
@@ -494,7 +455,7 @@ write_some_impl(
sr.consume(f.bytes_transferred);
return f.bytes_transferred;
}
- ec.assign(0, ec.category());
+ ec = {};
return 0;
}
@@ -502,22 +463,19 @@ template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_some_impl(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
WriteHandler&& handler)
{
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_some_op<
- AsyncWriteStream,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- isRequest, Body, Fields>{
- std::move(init.completion_handler), stream, sr}();
- return init.result.get();
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ run_write_some_op{},
+ handler,
+ &stream,
+ &sr);
}
} // detail
@@ -533,11 +491,11 @@ write_some(
serializer<isRequest, Body, Fields>& sr)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
error_code ec;
auto const bytes_transferred =
write_some(stream, sr, ec);
@@ -556,11 +514,11 @@ write_some(
error_code& ec)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
return detail::write_some_impl(stream, sr, ec);
}
@@ -568,8 +526,7 @@ template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_some(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -577,11 +534,11 @@ async_write_some(
{
static_assert(is_async_write_stream<
AsyncWriteStream>::value,
- "AsyncWriteStream requirements not met");
+ "AsyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
return detail::async_write_some_impl(stream, sr,
std::forward<WriteHandler>(handler));
}
@@ -596,11 +553,11 @@ write_header(SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
error_code ec;
auto const bytes_transferred =
write_header(stream, sr, ec);
@@ -619,11 +576,11 @@ write_header(
error_code& ec)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
sr.split(true);
std::size_t bytes_transferred = 0;
if(! sr.is_header_done())
@@ -642,7 +599,7 @@ write_header(
}
else
{
- ec.assign(0, ec.category());
+ ec = {};
}
return bytes_transferred;
}
@@ -651,8 +608,7 @@ template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_header(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -660,22 +616,20 @@ async_write_header(
{
static_assert(is_async_write_stream<
AsyncWriteStream>::value,
- "AsyncWriteStream requirements not met");
+ "AsyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
sr.split(true);
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_op<
- AsyncWriteStream,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- detail::serializer_is_header_done,
- isRequest, Body, Fields>{
- std::move(init.completion_handler), stream, sr}();
- return init.result.get();
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ detail::run_write_op{},
+ handler,
+ &stream,
+ detail::serializer_is_header_done{},
+ &sr);
}
//------------------------------------------------------------------------------
@@ -689,7 +643,7 @@ write(
serializer<isRequest, Body, Fields>& sr)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
error_code ec;
auto const bytes_transferred =
write(stream, sr, ec);
@@ -708,7 +662,7 @@ write(
error_code& ec)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
std::size_t bytes_transferred = 0;
sr.split(false);
for(;;)
@@ -727,8 +681,7 @@ template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -736,22 +689,20 @@ async_write(
{
static_assert(is_async_write_stream<
AsyncWriteStream>::value,
- "AsyncWriteStream requirements not met");
+ "AsyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
sr.split(false);
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_op<
- AsyncWriteStream,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- detail::serializer_is_done,
- isRequest, Body, Fields>{
- std::move(init.completion_handler), stream, sr}();
- return init.result.get();
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ detail::run_write_op{},
+ handler,
+ &stream,
+ detail::serializer_is_done{},
+ &sr);
}
//------------------------------------------------------------------------------
@@ -767,11 +718,11 @@ write(
message<isRequest, Body, Fields>& msg)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
error_code ec;
auto const bytes_transferred =
write(stream, msg, ec);
@@ -791,11 +742,11 @@ write(
message<isRequest, Body, Fields> const& msg)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
error_code ec;
auto const bytes_transferred =
write(stream, msg, ec);
@@ -816,11 +767,11 @@ write(
error_code& ec)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
serializer<isRequest, Body, Fields> sr{msg};
return write(stream, sr, ec);
}
@@ -837,11 +788,11 @@ write(
error_code& ec)
{
static_assert(is_sync_write_stream<SyncWriteStream>::value,
- "SyncWriteStream requirements not met");
+ "SyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
serializer<isRequest, Body, Fields> sr{msg};
return write(stream, sr, ec);
}
@@ -852,8 +803,7 @@ template<
class WriteHandler>
typename std::enable_if<
is_mutable_body_writer<Body>::value,
- BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))>::type
+ BOOST_BEAST_ASYNC_RESULT2(WriteHandler)>::type
async_write(
AsyncWriteStream& stream,
message<isRequest, Body, Fields>& msg,
@@ -861,20 +811,19 @@ async_write(
{
static_assert(
is_async_write_stream<AsyncWriteStream>::value,
- "AsyncWriteStream requirements not met");
+ "AsyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_msg_op<
- AsyncWriteStream,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- isRequest, Body, Fields>{
- std::move(init.completion_handler), stream, msg}();
- return init.result.get();
+ "BodyWriter type requirements not met");
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ detail::run_write_msg_op{},
+ handler,
+ &stream,
+ &msg,
+ std::false_type{});
}
template<
@@ -883,8 +832,7 @@ template<
class WriteHandler>
typename std::enable_if<
! is_mutable_body_writer<Body>::value,
- BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))>::type
+ BOOST_BEAST_ASYNC_RESULT2(WriteHandler)>::type
async_write(
AsyncWriteStream& stream,
message<isRequest, Body, Fields> const& msg,
@@ -892,20 +840,19 @@ async_write(
{
static_assert(
is_async_write_stream<AsyncWriteStream>::value,
- "AsyncWriteStream requirements not met");
+ "AsyncWriteStream type requirements not met");
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
- BOOST_BEAST_HANDLER_INIT(
- WriteHandler, void(error_code, std::size_t));
- detail::write_msg_op<
- AsyncWriteStream,
- BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void(error_code, std::size_t)),
- isRequest, Body, Fields>{
- std::move(init.completion_handler), stream, msg}();
- return init.result.get();
+ "BodyWriter type requirements not met");
+ return net::async_initiate<
+ WriteHandler,
+ void(error_code, std::size_t)>(
+ detail::run_write_msg_op{},
+ handler,
+ &stream,
+ &msg,
+ std::true_type{});
}
//------------------------------------------------------------------------------
@@ -931,11 +878,11 @@ public:
operator()(error_code& ec,
ConstBufferSequence const& buffers) const
{
- ec.assign(0, ec.category());
+ ec = {};
if(os_.fail())
return;
std::size_t bytes_transferred = 0;
- for(auto b : buffers_range(buffers))
+ for(auto b : beast::buffers_range_ref(buffers))
{
os_.write(static_cast<char const*>(
b.data()), b.size());
@@ -975,9 +922,9 @@ operator<<(std::ostream& os,
message<isRequest, Body, Fields> const& msg)
{
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
serializer<isRequest, Body, Fields> sr{msg};
error_code ec;
detail::write_ostream_lambda<decltype(sr)> f{os, sr};
@@ -990,7 +937,7 @@ operator<<(std::ostream& os,
{
os.setstate(std::ios::failbit);
break;
- }
+ }
}
while(! sr.is_done());
return os;
diff --git a/boost/beast/http/message.hpp b/boost/beast/http/message.hpp
index bd85d160f1..c21e3685f0 100644
--- a/boost/beast/http/message.hpp
+++ b/boost/beast/http/message.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -16,8 +16,8 @@
#include <boost/beast/http/status.hpp>
#include <boost/beast/http/type_traits.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/detail/integer_sequence.hpp>
#include <boost/core/empty_value.hpp>
+#include <boost/mp11/integer_sequence.hpp>
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <boost/throw_exception.hpp>
@@ -47,18 +47,19 @@ namespace http {
*/
#if BOOST_BEAST_DOXYGEN
template<bool isRequest, class Fields = fields>
-struct header : Fields
+class header : public Fields
#else
template<bool isRequest, class Fields = fields>
-struct header;
+class header;
template<class Fields>
-struct header<true, Fields> : Fields
+class header<true, Fields> : public Fields
#endif
{
+public:
static_assert(is_fields<Fields>::value,
- "Fields requirements not met");
+ "Fields type requirements not met");
/// Indicates if the header is a request or response.
#if BOOST_BEAST_DOXYGEN
@@ -128,7 +129,7 @@ struct header<true, Fields> : Fields
@note This function is only available when `isRequest == true`.
- @see @ref method_string
+ @see method_string
*/
verb
method() const;
@@ -151,7 +152,7 @@ struct header<true, Fields> : Fields
@note This function is only available when `isRequest == true`.
- @see @ref method
+ @see method
*/
string_view
method_string() const;
@@ -222,14 +223,14 @@ struct header<true, Fields> : Fields
! std::is_convertible<typename
std::decay<Arg1>::type, verb>::value &&
! std::is_convertible<typename
- std::decay<Arg1>::type, header>::value
+ std::decay<Arg1>::type, status>::value
>::type>
explicit
header(Arg1&& arg1, ArgN&&... argn);
private:
template<bool, class, class>
- friend struct message;
+ friend class message;
template<class T>
friend
@@ -258,10 +259,11 @@ private:
A `header` includes the start-line and header-fields.
*/
template<class Fields>
-struct header<false, Fields> : Fields
+class header<false, Fields> : public Fields
{
+public:
static_assert(is_fields<Fields>::value,
- "Fields requirements not met");
+ "Fields type requirements not met");
/// Indicates if the header is a request or response.
using is_request = std::false_type;
@@ -297,9 +299,11 @@ struct header<false, Fields> : Fields
template<class Arg1, class... ArgN,
class = typename std::enable_if<
! std::is_convertible<typename
- std::decay<Arg1>::type, status>::value &&
+ std::decay<Arg1>::type, header>::value &&
+ ! std::is_convertible<typename
+ std::decay<Arg1>::type, verb>::value &&
! std::is_convertible<typename
- std::decay<Arg1>::type, header>::value
+ std::decay<Arg1>::type, status>::value
>::type>
explicit
header(Arg1&& arg1, ArgN&&... argn);
@@ -418,7 +422,7 @@ struct header<false, Fields> : Fields
private:
#if ! BOOST_BEAST_DOXYGEN
template<bool, class, class>
- friend struct message;
+ friend class message;
template<class T>
friend
@@ -487,13 +491,14 @@ using value_type_t = typename T::value_type;
field value pairs.
*/
template<bool isRequest, class Body, class Fields = fields>
-struct message
- : header<isRequest, Fields>
+class message
+ : public header<isRequest, Fields>
#if ! BOOST_BEAST_DOXYGEN
, boost::empty_value<
typename Body::value_type>
#endif
{
+public:
/// The base class used to hold the header portion of the message.
using header_type = header<isRequest, Fields>;
@@ -542,11 +547,11 @@ struct message
/** Constructor
- @param method The request-method to use
+ @param method The request-method to use.
@param target The request-target.
- @param version The HTTP-version
+ @param version The HTTP-version.
@note This function is only available when `isRequest == true`.
*/
@@ -561,11 +566,11 @@ struct message
/** Constructor
- @param method The request-method to use
+ @param method The request-method to use.
@param target The request-target.
- @param version The HTTP-version
+ @param version The HTTP-version.
@param body_arg An argument forwarded to the `body` constructor.
@@ -585,11 +590,11 @@ struct message
/** Constructor
- @param method The request-method to use
+ @param method The request-method to use.
@param target The request-target.
- @param version The HTTP-version
+ @param version The HTTP-version.
@param body_arg An argument forwarded to the `body` constructor.
@@ -611,9 +616,9 @@ struct message
/** Constructor
- @param result The status-code for the response
+ @param result The status-code for the response.
- @param version The HTTP-version
+ @param version The HTTP-version.
@note This member is only available when `isRequest == false`.
*/
@@ -628,9 +633,9 @@ struct message
/** Constructor
- @param result The status-code for the response
+ @param result The status-code for the response.
- @param version The HTTP-version
+ @param version The HTTP-version.
@param body_arg An argument forwarded to the `body` constructor.
@@ -648,9 +653,9 @@ struct message
/** Constructor
- @param result The status-code for the response
+ @param result The status-code for the response.
- @param version The HTTP-version
+ @param version The HTTP-version.
@param body_arg An argument forwarded to the `body` constructor.
@@ -722,7 +727,7 @@ struct message
/** Set or clear the chunked Transfer-Encoding
- This function will set or removed the "chunked" transfer
+ This function will set or remove the "chunked" transfer
encoding as the last item in the list of encodings in the
field.
@@ -804,7 +809,7 @@ struct message
@li @ref chunked would return `true`
@li @ref result returns @ref status::no_content
-
+
@li @ref result returns @ref status::not_modified
@li @ref result returns any informational status class (100 to 199)
@@ -821,7 +826,7 @@ struct message
/** Returns the payload size of the body in octets if possible.
- This function invokes the @b Body algorithm to measure
+ This function invokes the <em>Body</em> algorithm to measure
the number of octets in the serialized body container. If
there is no body, this will return zero. Otherwise, if the
body exists but is not known ahead of time, `boost::none`
@@ -893,7 +898,7 @@ struct message
private:
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
template<
class... BodyArgs,
@@ -901,7 +906,7 @@ private:
message(
std::piecewise_construct_t,
std::tuple<BodyArgs...>& body_args,
- beast::detail::index_sequence<IBodyArgs...>)
+ mp11::index_sequence<IBodyArgs...>)
: boost::empty_value<
typename Body::value_type>(boost::empty_init_t(),
std::forward<BodyArgs>(
@@ -919,8 +924,8 @@ private:
std::piecewise_construct_t,
std::tuple<BodyArgs...>& body_args,
std::tuple<FieldsArgs...>& fields_args,
- beast::detail::index_sequence<IBodyArgs...>,
- beast::detail::index_sequence<IFieldsArgs...>)
+ mp11::index_sequence<IBodyArgs...>,
+ mp11::index_sequence<IFieldsArgs...>)
: header_type(std::forward<FieldsArgs>(
std::get<IFieldsArgs>(fields_args))...)
, boost::empty_value<
@@ -998,6 +1003,6 @@ swap(
} // beast
} // boost
-#include <boost/beast/http/impl/message.ipp>
+#include <boost/beast/http/impl/message.hpp>
#endif
diff --git a/boost/beast/http/parser.hpp b/boost/beast/http/parser.hpp
index fb7b74f240..9b0523f7e3 100644
--- a/boost/beast/http/parser.hpp
+++ b/boost/beast/http/parser.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -35,7 +35,7 @@ namespace http {
will be parsed.
@tparam Body The type used to represent the body. This must
- meet the requirements of @b Body.
+ meet the requirements of <em>Body</em>.
@tparam Allocator The type of allocator used with the
@ref basic_fields container.
@@ -47,24 +47,21 @@ template<
class Body,
class Allocator = std::allocator<char>>
class parser
- : public basic_parser<isRequest,
- parser<isRequest, Body, Allocator>>
+ : public basic_parser<isRequest>
{
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_reader<Body>::value,
- "BodyReader requirements not met");
+ "BodyReader type requirements not met");
template<bool, class, class>
friend class parser;
- using base_type = basic_parser<isRequest,
- parser<isRequest, Body, Allocator>>;
-
message<isRequest, Body, basic_fields<Allocator>> m_;
typename Body::reader rd_;
bool rd_inited_ = false;
+ bool used_ = false;
std::function<void(
std::uint64_t,
@@ -123,7 +120,7 @@ public:
This constructs a new parser by move constructing the
header from another parser with a different body type. The
constructed-from parser must not have any parsed body octets or
- initialized @b BodyReader, otherwise an exception is generated.
+ initialized <em>BodyReader</em>, otherwise an exception is generated.
@par Example
@code
@@ -297,8 +294,6 @@ public:
}
private:
- friend class basic_parser<isRequest, parser>;
-
parser(std::true_type);
parser(std::false_type);
@@ -338,42 +333,95 @@ private:
string_view method_str,
string_view target,
int version,
- error_code& ec)
+ error_code& ec,
+ std::true_type)
{
- try
- {
- m_.target(target);
- if(method != verb::unknown)
- m_.method(method);
- else
- m_.method_string(method_str);
- ec.assign(0, ec.category());
- }
- catch(std::bad_alloc const&)
+ // If this assert goes off, it means you tried to re-use a
+ // parser after it was done reading a message. This is not
+ // allowed, you need to create a new parser for each message.
+ // The easiest way to do that is to store the parser in
+ // an optional object.
+
+ BOOST_ASSERT(! used_);
+ if(used_)
{
- ec = error::bad_alloc;
+ ec = error::stale_parser;
+ return;
}
+ used_ = true;
+
+ m_.target(target);
+ if(method != verb::unknown)
+ m_.method(method);
+ else
+ m_.method_string(method_str);
m_.version(version);
}
void
+ on_request_impl(
+ verb, string_view, string_view,
+ int, error_code&, std::false_type)
+ {
+ }
+
+ void
+ on_request_impl(
+ verb method,
+ string_view method_str,
+ string_view target,
+ int version,
+ error_code& ec) override
+ {
+ this->on_request_impl(
+ method, method_str, target, version, ec,
+ std::integral_constant<bool, isRequest>{});
+ }
+
+ void
on_response_impl(
int code,
string_view reason,
int version,
- error_code& ec)
+ error_code& ec,
+ std::true_type)
{
- m_.result(code);
- m_.version(version);
- try
+ // If this assert goes off, it means you tried to re-use a
+ // parser after it was done reading a message. This is not
+ // allowed, you need to create a new parser for each message.
+ // The easiest way to do that is to store the parser in
+ // an optional object.
+
+ BOOST_ASSERT(! used_);
+ if(used_)
{
- m_.reason(reason);
- ec.assign(0, ec.category());
- }
- catch(std::bad_alloc const&)
- {
- ec = error::bad_alloc;
+ ec = error::stale_parser;
+ return;
}
+ used_ = true;
+
+ m_.result(code);
+ m_.version(version);
+ m_.reason(reason);
+ }
+
+ void
+ on_response_impl(
+ int, string_view, int,
+ error_code&, std::false_type)
+ {
+ }
+
+ void
+ on_response_impl(
+ int code,
+ string_view reason,
+ int version,
+ error_code& ec) override
+ {
+ this->on_response_impl(
+ code, reason, version, ec,
+ std::integral_constant<bool, ! isRequest>{});
}
void
@@ -381,29 +429,21 @@ private:
field name,
string_view name_string,
string_view value,
- error_code& ec)
+ error_code&) override
{
- try
- {
- m_.insert(name, name_string, value);
- ec.assign(0, ec.category());
- }
- catch(std::bad_alloc const&)
- {
- ec = error::bad_alloc;
- }
+ m_.insert(name, name_string, value);
}
void
- on_header_impl(error_code& ec)
+ on_header_impl(error_code& ec) override
{
- ec.assign(0, ec.category());
+ ec = {};
}
void
on_body_init_impl(
boost::optional<std::uint64_t> const& content_length,
- error_code& ec)
+ error_code& ec) override
{
rd_.init(content_length, ec);
rd_inited_ = true;
@@ -412,9 +452,9 @@ private:
std::size_t
on_body_impl(
string_view body,
- error_code& ec)
+ error_code& ec) override
{
- return rd_.put(boost::asio::buffer(
+ return rd_.put(net::buffer(
body.data(), body.size()), ec);
}
@@ -422,27 +462,27 @@ private:
on_chunk_header_impl(
std::uint64_t size,
string_view extensions,
- error_code& ec)
+ error_code& ec) override
{
if(cb_h_)
return cb_h_(size, extensions, ec);
- ec.assign(0, ec.category());
}
std::size_t
on_chunk_body_impl(
std::uint64_t remain,
string_view body,
- error_code& ec)
+ error_code& ec) override
{
if(cb_b_)
return cb_b_(remain, body, ec);
- return rd_.put(boost::asio::buffer(
+ return rd_.put(net::buffer(
body.data(), body.size()), ec);
}
void
- on_finish_impl(error_code& ec)
+ on_finish_impl(
+ error_code& ec) override
{
rd_.finish(ec);
}
@@ -460,6 +500,6 @@ using response_parser = parser<false, Body, Allocator>;
} // beast
} // boost
-#include <boost/beast/http/impl/parser.ipp>
+#include <boost/beast/http/impl/parser.hpp>
#endif
diff --git a/boost/beast/http/read.hpp b/boost/beast/http/read.hpp
index a4f0efe400..229444be8f 100644
--- a/boost/beast/http/read.hpp
+++ b/boost/beast/http/read.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -20,604 +20,635 @@ namespace boost {
namespace beast {
namespace http {
+//------------------------------------------------------------------------------
+
/** Read part of a message from a stream using a parser.
- This function is used to read part of a message from a stream into a
- subclass of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read part of a message from a stream into an
+ instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li A call to @ref basic_parser::put with a non-empty buffer sequence
- is successful.
+ is successful.
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
@throws system_error Thrown on failure.
+
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read_some(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser);
+ basic_parser<isRequest>& parser);
/** Read part of a message from a stream using a parser.
- This function is used to read part of a message from a stream into a
- subclass of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read part of a message from a stream into an
+ instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li A call to @ref basic_parser::put with a non-empty buffer sequence
- is successful.
+ is successful.
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
-
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- @li @ref error::end_of_stream if no octets were parsed, or
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- The function returns the number of bytes processed from the dynamic
- buffer. The caller should remove these bytes by calling `consume` on
- the dynamic buffer, regardless of any error.
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ support the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
@param ec Set to the error, if any occurred.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
+
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read_some(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
error_code& ec);
/** Read part of a message asynchronously from a stream using a parser.
This function is used to asynchronously read part of a message from
- a stream into a subclass of @ref basic_parser.
- The function call always returns immediately. The asynchronous operation
- will continue until one of the following conditions is true:
+ a stream into an instance of @ref basic_parser. The function call
+ always returns immediately. The asynchronous operation will continue
+ until one of the following conditions is true:
@li A call to @ref basic_parser::put with a non-empty buffer sequence
- is successful.
+ is successful.
@li An error occurs.
- This operation is implemented in terms of zero or more calls to
- the next layer's `async_read_some` function, and is known as a
- <em>composed operation</em>. The program must ensure that the
- stream performs no other reads until this operation completes.
- The implementation may read additional octets that lie past the
- end of the object being parsed. This additional data is stored
- in the stream buffer, which may be used in subsequent calls.
+ This operation is implemented in terms of zero or more calls to the
+ next layer's `async_read_some` function, and is known as a <em>composed
+ operation</em>. The program must ensure that the stream performs no other
+ reads until this operation completes. The implementation may read additional
+ bytes from the stream that lie past the end of the message being read.
+ These additional bytes are stored in the dynamic buffer, which must be
+ preserved for subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b AsyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type
+ must meet the <em>AsyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements. The object must remain valid at least until the handler
+ is called; ownership is not transferred.
- @param parser The parser to use.
- The object must remain valid at least until the
- handler is called; ownership is not transferred.
+ @param parser The parser to use. The object must remain valid at least until
+ the handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
- std::size_t bytes_transferred // the number of bytes transferred to the parser
- ); @endcode
+ std::size_t bytes_transferred // the total number of bytes transferred from the stream
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- The completion handler will receive as a parameter the number
- of octets processed from the dynamic buffer. The octets should
- be removed by calling `consume` on the dynamic buffer after
- the read completes, regardless of any error.
+ @note The completion handler will receive as a parameter the total number
+ of bytes transferred from the stream. This may be zero for the case where
+ there is sufficient pre-existing message data in the dynamic buffer.
*/
template<
class AsyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived,
+ bool isRequest,
class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read_some(
AsyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
ReadHandler&& handler);
//------------------------------------------------------------------------------
-/** Read a header from a stream using a parser.
+/** Read a complete message header from a stream using a parser.
- This function is used to read a header from a stream into a subclass
- of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message header from a stream
+ into an instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
@throws system_error Thrown on failure.
- @note The implementation will call @ref basic_parser::eager
- with the value `false` on the parser passed in.
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `false` on the parser passed in.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read_header(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser);
+ basic_parser<isRequest>& parser);
-/** Read a header from a stream using a parser.
+/** Read a complete message header from a stream using a parser.
- This function is used to read a header from a stream into a subclass
- of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message header from a stream
+ into an instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
@param ec Set to the error, if any occurred.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
- @note The implementation will call @ref basic_parser::eager
- with the value `false` on the parser passed in.
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `false` on the parser passed in.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read_header(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
error_code& ec);
-/** Read a header from a stream asynchronously using a parser.
+/** Read a complete message header asynchronously from a stream using a parser.
- This function is used to asynchronously read a header from a stream
- into a subclass of @ref basic_parser.
- The function call always returns immediately. The asynchronous operation
- will continue until one of the following conditions is true:
+ This function is used to asynchronously read a complete message header from
+ a stream into an instance of @ref basic_parser. The function call always
+ returns immediately. The asynchronous operation will continue until one of
+ the following conditions is true:
@li @ref basic_parser::is_header_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or more calls to
- the stream's `async_read_some` function, and is known as a
- <em>composed operation</em>. The program must ensure that the
- stream performs no other reads until this operation completes.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of zero or more calls to the
+ next layer's `async_read_some` function, and is known as a <em>composed
+ operation</em>. The program must ensure that the stream performs no other
+ reads until this operation completes. The implementation may read additional
+ bytes from the stream that lie past the end of the message being read.
+ These additional bytes are stored in the dynamic buffer, which must be
+ preserved for subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b AsyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type
+ must meet the <em>AsyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements. The object must remain valid at least until the handler
+ is called; ownership is not transferred.
- @param parser The parser to use.
- The object must remain valid at least until the
- handler is called; ownership is not transferred.
-
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
- error_code const& error, // result of operation,
- std::size_t bytes_transferred // the number of bytes transferred to the parser
- ); @endcode
+ @param parser The parser to use. The object must remain valid at least until
+ the handler is called; ownership is not transferred.
+
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
+ error_code const& error, // result of operation
+ std::size_t bytes_transferred // the total number of bytes transferred from the stream
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @note The implementation will call @ref basic_parser::eager
- with the value `false` on the parser passed in.
+ @note The completion handler will receive as a parameter the total number
+ of bytes transferred from the stream. This may be zero for the case where
+ there is sufficient pre-existing message data in the dynamic buffer. The
+ implementation will call @ref basic_parser::eager with the value `false`
+ on the parser passed in.
*/
template<
class AsyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived,
+ bool isRequest,
class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read_header(
AsyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
ReadHandler&& handler);
//------------------------------------------------------------------------------
/** Read a complete message from a stream using a parser.
- This function is used to read a complete message from a stream into a
- subclass of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message from a stream into an
+ instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li @ref basic_parser::is_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
@throws system_error Thrown on failure.
- @note The implementation will call @ref basic_parser::eager
- with the value `true` on the parser passed in.
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `true` on the parser passed in.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser);
+ basic_parser<isRequest>& parser);
/** Read a complete message from a stream using a parser.
- This function is used to read a complete message from a stream into a
- subclass of @ref basic_parser.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message from a stream into an
+ instance of @ref basic_parser. The call will block until one of the
+ following conditions is true:
@li @ref basic_parser::is_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
@param parser The parser to use.
@param ec Set to the error, if any occurred.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
- @note The implementation will call @ref basic_parser::eager
- with the value `true` on the parser passed in.
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `true` on the parser passed in.
*/
template<
class SyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived>
+ bool isRequest>
std::size_t
read(
SyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
error_code& ec);
-/** Read a complete message from a stream asynchronously using a parser.
+/** Read a complete message asynchronously from a stream using a parser.
This function is used to asynchronously read a complete message from a
- stream into a subclass of @ref basic_parser.
- The function call always returns immediately. The asynchronous operation
- will continue until one of the following conditions is true:
+ stream into an instance of @ref basic_parser. The function call always
+ returns immediately. The asynchronous operation will continue until one
+ of the following conditions is true:
@li @ref basic_parser::is_done returns `true`
@li An error occurs.
- This operation is implemented in terms of one or more calls to
- the stream's `async_read_some` function, and is known as a
- <em>composed operation</em>. The program must ensure that the
- stream performs no other reads until this operation completes.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of zero or more calls to the
+ next layer's `async_read_some` function, and is known as a <em>composed
+ operation</em>. The program must ensure that the stream performs no other
+ reads until this operation completes. The implementation may read additional
+ bytes from the stream that lie past the end of the message being read.
+ These additional bytes are stored in the dynamic buffer, which must be
+ preserved for subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b AsyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type
+ must meet the <em>AsyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements. The object must remain valid at least until the handler
+ is called; ownership is not transferred.
- @param parser The parser to use.
- The object must remain valid at least until the
- handler is called; ownership is not transferred.
-
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
- error_code const& error, // result of operation,
- std::size_t bytes_transferred // the number of bytes transferred to the parser
- ); @endcode
+ @param parser The parser to use. The object must remain valid at least until
+ the handler is called; ownership is not transferred.
+
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
+ error_code const& error, // result of operation
+ std::size_t bytes_transferred // the total number of bytes transferred from the stream
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @note The implementation will call @ref basic_parser::eager
- with the value `true` on the parser passed in.
+ @note The completion handler will receive as a parameter the total number
+ of bytes transferred from the stream. This may be zero for the case where
+ there is sufficient pre-existing message data in the dynamic buffer. The
+ implementation will call @ref basic_parser::eager with the value `true`
+ on the parser passed in.
*/
template<
class AsyncReadStream,
class DynamicBuffer,
- bool isRequest, class Derived,
+ bool isRequest,
class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
- basic_parser<isRequest, Derived>& parser,
+ basic_parser<isRequest>& parser,
ReadHandler&& handler);
//------------------------------------------------------------------------------
/** Read a complete message from a stream.
- This function is used to read a complete message from a stream using HTTP/1.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message from a stream into an
+ instance of @ref message. The call will block until one of the following
+ conditions is true:
- @li The entire message is read.
+ @li The entire message is read in.
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
- @param msg An object in which to store the message contents.
- This object should not have previous contents, otherwise
- the behavior is undefined.
- The type must be @b MoveAssignable and @b MoveConstructible.
+ @param msg The container in which to store the message contents. This
+ message container should not have previous contents, otherwise the behavior
+ is undefined. The type must be meet the <em>MoveAssignable</em> and
+ <em>MoveConstructible</em> requirements.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
@throws system_error Thrown on failure.
+
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `true` on the parser passed in.
*/
template<
class SyncReadStream,
@@ -631,47 +662,53 @@ read(
/** Read a complete message from a stream.
- This function is used to read a complete message from a stream using HTTP/1.
- The call will block until one of the following conditions is true:
+ This function is used to read a complete message from a stream into an
+ instance of @ref message. The call will block until one of the following
+ conditions is true:
- @li The entire message is read.
+ @li The entire message is read in.
@li An error occurs.
- This operation is implemented in terms of one or
- more calls to the stream's `read_some` function.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
+ This operation is implemented in terms of one or more calls to the stream's
+ `read_some` function. The implementation may read additional bytes from
+ the stream that lie past the end of the message being read. These additional
+ bytes are stored in the dynamic buffer, which must be preserved for
+ subsequent reads.
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
- @li @ref error::end_of_stream if no octets were parsed, or
+ @li @ref error::end_of_stream if no bytes were parsed, or
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
- @param stream The stream from which the data is to be read.
- The type must support the @b SyncReadStream concept.
+ @param stream The stream from which the data is to be read. The type must
+ meet the <em>SyncReadStream</em> requirements.
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements.
- @param msg An object in which to store the message contents.
- This object should not have previous contents, otherwise
- the behavior is undefined.
- The type must be @b MoveAssignable and @b MoveConstructible.
+ @param msg The container in which to store the message contents. This
+ message container should not have previous contents, otherwise the behavior
+ is undefined. The type must be meet the <em>MoveAssignable</em> and
+ <em>MoveConstructible</em> requirements.
@param ec Set to the error, if any occurred.
- @return The number of bytes transferred to the parser.
+ @return The number of bytes transferred from the stream.
+
+ @note The function returns the total number of bytes transferred from the
+ stream. This may be zero for the case where there is sufficient pre-existing
+ message data in the dynamic buffer. The implementation will call
+ @ref basic_parser::eager with the value `true` on the parser passed in.
*/
template<
class SyncReadStream,
@@ -684,72 +721,79 @@ read(
message<isRequest, Body, basic_fields<Allocator>>& msg,
error_code& ec);
-/** Read a complete message from a stream asynchronously.
+/** Read a complete message asynchronously from a stream.
This function is used to asynchronously read a complete message from a
- stream using HTTP/1.
- The function call always returns immediately. The asynchronous operation
- will continue until one of the following conditions is true:
+ stream into an instance of @ref message. The function call always returns
+ immediately. The asynchronous operation will continue until one of the
+ following conditions is true:
- @li The entire message is read.
+ @li The entire message is read in.
@li An error occurs.
- This operation is implemented in terms of one or more calls to
- the stream's `async_read_some` function, and is known as a
- <em>composed operation</em>. The program must ensure that the
- stream performs no other reads until this operation completes.
- The implementation may read additional octets that lie past the
- end of the message being read. This additional data is stored
- in the dynamic buffer, which must be retained for subsequent reads.
-
- If the stream returns the error `boost::asio::error::eof` indicating the
- end of file during a read, the error returned from this function will be:
-
- @li @ref error::end_of_stream if no octets were parsed, or
-
- @li @ref error::partial_message if any octets were parsed but the
- message was incomplete, otherwise:
-
- @li A successful result. A subsequent attempt to read will
- return @ref error::end_of_stream
-
- @param stream The stream from which the data is to be read.
- The type must support the @b AsyncReadStream concept.
-
- @param buffer A @b DynamicBuffer holding additional bytes
- read by the implementation from the stream. This is both
- an input and an output parameter; on entry, any data in the
- dynamic buffer's input sequence will be given to the parser
- first.
-
- @param msg An object in which to store the message contents.
- This object should not have previous contents, otherwise
- the behavior is undefined.
- The type must be @b MoveAssignable and @b MoveConstructible.
-
- The object must remain valid at least until the
- handler is called; ownership is not transferred.
-
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
- error_code const& error, // result of operation,
- std::size_t bytes_transferred // the number of bytes transferred to the parser
- ); @endcode
+ This operation is implemented in terms of zero or more calls to the
+ next layer's `async_read_some` function, and is known as a <em>composed
+ operation</em>. The program must ensure that the stream performs no other
+ reads until this operation completes. The implementation may read additional
+ bytes from the stream that lie past the end of the message being read.
+ These additional bytes are stored in the dynamic buffer, which must be
+ preserved for subsequent reads.
+
+ If the end of file error is received while reading from the stream, then
+ the error returned from this function will be:
+
+ @li @ref error::end_of_stream if no bytes were parsed, or
+
+ @li @ref error::partial_message if any bytes were parsed but the
+ message was incomplete, otherwise:
+
+ @li A successful result. The next attempt to read will return
+ @ref error::end_of_stream
+
+ @param stream The stream from which the data is to be read. The type
+ must meet the <em>AsyncReadStream</em> requirements.
+
+ @param buffer Storage for additional bytes read by the implementation from
+ the stream. This is both an input and an output parameter; on entry, the
+ parser will be presented with any remaining data in the dynamic buffer's
+ readable bytes sequence first. The type must meet the <em>DynamicBuffer</em>
+ requirements. The object must remain valid at least until the handler
+ is called; ownership is not transferred.
+
+ @param msg The container in which to store the message contents. This
+ message container should not have previous contents, otherwise the behavior
+ is undefined. The type must be meet the <em>MoveAssignable</em> and
+ <em>MoveConstructible</em> requirements. The object must remain valid
+ at least until the handler is called; ownership is not transferred.
+
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
+ error_code const& error, // result of operation
+ std::size_t bytes_transferred // the total number of bytes transferred from the stream
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
+
+ @note The completion handler will receive as a parameter the total number
+ of bytes transferred from the stream. This may be zero for the case where
+ there is sufficient pre-existing message data in the dynamic buffer. The
+ implementation will call @ref basic_parser::eager with the value `true`
+ on the parser passed in.
*/
template<
class AsyncReadStream,
class DynamicBuffer,
bool isRequest, class Body, class Allocator,
class ReadHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- ReadHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
async_read(
AsyncReadStream& stream,
DynamicBuffer& buffer,
@@ -760,6 +804,6 @@ async_read(
} // beast
} // boost
-#include <boost/beast/http/impl/read.ipp>
+#include <boost/beast/http/impl/read.hpp>
#endif
diff --git a/boost/beast/http/rfc7230.hpp b/boost/beast/http/rfc7230.hpp
index 952cb929d6..bc2498db52 100644
--- a/boost/beast/http/rfc7230.hpp
+++ b/boost/beast/http/rfc7230.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -66,7 +66,7 @@ public:
/// A constant iterator to the list
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
class const_iterator;
#endif
@@ -155,7 +155,7 @@ public:
/// A constant iterator to the list
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
class const_iterator;
#endif
@@ -243,7 +243,7 @@ public:
/// A constant iterator to the list
#if BOOST_BEAST_DOXYGEN
- using const_iterator = implementation_defined;
+ using const_iterator = __implementation_defined__;
#else
class const_iterator;
#endif
@@ -324,6 +324,6 @@ validate_list(detail::basic_parsed_list<
} // beast
} // boost
-#include <boost/beast/http/impl/rfc7230.ipp>
+#include <boost/beast/http/impl/rfc7230.hpp>
#endif
diff --git a/boost/beast/http/serializer.hpp b/boost/beast/http/serializer.hpp
index 352e735fe5..f2922608c7 100644
--- a/boost/beast/http/serializer.hpp
+++ b/boost/beast/http/serializer.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -15,7 +15,6 @@
#include <boost/beast/core/buffers_prefix.hpp>
#include <boost/beast/core/buffers_suffix.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/core/detail/variant.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/chunk_encode.hpp>
@@ -58,18 +57,18 @@ class serializer
{
public:
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
static_assert(is_body_writer<Body>::value,
- "BodyWriter requirements not met");
+ "BodyWriter type requirements not met");
/** The type of message this serializer uses
This may be const or non-const depending on the
- implementation of the corresponding @b BodyWriter.
+ implementation of the corresponding <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using value_type = implementation_defined;
+ using value_type = __implementation_defined__;
#else
using value_type = typename std::conditional<
std::is_constructible<typename Body::writer,
@@ -130,7 +129,7 @@ private:
using cb4_t = buffers_suffix<buffers_cat_view<
typename Fields::writer::const_buffers_type,// header
detail::chunk_size, // chunk-size
- boost::asio::const_buffer, // chunk-ext
+ net::const_buffer, // chunk-ext
chunk_crlf, // crlf
typename writer::const_buffers_type, // body
chunk_crlf>>; // crlf
@@ -138,7 +137,7 @@ private:
using cb5_t = buffers_suffix<buffers_cat_view<
detail::chunk_size, // chunk-header
- boost::asio::const_buffer, // chunk-ext
+ net::const_buffer, // chunk-ext
chunk_crlf, // crlf
typename writer::const_buffers_type, // body
chunk_crlf>>; // crlf
@@ -146,30 +145,30 @@ private:
using cb6_t = buffers_suffix<buffers_cat_view<
detail::chunk_size, // chunk-header
- boost::asio::const_buffer, // chunk-size
+ net::const_buffer, // chunk-size
chunk_crlf, // crlf
typename writer::const_buffers_type, // body
chunk_crlf, // crlf
- boost::asio::const_buffer, // chunk-final
- boost::asio::const_buffer, // trailers
+ net::const_buffer, // chunk-final
+ net::const_buffer, // trailers
chunk_crlf>>; // crlf
using pcb6_t = buffers_prefix_view<cb6_t const&>;
using cb7_t = buffers_suffix<buffers_cat_view<
typename Fields::writer::const_buffers_type,// header
detail::chunk_size, // chunk-size
- boost::asio::const_buffer, // chunk-ext
+ net::const_buffer, // chunk-ext
chunk_crlf, // crlf
typename writer::const_buffers_type, // body
chunk_crlf, // crlf
- boost::asio::const_buffer, // chunk-final
- boost::asio::const_buffer, // trailers
+ net::const_buffer, // chunk-final
+ net::const_buffer, // trailers
chunk_crlf>>; // crlf
using pcb7_t = buffers_prefix_view<cb7_t const&>;
using cb8_t = buffers_suffix<buffers_cat_view<
- boost::asio::const_buffer, // chunk-final
- boost::asio::const_buffer, // trailers
+ net::const_buffer, // chunk-final
+ net::const_buffer, // trailers
chunk_crlf>>; // crlf
using pcb8_t = buffers_prefix_view<cb8_t const&>;
@@ -187,7 +186,7 @@ private:
int s_ = do_construct;
bool split_ = false;
bool header_done_ = false;
- bool more_;
+ bool more_ = false;
public:
/// Constructor
@@ -295,7 +294,7 @@ public:
/** Returns the next set of buffers in the serialization.
This function will attempt to call the `visit` function
- object with a @b ConstBufferSequence of unspecified type
+ object with a <em>ConstBufferSequence</em> of unspecified type
representing the next set of buffers in the serialization
of the message represented by this object.
@@ -337,7 +336,7 @@ public:
void
consume(std::size_t n);
- /** Provides low-level access to the associated @b BodyWriter
+ /** Provides low-level access to the associated <em>BodyWriter</em>
This function provides access to the instance of the writer
associated with the body and created by the serializer
@@ -366,6 +365,6 @@ using response_serializer = serializer<false, Body, Fields>;
} // beast
} // boost
-#include <boost/beast/http/impl/serializer.ipp>
+#include <boost/beast/http/impl/serializer.hpp>
#endif
diff --git a/boost/beast/http/span_body.hpp b/boost/beast/http/span_body.hpp
index f20481164e..a0d32f8470 100644
--- a/boost/beast/http/span_body.hpp
+++ b/boost/beast/http/span_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -11,6 +11,7 @@
#define BOOST_BEAST_HTTP_SPAN_BODY_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/span.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
@@ -20,7 +21,7 @@ namespace boost {
namespace beast {
namespace http {
-/** A @b Body using @ref span
+/** A <em>Body</em> using @ref span
This body uses @ref span as a memory-based container for
holding message payloads. The container represents a
@@ -61,10 +62,10 @@ public:
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
class reader
{
@@ -87,7 +88,7 @@ public:
ec = error::buffer_overflow;
return;
}
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -95,17 +96,15 @@ public:
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 n = buffer_bytes(buffers);
auto const len = body_.size();
if(n > len)
{
ec = error::buffer_overflow;
return 0;
}
- ec.assign(0, ec.category());
- buffer_copy(boost::asio::buffer(
+ ec = {};
+ net::buffer_copy(net::buffer(
body_.data(), n), buffers);
body_ = value_type{
body_.data() + n, body_.size() - n};
@@ -115,17 +114,17 @@ public:
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer
{
@@ -133,7 +132,7 @@ public:
public:
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
explicit
@@ -145,13 +144,13 @@ public:
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
return {{
{ body_.data(),
body_.size() * sizeof(typename
diff --git a/boost/beast/http/status.hpp b/boost/beast/http/status.hpp
index 8d7938ca0c..2e9b7da762 100644
--- a/boost/beast/http/status.hpp
+++ b/boost/beast/http/status.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -30,7 +30,16 @@ enum class status : unsigned
unknown = 0,
continue_ = 100,
+
+ /** Switching Protocols
+
+ This status indicates that a request to switch to a new
+ protocol was accepted and applied by the server. A successful
+ response to a WebSocket Upgrade HTTP request will have this
+ code.
+ */
switching_protocols = 101,
+
processing = 102,
ok = 200,
@@ -125,6 +134,7 @@ enum class status_class : unsigned
If the integer does not match a known status code,
@ref status::unknown is returned.
*/
+BOOST_BEAST_DECL
status
int_to_status(unsigned v);
@@ -135,6 +145,7 @@ int_to_status(unsigned v);
@return The status class. If the integer does not match
a known status class, @ref status_class::unknown is returned.
*/
+BOOST_BEAST_DECL
status_class
to_status_class(unsigned v);
@@ -144,6 +155,7 @@ to_status_class(unsigned v);
@return The status class.
*/
+BOOST_BEAST_DECL
status_class
to_status_class(status v);
@@ -151,10 +163,12 @@ to_status_class(status v);
@param v The status code to use.
*/
+BOOST_BEAST_DECL
string_view
obsolete_reason(status v);
/// Outputs the standard reason phrase of a status code to a stream.
+BOOST_BEAST_DECL
std::ostream&
operator<<(std::ostream&, status);
@@ -162,6 +176,8 @@ operator<<(std::ostream&, status);
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/http/impl/status.ipp>
+#endif
#endif
diff --git a/boost/beast/http/string_body.hpp b/boost/beast/http/string_body.hpp
index 1e37aa0dc5..73a01a41fd 100644
--- a/boost/beast/http/string_body.hpp
+++ b/boost/beast/http/string_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -11,8 +11,11 @@
#define BOOST_BEAST_HTTP_STRING_BODY_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
+#include <boost/beast/core/buffers_range.hpp>
+#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
@@ -27,7 +30,7 @@ namespace boost {
namespace beast {
namespace http {
-/** A @b Body using `std::basic_string`
+/** A <em>Body</em> using `std::basic_string`
This body uses `std::basic_string` as a memory-based container
for holding message payloads. Messages using this body type
@@ -69,10 +72,10 @@ public:
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
class reader
{
@@ -92,23 +95,14 @@ public:
{
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&)
+ if(*length > body_.max_size())
{
ec = error::buffer_overflow;
return;
}
+ body_.reserve(beast::detail::clamp(*length));
}
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -116,22 +110,18 @@ public:
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 extra = buffer_bytes(buffers);
auto const size = body_.size();
- try
- {
- body_.resize(size + extra);
- }
- catch(std::exception const&)
+ if (extra > body_.max_size() - size)
{
ec = error::buffer_overflow;
return 0;
}
- ec.assign(0, ec.category());
+
+ body_.resize(size + extra);
+ ec = {};
CharT* dest = &body_[size];
- for(auto b : beast::detail::buffers_range(buffers))
+ for(auto b : beast::buffers_range_ref(buffers))
{
Traits::copy(dest, static_cast<
CharT const*>(b.data()), b.size());
@@ -143,17 +133,17 @@ public:
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer
{
@@ -161,7 +151,7 @@ public:
public:
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
explicit
@@ -173,13 +163,13 @@ public:
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
return {{const_buffers_type{
body_.data(), body_.size()}, false}};
}
@@ -187,7 +177,7 @@ public:
#endif
};
-/// A @b Body using `std::string`
+/// A <em>Body</em> using `std::string`
using string_body = basic_string_body<char>;
} // http
diff --git a/boost/beast/http/type_traits.hpp b/boost/beast/http/type_traits.hpp
index d3b897f894..b8bfdbaaa1 100644
--- a/boost/beast/http/type_traits.hpp
+++ b/boost/beast/http/type_traits.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -13,7 +13,6 @@
#include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/error.hpp>
#include <boost/beast/core/string.hpp>
-#include <boost/beast/core/type_traits.hpp>
#include <boost/beast/http/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
@@ -25,14 +24,14 @@ namespace beast {
namespace http {
template<bool, class, class>
-struct message;
+class message;
-/** Determine if `T` meets the requirements of @b Body.
+/** Determine if a type meets the <em>Body</em> named requirements.
- This metafunction is equivalent to `std::true_type`
- if `T` has a nested type named `value_type`.
+ This alias template is `std::true_type` if `T` meets
+ the requirements, otherwise it is `std::false_type`.
- @tparam T The body type to test.
+ @tparam T The type to test.
@par Example
@code
@@ -40,24 +39,24 @@ struct message;
void check_body(message<isRequest, Body, Fields> const&)
{
static_assert(is_body<Body>::value,
- "Body requirements not met");
+ "Body type requirements not met");
}
@endcode
*/
template<class T>
#if BOOST_BEAST_DOXYGEN
-struct is_body : std::integral_constant<bool, ...>{};
+using is_body = __see_below__;
#else
using is_body = detail::has_value_type<T>;
#endif
-/** Determine if a @b Body type has a reader.
+/** Determine if a type has a nested <em>BodyWriter</em>.
- This metafunction is equivalent to `std::true_type` if:
+ This alias template is `std::true_type` when:
- @li `T` has a nested type named `reader`
+ @li `T` has a nested type named `writer`
- @li The nested type meets the requirements of @b BodyWriter.
+ @li `writer` meets the requirements of <em>BodyWriter</em>.
@tparam T The body type to test.
@@ -73,7 +72,7 @@ using is_body = detail::has_value_type<T>;
*/
#if BOOST_BEAST_DOXYGEN
template<class T>
-struct is_body_writer : std::integral_constant<bool, ...> {};
+using is_body_writer = __see_below__;
#else
template<class T, class = void>
struct is_body_writer : std::false_type {};
@@ -88,7 +87,7 @@ struct is_body_writer<T, beast::detail::void_t<
typename T::writer::const_buffers_type, bool>>&>() =
std::declval<typename T::writer>().get(std::declval<error_code&>())
)>> : std::integral_constant<bool,
- boost::asio::is_const_buffer_sequence<
+ net::is_const_buffer_sequence<
typename T::writer::const_buffers_type>::value && (
(std::is_constructible<typename T::writer,
header<true, detail::fields_model>&,
@@ -100,11 +99,19 @@ struct is_body_writer<T, beast::detail::void_t<
> {};
#endif
-/** Returns true if the writer for a @b Body mutates the body container.
+/** Determine if a type has a nested <em>BodyWriter</em>.
+
+ This alias template is `std::true_type` when:
+
+ @li `T` has a nested type named `writer`
+
+ @li `writer` meets the requirements of <em>BodyWriter</em>.
+
+ @tparam T The body type to test.
*/
#if BOOST_BEAST_DOXYGEN
template<class T>
-struct is_mutable_body_writer : std::integral_constant<bool, ...> {};
+using is_mutable_body_writer = __see_below__;
#else
template<class T, class = void>
struct is_mutable_body_writer : std::false_type {};
@@ -119,7 +126,7 @@ struct is_mutable_body_writer<T, beast::detail::void_t<
typename T::writer::const_buffers_type, bool>>&>() =
std::declval<typename T::writer>().get(std::declval<error_code&>())
)>> : std::integral_constant<bool,
- boost::asio::is_const_buffer_sequence<
+ net::is_const_buffer_sequence<
typename T::writer::const_buffers_type>::value && ((
std::is_constructible<typename T::writer,
header<true, detail::fields_model>&,
@@ -137,13 +144,13 @@ struct is_mutable_body_writer<T, beast::detail::void_t<
>{};
#endif
-/** Determine if a @b Body type has a reader.
+/** Determine if a type has a nested <em>BodyReader</em>.
- This metafunction is equivalent to `std::true_type` if:
+ This alias template is `std::true_type` when:
@li `T` has a nested type named `reader`
- @li The nested type meets the requirements of @b BodyReader.
+ @li `reader` meets the requirements of <em>BodyReader</em>.
@tparam T The body type to test.
@@ -159,7 +166,7 @@ struct is_mutable_body_writer<T, beast::detail::void_t<
*/
#if BOOST_BEAST_DOXYGEN
template<class T>
-struct is_body_reader : std::integral_constant<bool, ...> {};
+using is_body_reader = __see_below__;
#else
template<class T, class = void>
struct is_body_reader : std::false_type {};
@@ -171,7 +178,7 @@ struct is_body_reader<T, beast::detail::void_t<decltype(
std::declval<error_code&>()),
std::declval<std::size_t&>() =
std::declval<typename T::reader&>().put(
- std::declval<boost::asio::const_buffer>(),
+ std::declval<net::const_buffer>(),
std::declval<error_code&>()),
std::declval<typename T::reader&>().finish(
std::declval<error_code&>())
@@ -187,25 +194,25 @@ struct is_body_reader<T, beast::detail::void_t<decltype(
};
#endif
-/** Determine if `T` meets the requirements of @b Fields
+/** Determine if a type meets the <em>Fields</em> named requirements.
- @tparam T The body type to test.
+ This alias template is `std::true_type` if `T` meets
+ the requirements, otherwise it is `std::false_type`.
- @par Example
+ @tparam T The type to test.
+ @par Example
Use with `static_assert`:
-
@code
template<bool isRequest, class Body, class Fields>
void f(message<isRequest, Body, Fields> const&)
{
static_assert(is_fields<Fields>::value,
- "Fields requirements not met");
+ "Fields type requirements not met");
...
@endcode
Use with `std::enable_if` (SFINAE):
-
@code
template<bool isRequest, class Body, class Fields>
typename std::enable_if<is_fields<Fields>::value>::type
@@ -214,7 +221,7 @@ struct is_body_reader<T, beast::detail::void_t<decltype(
*/
#if BOOST_BEAST_DOXYGEN
template<class T>
-struct is_fields : std::integral_constant<bool, ...> {};
+using is_fields = __see_below__;
#else
template<class T>
using is_fields = typename detail::is_fields_helper<T>::type;
diff --git a/boost/beast/http/vector_body.hpp b/boost/beast/http/vector_body.hpp
index 40c885e43e..b44ef0f625 100644
--- a/boost/beast/http/vector_body.hpp
+++ b/boost/beast/http/vector_body.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -11,8 +11,10 @@
#define BOOST_BEAST_HTTP_VECTOR_BODY_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/message.hpp>
+#include <boost/beast/core/detail/clamp.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/optional.hpp>
@@ -27,7 +29,7 @@ namespace boost {
namespace beast {
namespace http {
-/** A @b Body using `std::vector`
+/** A <em>Body</em> using `std::vector`
This body uses `std::vector` as a memory-based container
for holding message payloads. Messages using this body type
@@ -64,10 +66,10 @@ public:
/** The algorithm for parsing the body
- Meets the requirements of @b BodyReader.
+ Meets the requirements of <em>BodyReader</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using reader = implementation_defined;
+ using reader = __implementation_defined__;
#else
class reader
{
@@ -87,23 +89,14 @@ public:
{
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&)
+ if(*length > body_.max_size())
{
ec = error::buffer_overflow;
return;
}
+ body_.reserve(beast::detail::clamp(*length));
}
- ec.assign(0, ec.category());
+ ec = {};
}
template<class ConstBufferSequence>
@@ -111,38 +104,34 @@ public:
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 n = buffer_bytes(buffers);
auto const len = body_.size();
- try
- {
- body_.resize(len + n);
- }
- catch(std::exception const&)
+ if (n > body_.max_size() - len)
{
ec = error::buffer_overflow;
return 0;
}
- ec.assign(0, ec.category());
- return buffer_copy(boost::asio::buffer(
+
+ body_.resize(len + n);
+ ec = {};
+ return net::buffer_copy(net::buffer(
&body_[0] + len, n), buffers);
}
void
finish(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
};
#endif
/** The algorithm for serializing the body
- Meets the requirements of @b BodyWriter.
+ Meets the requirements of <em>BodyWriter</em>.
*/
#if BOOST_BEAST_DOXYGEN
- using writer = implementation_defined;
+ using writer = __implementation_defined__;
#else
class writer
{
@@ -150,7 +139,7 @@ public:
public:
using const_buffers_type =
- boost::asio::const_buffer;
+ net::const_buffer;
template<bool isRequest, class Fields>
explicit
@@ -162,13 +151,13 @@ public:
void
init(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
}
boost::optional<std::pair<const_buffers_type, bool>>
get(error_code& ec)
{
- ec.assign(0, ec.category());
+ ec = {};
return {{const_buffers_type{
body_.data(), body_.size()}, false}};
}
diff --git a/boost/beast/http/verb.hpp b/boost/beast/http/verb.hpp
index 1540a243e8..5352851a48 100644
--- a/boost/beast/http/verb.hpp
+++ b/boost/beast/http/verb.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -133,10 +133,12 @@ enum class verb
If the string does not match a known request method,
@ref verb::unknown is returned.
*/
+BOOST_BEAST_DECL
verb
string_to_verb(string_view s);
/// Returns the text representation of a request method verb.
+BOOST_BEAST_DECL
string_view
to_string(verb v);
@@ -152,6 +154,8 @@ operator<<(std::ostream& os, verb v)
} // beast
} // boost
+#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/http/impl/verb.ipp>
+#endif
#endif
diff --git a/boost/beast/http/write.hpp b/boost/beast/http/write.hpp
index 422f93404f..b4d741013c 100644
--- a/boost/beast/http/write.hpp
+++ b/boost/beast/http/write.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -55,7 +55,7 @@ namespace http {
stream.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -97,7 +97,7 @@ write_some(
stream.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -105,7 +105,7 @@ write_some(
@return The number of bytes written to the stream.
- @see @ref async_write_some, @ref serializer
+ @see async_write_some, serializer
*/
template<
class SyncWriteStream,
@@ -143,32 +143,34 @@ write_some(
stream.
@param stream The stream to which the data is to be written.
- The type must support the @b AsyncWriteStream concept.
+ The type must support the <em>AsyncWriteStream</em> concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
- ); @endcode
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @see @ref serializer
+ @see serializer
*/
template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_some(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -190,7 +192,7 @@ async_write_some(
to the stream's `write_some` function.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -201,7 +203,7 @@ async_write_some(
@note The implementation will call @ref serializer::split with
the value `true` on the serializer passed in.
- @see @ref serializer
+ @see serializer
*/
template<
class SyncWriteStream,
@@ -225,7 +227,7 @@ write_header(
to the stream's `write_some` function.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -236,7 +238,7 @@ write_header(
@note The implementation will call @ref serializer::split with
the value `true` on the serializer passed in.
- @see @ref serializer
+ @see serializer
*/
template<
class SyncWriteStream,
@@ -264,35 +266,37 @@ write_header(
until this operation completes.
@param stream The stream to which the data is to be written.
- The type must support the @b AsyncWriteStream concept.
+ The type must support the <em>AsyncWriteStream</em> concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
- ); @endcode
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
@note The implementation will call @ref serializer::split with
the value `true` on the serializer passed in.
- @see @ref serializer
+ @see serializer
*/
template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write_header(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -314,7 +318,7 @@ async_write_header(
to the stream's `write_some` function.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -322,7 +326,7 @@ async_write_header(
@throws system_error Thrown on failure.
- @see @ref serializer
+ @see serializer
*/
template<
class SyncWriteStream,
@@ -346,7 +350,7 @@ write(
to the stream's `write_some` function.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param sr The serializer to use.
@@ -354,7 +358,7 @@ write(
@return The number of bytes written to the stream.
- @see @ref serializer
+ @see serializer
*/
template<
class SyncWriteStream,
@@ -382,32 +386,34 @@ write(
until this operation completes.
@param stream The stream to which the data is to be written.
- The type must support the @b AsyncWriteStream concept.
+ The type must support the <em>AsyncWriteStream</em> concept.
@param sr The serializer to use.
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
- ); @endcode
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @see @ref serializer
+ @see serializer
*/
template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
async_write(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
@@ -429,10 +435,10 @@ async_write(
with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `true`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param msg The message to write.
@@ -440,7 +446,7 @@ async_write(
@throws system_error Thrown on failure.
- @see @ref message
+ @see message
*/
template<
class SyncWriteStream,
@@ -470,10 +476,10 @@ write(
with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `false`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param msg The message to write.
@@ -481,7 +487,7 @@ write(
@throws system_error Thrown on failure.
- @see @ref message
+ @see message
*/
template<
class SyncWriteStream,
@@ -511,10 +517,10 @@ write(
with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `true`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param msg The message to write.
@@ -522,7 +528,7 @@ write(
@return The number of bytes written to the stream.
- @see @ref message
+ @see message
*/
template<
class SyncWriteStream,
@@ -553,10 +559,10 @@ write(
with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `false`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
@param stream The stream to which the data is to be written.
- The type must support the @b SyncWriteStream concept.
+ The type must support the <em>SyncWriteStream</em> concept.
@param msg The message to write.
@@ -564,7 +570,7 @@ write(
@return The number of bytes written to the stream.
- @see @ref message
+ @see message
*/
template<
class SyncWriteStream,
@@ -598,41 +604,42 @@ write(
@ref serializer with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `true`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `true`.
@param stream The stream to which the data is to be written.
- The type must support the @b AsyncWriteStream concept.
+ The type must support the <em>AsyncWriteStream</em> concept.
@param msg The message to write.
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
- ); @endcode
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @see @ref message
+ @see message
*/
template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
#if BOOST_BEAST_DOXYGEN
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
#else
typename std::enable_if<
is_mutable_body_writer<Body>::value,
- BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))>::type
+ BOOST_BEAST_ASYNC_RESULT2(WriteHandler)>::type
#endif
async_write(
AsyncWriteStream& stream,
@@ -656,41 +663,42 @@ async_write(
@ref serializer with an empty chunk decorator to produce buffers.
@note This function only participates in overload resolution
- if @ref is_mutable_body_writer for @b Body returns `false`.
+ if @ref is_mutable_body_writer for <em>Body</em> returns `false`.
@param stream The stream to which the data is to be written.
- The type must support the @b AsyncWriteStream concept.
+ The type must support the <em>AsyncWriteStream</em> concept.
@param msg The message to write.
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler Invoked when the operation completes.
- The handler may be moved or copied as needed.
- The equivalent function signature of the handler must be:
- @code void handler(
+ @param handler The completion handler to invoke when the operation
+ completes. The implementation takes ownership of the handler by
+ performing a decay-copy. The equivalent function signature of
+ the handler must be:
+ @code
+ void handler(
error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
- ); @endcode
+ );
+ @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
- manner equivalent to using `boost::asio::io_context::post`.
+ manner equivalent to using `net::post`.
- @see @ref message
+ @see message
*/
template<
class AsyncWriteStream,
bool isRequest, class Body, class Fields,
class WriteHandler>
#if BOOST_BEAST_DOXYGEN
-BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))
+BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
#else
typename std::enable_if<
! is_mutable_body_writer<Body>::value,
- BOOST_ASIO_INITFN_RESULT_TYPE(
- WriteHandler, void(error_code, std::size_t))>::type
+ BOOST_BEAST_ASYNC_RESULT2(WriteHandler)>::type
#endif
async_write(
AsyncWriteStream& stream,
@@ -734,6 +742,6 @@ operator<<(std::ostream& os,
} // beast
} // boost
-#include <boost/beast/http/impl/write.ipp>
+#include <boost/beast/http/impl/write.hpp>
#endif