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.hpp10
-rw-r--r--boost/beast/http/basic_file_body.hpp25
-rw-r--r--boost/beast/http/buffer_body.hpp9
-rw-r--r--boost/beast/http/detail/rfc7230.hpp4
-rw-r--r--boost/beast/http/detail/type_traits.hpp16
-rw-r--r--boost/beast/http/empty_body.hpp7
-rw-r--r--boost/beast/http/error.hpp13
-rw-r--r--boost/beast/http/field.hpp1
-rw-r--r--boost/beast/http/fields.hpp44
-rw-r--r--boost/beast/http/impl/basic_parser.ipp10
-rw-r--r--boost/beast/http/impl/field.ipp3
-rw-r--r--boost/beast/http/impl/fields.ipp143
-rw-r--r--boost/beast/http/impl/file_body_win32.ipp79
-rw-r--r--boost/beast/http/impl/parser.ipp88
-rw-r--r--boost/beast/http/impl/read.ipp307
-rw-r--r--boost/beast/http/impl/serializer.ipp88
-rw-r--r--boost/beast/http/impl/status.ipp8
-rw-r--r--boost/beast/http/impl/verb.ipp10
-rw-r--r--boost/beast/http/impl/write.ipp83
-rw-r--r--boost/beast/http/message.hpp10
-rw-r--r--boost/beast/http/parser.hpp59
-rw-r--r--boost/beast/http/read.hpp16
-rw-r--r--boost/beast/http/serializer.hpp56
-rw-r--r--boost/beast/http/span_body.hpp10
-rw-r--r--boost/beast/http/string_body.hpp10
-rw-r--r--boost/beast/http/type_traits.hpp23
-rw-r--r--boost/beast/http/vector_body.hpp10
-rw-r--r--boost/beast/http/write.hpp16
28 files changed, 710 insertions, 448 deletions
diff --git a/boost/beast/http/basic_dynamic_body.hpp b/boost/beast/http/basic_dynamic_body.hpp
index 76c499c554..7d850d76f3 100644
--- a/boost/beast/http/basic_dynamic_body.hpp
+++ b/boost/beast/http/basic_dynamic_body.hpp
@@ -70,9 +70,8 @@ struct basic_dynamic_body
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest,
- basic_dynamic_body, Fields>& msg)
- : body_(msg.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -140,9 +139,8 @@ struct basic_dynamic_body
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- basic_dynamic_body, Fields> const& m)
- : body_(m.body())
+ writer(header<isRequest, Fields> const&, value_type const& b)
+ : body_(b)
{
}
diff --git a/boost/beast/http/basic_file_body.hpp b/boost/beast/http/basic_file_body.hpp
index cec72a8f54..6d1de9a3b8 100644
--- a/boost/beast/http/basic_file_body.hpp
+++ b/boost/beast/http/basic_file_body.hpp
@@ -239,8 +239,8 @@ public:
// Constructor.
//
- // `m` holds the message we are serializing, which will
- // always have the `basic_file_body` as the body type.
+ // `h` holds the headers of the message we are
+ // serializing, while `b` holds the body.
//
// Note that the message is passed by non-const reference.
// This is intentional, because reading from the file
@@ -262,8 +262,7 @@ public:
// a time.
//
template<bool isRequest, class Fields>
- writer(message<
- isRequest, basic_file_body, Fields>& m);
+ writer(header<isRequest, Fields>& h, value_type& b);
// Initializer
//
@@ -296,9 +295,11 @@ template<class File>
template<bool isRequest, class Fields>
basic_file_body<File>::
writer::
-writer(message<isRequest, basic_file_body, Fields>& m)
- : body_(m.body())
+writer(header<isRequest, Fields>& h, value_type& b)
+ : body_(b)
{
+ boost::ignore_unused(h);
+
// The file must already be open
BOOST_ASSERT(body_.file_.is_open());
@@ -398,13 +399,12 @@ public:
//
// This is called after the header is parsed and
// indicates that a non-zero sized body may be present.
- // `m` holds the message we are receiving, which will
- // always have the `basic_file_body` as the body type.
+ // `h` holds the received message headers.
+ // `b` is an instance of `basic_file_body`.
//
template<bool isRequest, class Fields>
explicit
- reader(
- message<isRequest, basic_file_body, Fields>& m);
+ reader(header<isRequest, Fields>&h, value_type& b);
// Initializer
//
@@ -447,9 +447,10 @@ template<class File>
template<bool isRequest, class Fields>
basic_file_body<File>::
reader::
-reader(message<isRequest, basic_file_body, Fields>& m)
- : body_(m.body())
+reader(header<isRequest, Fields>& h, value_type& body)
+ : body_(body)
{
+ boost::ignore_unused(h);
}
template<class File>
diff --git a/boost/beast/http/buffer_body.hpp b/boost/beast/http/buffer_body.hpp
index 675ea9475a..3ffe0a002a 100644
--- a/boost/beast/http/buffer_body.hpp
+++ b/boost/beast/http/buffer_body.hpp
@@ -105,8 +105,8 @@ struct buffer_body
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest, buffer_body, Fields>& m)
- : body_(m.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -167,9 +167,8 @@ struct buffer_body
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- buffer_body, Fields> const& msg)
- : body_(msg.body())
+ writer(header<isRequest, Fields> const&, value_type const& b)
+ : body_(b)
{
}
diff --git a/boost/beast/http/detail/rfc7230.hpp b/boost/beast/http/detail/rfc7230.hpp
index fdabc1a4d6..fac6790579 100644
--- a/boost/beast/http/detail/rfc7230.hpp
+++ b/boost/beast/http/detail/rfc7230.hpp
@@ -352,8 +352,8 @@ increment()
{
it = first;
};
- v.first.clear();
- v.second.clear();
+ v.first = {};
+ v.second = {};
detail::skip_ows(it, last);
first = it;
if(it == last)
diff --git a/boost/beast/http/detail/type_traits.hpp b/boost/beast/http/detail/type_traits.hpp
index c9a06f9784..1d0c991826 100644
--- a/boost/beast/http/detail/type_traits.hpp
+++ b/boost/beast/http/detail/type_traits.hpp
@@ -194,6 +194,22 @@ struct is_fields_helper : T
t10::value && t11::value && t12::value>;
};
+template<class T>
+using has_deprecated_body_writer =
+ std::integral_constant<bool,
+ std::is_constructible<typename T::writer,
+ message<true, T, detail::fields_model>&>::value &&
+ std::is_constructible<typename T::writer,
+ message<false, T, detail::fields_model>&>::value>;
+
+template<class T>
+using has_deprecated_body_reader =
+ std::integral_constant<bool,
+ std::is_constructible<typename T::reader,
+ message<true, T, detail::fields_model>&>::value &&
+ std::is_constructible<typename T::reader,
+ message<false, T, detail::fields_model>&>::value>;
+
} // detail
} // http
} // beast
diff --git a/boost/beast/http/empty_body.hpp b/boost/beast/http/empty_body.hpp
index 1845a22992..d56c14b4ef 100644
--- a/boost/beast/http/empty_body.hpp
+++ b/boost/beast/http/empty_body.hpp
@@ -63,7 +63,7 @@ struct empty_body
{
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest, empty_body, Fields>&)
+ reader(header<isRequest, Fields>&, value_type&)
{
}
@@ -100,12 +100,11 @@ struct empty_body
struct writer
{
using const_buffers_type =
- boost::asio::null_buffers;
+ boost::asio::const_buffer;
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- empty_body, Fields> const&)
+ writer(header<isRequest, Fields> const&, value_type const&)
{
}
diff --git a/boost/beast/http/error.hpp b/boost/beast/http/error.hpp
index 841a99de25..b3d9fb1188 100644
--- a/boost/beast/http/error.hpp
+++ b/boost/beast/http/error.hpp
@@ -22,15 +22,10 @@ enum class error
{
/** The end of the stream was reached.
- This error is returned under the following conditions:
-
- @li When attempting to read HTTP data from a stream and the stream
- read returns the error `boost::asio::error::eof` before any new octets
- have been received.
-
- @li When sending a complete HTTP message at once and the semantics of
- the message are that the connection should be closed to indicate the
- end of the message.
+ This error is returned when attempting to read HTTP data,
+ and the stream returns the error `boost::asio::error::eof`
+ before any octets corresponding to a new HTTP message have
+ been received.
*/
end_of_stream = 1,
diff --git a/boost/beast/http/field.hpp b/boost/beast/http/field.hpp
index 3d1446addc..09d9dfffdf 100644
--- a/boost/beast/http/field.hpp
+++ b/boost/beast/http/field.hpp
@@ -38,6 +38,7 @@ enum class field : unsigned short
access_control_allow_headers,
access_control_allow_methods,
access_control_allow_origin,
+ access_control_expose_headers,
access_control_max_age,
access_control_request_headers,
access_control_request_method,
diff --git a/boost/beast/http/fields.hpp b/boost/beast/http/fields.hpp
index 06c950ee5a..59cb338b83 100644
--- a/boost/beast/http/fields.hpp
+++ b/boost/beast/http/fields.hpp
@@ -14,6 +14,7 @@
#include <boost/beast/core/string_param.hpp>
#include <boost/beast/core/string.hpp>
#include <boost/beast/core/detail/allocator.hpp>
+#include <boost/beast/core/detail/empty_base_optimization.hpp>
#include <boost/beast/http/field.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/intrusive/list.hpp>
@@ -51,7 +52,15 @@ namespace http {
*/
template<class Allocator>
class basic_fields
+#ifndef BOOST_BEAST_DOXYGEN
+ : private beast::detail::empty_base_optimization<Allocator>
+#endif
{
+ // Fancy pointers are not supported
+ static_assert(std::is_pointer<typename
+ std::allocator_traits<Allocator>::pointer>::value,
+ "Allocator must use regular pointers");
+
friend class fields_test; // for `header`
static std::size_t constexpr max_static_buffer = 4096;
@@ -93,7 +102,7 @@ public:
value_type& operator=(value_type const&) = delete;
/// Returns the field enum, which can be @ref field::unknown
- field const
+ field
name() const;
/// Returns the field name as a string
@@ -179,6 +188,19 @@ private:
boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<key_compare>>::type;
+ using align_type = typename
+ boost::type_with_alignment<alignof(value_type)>::type;
+
+ using rebind_type = typename
+ beast::detail::allocator_traits<Allocator>::
+ template rebind_alloc<align_type>;
+
+ using alloc_traits =
+ beast::detail::allocator_traits<rebind_type>;
+
+ using size_type = typename
+ beast::detail::allocator_traits<Allocator>::size_type;
+
public:
/// Destructor
@@ -192,14 +214,14 @@ public:
@param alloc The allocator to use.
*/
explicit
- basic_fields(Allocator const& alloc);
+ basic_fields(Allocator const& alloc) noexcept;
/** Move constructor.
The state of the moved-from object is
as if constructed using the same allocator.
*/
- basic_fields(basic_fields&&);
+ basic_fields(basic_fields&&) noexcept;
/** Move constructor.
@@ -236,7 +258,8 @@ public:
The state of the moved-from object is
as if constructed using the same allocator.
*/
- basic_fields& operator=(basic_fields&&);
+ basic_fields& operator=(basic_fields&&) noexcept(
+ alloc_traits::propagate_on_container_move_assignment::value);
/// Copy assignment.
basic_fields& operator=(basic_fields const&);
@@ -260,7 +283,7 @@ public:
allocator_type
get_allocator() const
{
- return alloc_;
+ return this->member();
}
//--------------------------------------------------------------------------
@@ -681,16 +704,6 @@ private:
template<class OtherAlloc>
friend class basic_fields;
- using base_alloc_type = typename
- beast::detail::allocator_traits<Allocator>::
- template rebind_alloc<value_type>;
-
- using alloc_traits =
- beast::detail::allocator_traits<base_alloc_type>;
-
- using size_type = typename
- beast::detail::allocator_traits<Allocator>::size_type;
-
value_type&
new_element(field name,
string_view sname, string_view value);
@@ -736,7 +749,6 @@ private:
void
swap(basic_fields& other, std::false_type);
- base_alloc_type alloc_;
set_t set_;
list_t list_;
string_view method_;
diff --git a/boost/beast/http/impl/basic_parser.ipp b/boost/beast/http/impl/basic_parser.ipp
index 355a76fb16..39ad3cc68e 100644
--- a/boost/beast/http/impl/basic_parser.ipp
+++ b/boost/beast/http/impl/basic_parser.ipp
@@ -148,7 +148,7 @@ loop:
return 0;
}
state_ = state::start_line;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case state::start_line:
{
@@ -179,7 +179,7 @@ loop:
ec = error::need_more;
goto done;
}
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case state::fields:
@@ -212,7 +212,7 @@ loop:
if(ec)
goto done;
state_ = state::body;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case state::body:
BOOST_ASSERT(! skip_);
@@ -227,7 +227,7 @@ loop:
if(ec)
goto done;
state_ = state::body_to_eof;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case state::body_to_eof:
BOOST_ASSERT(! skip_);
@@ -241,7 +241,7 @@ loop:
if(ec)
goto done;
state_ = state::chunk_header;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case state::chunk_header:
parse_chunk_header(p, n, ec);
diff --git a/boost/beast/http/impl/field.ipp b/boost/beast/http/impl/field.ipp
index 8da470ff24..467a40aeee 100644
--- a/boost/beast/http/impl/field.ipp
+++ b/boost/beast/http/impl/field.ipp
@@ -26,7 +26,7 @@ namespace detail {
struct field_table
{
using array_type =
- std::array<string_view, 352>;
+ std::array<string_view, 353>;
struct hash
{
@@ -104,6 +104,7 @@ struct field_table
"Access-Control-Allow-Headers",
"Access-Control-Allow-Methods",
"Access-Control-Allow-Origin",
+ "Access-Control-Expose-Headers",
"Access-Control-Max-Age",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
diff --git a/boost/beast/http/impl/fields.ipp b/boost/beast/http/impl/fields.ipp
index 67d7cc45b4..a07fd0fa30 100644
--- a/boost/beast/http/impl/fields.ipp
+++ b/boost/beast/http/impl/fields.ipp
@@ -272,8 +272,10 @@ writer(basic_fields const& f,
template<class Allocator>
basic_fields<Allocator>::
value_type::
-value_type(field name,
- string_view sname, string_view value)
+value_type(
+ field name,
+ string_view sname,
+ string_view value)
: off_(static_cast<off_t>(sname.size() + 2))
, len_(static_cast<off_t>(value.size()))
, f_(name)
@@ -285,13 +287,13 @@ value_type(field name,
p[off_-1] = ' ';
p[off_ + len_] = '\r';
p[off_ + len_ + 1] = '\n';
- std::memcpy(p, sname.data(), sname.size());
- std::memcpy(p + off_, value.data(), value.size());
+ sname.copy(p, sname.size());
+ value.copy(p + off_, value.size());
}
template<class Allocator>
inline
-field const
+field
basic_fields<Allocator>::
value_type::
name() const
@@ -349,30 +351,31 @@ basic_fields<Allocator>::
template<class Allocator>
basic_fields<Allocator>::
-basic_fields(Allocator const& alloc)
- : alloc_(alloc)
+basic_fields(Allocator const& alloc) noexcept
+ : beast::detail::empty_base_optimization<Allocator>(alloc)
{
}
template<class Allocator>
basic_fields<Allocator>::
-basic_fields(basic_fields&& other)
- : alloc_(std::move(other.alloc_))
+basic_fields(basic_fields&& other) noexcept
+ : beast::detail::empty_base_optimization<Allocator>(
+ std::move(other.member()))
, set_(std::move(other.set_))
, list_(std::move(other.list_))
, method_(other.method_)
, target_or_reason_(other.target_or_reason_)
{
- other.method_.clear();
- other.target_or_reason_.clear();
+ other.method_ = {};
+ other.target_or_reason_ = {};
}
template<class Allocator>
basic_fields<Allocator>::
basic_fields(basic_fields&& other, Allocator const& alloc)
- : alloc_(alloc)
+ : beast::detail::empty_base_optimization<Allocator>(alloc)
{
- if(alloc_ != other.alloc_)
+ if(this->member() != other.member())
{
copy_all(other);
other.clear_all();
@@ -389,8 +392,8 @@ basic_fields(basic_fields&& other, Allocator const& alloc)
template<class Allocator>
basic_fields<Allocator>::
basic_fields(basic_fields const& other)
- : alloc_(alloc_traits::
- select_on_container_copy_construction(other.alloc_))
+ : beast::detail::empty_base_optimization<Allocator>(alloc_traits::
+ select_on_container_copy_construction(other.member()))
{
copy_all(other);
}
@@ -399,7 +402,7 @@ template<class Allocator>
basic_fields<Allocator>::
basic_fields(basic_fields const& other,
Allocator const& alloc)
- : alloc_(alloc)
+ : beast::detail::empty_base_optimization<Allocator>(alloc)
{
copy_all(other);
}
@@ -417,7 +420,7 @@ template<class OtherAlloc>
basic_fields<Allocator>::
basic_fields(basic_fields<OtherAlloc> const& other,
Allocator const& alloc)
- : alloc_(alloc)
+ : beast::detail::empty_base_optimization<Allocator>(alloc)
{
copy_all(other);
}
@@ -425,9 +428,12 @@ basic_fields(basic_fields<OtherAlloc> const& other,
template<class Allocator>
auto
basic_fields<Allocator>::
-operator=(basic_fields&& other) ->
- basic_fields&
+operator=(basic_fields&& other) noexcept(
+ alloc_traits::propagate_on_container_move_assignment::value)
+ -> basic_fields&
{
+ static_assert(is_nothrow_move_assignable<Allocator>::value,
+ "Allocator must be noexcept assignable.");
if(this == &other)
return *this;
move_assign(other, std::integral_constant<bool,
@@ -605,11 +611,11 @@ basic_fields<Allocator>::
erase(const_iterator pos) ->
const_iterator
{
- auto next = pos.iter();
+ auto next = pos;
auto& e = *next++;
set_.erase(e);
- list_.erase(e);
- delete_element(e);
+ list_.erase(pos);
+ delete_element(const_cast<value_type&>(e));
return next;
}
@@ -1014,13 +1020,13 @@ set_chunked_impl(bool value)
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
std::string s;
#else
- using rebind_type =
+ using A =
typename beast::detail::allocator_traits<
Allocator>::template rebind_alloc<char>;
std::basic_string<
char,
std::char_traits<char>,
- rebind_type> s{rebind_type{alloc_}};
+ A> s{A{this->member()}};
#endif
s.reserve(it->value().size() + 9);
s.append(it->value().data(), it->value().size());
@@ -1051,13 +1057,13 @@ set_chunked_impl(bool value)
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
std::string s;
#else
- using rebind_type =
+ using A =
typename beast::detail::allocator_traits<
Allocator>::template rebind_alloc<char>;
std::basic_string<
char,
std::char_traits<char>,
- rebind_type> s{rebind_type{alloc_}};
+ A> s{A{this->member()}};
#endif
s.reserve(it->value().size());
detail::filter_token_list_last(s, it->value(),
@@ -1108,13 +1114,13 @@ set_keep_alive_impl(
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
std::string s;
#else
- using rebind_type =
+ using A =
typename beast::detail::allocator_traits<
Allocator>::template rebind_alloc<char>;
std::basic_string<
char,
std::char_traits<char>,
- rebind_type> s{rebind_type{alloc_}};
+ A> s{A{this->member()}};
#endif
s.reserve(value.size());
detail::keep_alive_impl(
@@ -1148,13 +1154,14 @@ new_element(field name,
static_cast<off_t>(sname.size() + 2);
std::uint16_t const len =
static_cast<off_t>(value.size());
- auto const p = alloc_traits::allocate(alloc_,
- 1 + (off + len + 2 + sizeof(value_type) - 1) /
- sizeof(value_type));
+ auto a = rebind_type{this->member()};
+ auto const p = alloc_traits::allocate(a,
+ (sizeof(value_type) + off + len + 2 + sizeof(align_type) - 1) /
+ sizeof(align_type));
// VFALCO allocator can't call the constructor because its private
- //alloc_traits::construct(alloc_, p, name, sname, value);
+ //alloc_traits::construct(a, p, name, sname, value);
new(p) value_type{name, sname, value};
- return *p;
+ return *reinterpret_cast<value_type*>(p);
}
template<class Allocator>
@@ -1162,10 +1169,14 @@ void
basic_fields<Allocator>::
delete_element(value_type& e)
{
- auto const n = 1 + (e.off_ + e.len_ + 2 +
- sizeof(value_type) - 1) / sizeof(value_type);
- alloc_traits::destroy(alloc_, &e);
- alloc_traits::deallocate(alloc_, &e, n);
+ auto a = rebind_type{this->member()};
+ auto const n =
+ (sizeof(value_type) + e.off_ + e.len_ + 2 + sizeof(align_type) - 1) /
+ sizeof(align_type);
+ //alloc_traits::destroy(a, &e);
+ e.~value_type();
+ alloc_traits::deallocate(a,
+ reinterpret_cast<align_type*>(&e), n);
}
template<class Allocator>
@@ -1207,19 +1218,20 @@ realloc_string(string_view& dest, string_view s)
return;
auto a = typename beast::detail::allocator_traits<
Allocator>::template rebind_alloc<
- char>(alloc_);
- if(! dest.empty())
+ char>(this->member());
+ char* p = nullptr;
+ if(! s.empty())
{
+ p = a.allocate(s.size());
+ s.copy(p, s.size());
+ }
+ if(! dest.empty())
a.deallocate(const_cast<char*>(
dest.data()), dest.size());
- dest.clear();
- }
- if(! s.empty())
- {
- auto const p = a.allocate(s.size());
- std::memcpy(p, s.data(), s.size());
+ if(p)
dest = {p, s.size()};
- }
+ else
+ dest = {};
}
template<class Allocator>
@@ -1235,20 +1247,21 @@ realloc_target(
return;
auto a = typename beast::detail::allocator_traits<
Allocator>::template rebind_alloc<
- char>(alloc_);
- if(! dest.empty())
- {
- a.deallocate(const_cast<char*>(
- dest.data()), dest.size());
- dest.clear();
- }
+ char>(this->member());
+ char* p = nullptr;
if(! s.empty())
{
- auto const p = a.allocate(1 + s.size());
+ p = a.allocate(1 + s.size());
p[0] = ' ';
- std::memcpy(p + 1, s.data(), s.size());
- dest = {p, 1 + s.size()};
+ s.copy(p + 1, s.size());
}
+ if(! dest.empty())
+ a.deallocate(const_cast<char*>(
+ dest.data()), dest.size());
+ if(p)
+ dest = {p, 1 + s.size()};
+ else
+ dest = {};
}
template<class Allocator>
@@ -1296,9 +1309,9 @@ move_assign(basic_fields& other, std::true_type)
list_ = std::move(other.list_);
method_ = other.method_;
target_or_reason_ = other.target_or_reason_;
- other.method_.clear();
- other.target_or_reason_.clear();
- alloc_ = other.alloc_;
+ other.method_ = {};
+ other.target_or_reason_ = {};
+ this->member() = other.member();
}
template<class Allocator>
@@ -1308,7 +1321,7 @@ basic_fields<Allocator>::
move_assign(basic_fields& other, std::false_type)
{
clear_all();
- if(alloc_ != other.alloc_)
+ if(this->member() != other.member())
{
copy_all(other);
other.clear_all();
@@ -1319,8 +1332,8 @@ move_assign(basic_fields& other, std::false_type)
list_ = std::move(other.list_);
method_ = other.method_;
target_or_reason_ = other.target_or_reason_;
- other.method_.clear();
- other.target_or_reason_.clear();
+ other.method_ = {};
+ other.target_or_reason_ = {};
}
}
@@ -1331,7 +1344,7 @@ basic_fields<Allocator>::
copy_assign(basic_fields const& other, std::true_type)
{
clear_all();
- alloc_ = other.alloc_;
+ this->member() = other.member();
copy_all(other);
}
@@ -1352,7 +1365,7 @@ basic_fields<Allocator>::
swap(basic_fields& other, std::true_type)
{
using std::swap;
- swap(alloc_, other.alloc_);
+ swap(this->member(), other.member());
swap(set_, other.set_);
swap(list_, other.list_);
swap(method_, other.method_);
@@ -1365,7 +1378,7 @@ void
basic_fields<Allocator>::
swap(basic_fields& other, std::false_type)
{
- BOOST_ASSERT(alloc_ == other.alloc_);
+ BOOST_ASSERT(this->member() == other.member());
using std::swap;
swap(set_, other.set_);
swap(list_, other.list_);
diff --git a/boost/beast/http/impl/file_body_win32.ipp b/boost/beast/http/impl/file_body_win32.ipp
index e11c443ed2..627401f531 100644
--- a/boost/beast/http/impl/file_body_win32.ipp
+++ b/boost/beast/http/impl/file_body_win32.ipp
@@ -21,10 +21,12 @@
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_stream_socket.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>
#include <boost/winapi/basic_types.hpp>
+#include <boost/winapi/get_last_error.hpp>
#include <algorithm>
#include <cstring>
@@ -123,9 +125,8 @@ struct basic_file_body<file_win32>
boost::asio::const_buffer;
template<bool isRequest, class Fields>
- writer(message<isRequest,
- basic_file_body<file_win32>, Fields>& m)
- : body_(m.body())
+ writer(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -167,8 +168,8 @@ struct basic_file_body<file_win32>
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest, basic_file_body, Fields>& m)
- : body_(m.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -344,7 +345,7 @@ class write_some_win32_op
public:
write_some_win32_op(write_some_win32_op&&) = default;
- write_some_win32_op(write_some_win32_op const&) = default;
+ write_some_win32_op(write_some_win32_op const&) = delete;
template<class DeducedHandler>
write_some_win32_op(
@@ -364,7 +365,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(h_);
+ return (boost::asio::get_associated_allocator)(h_);
}
using executor_type =
@@ -374,7 +375,7 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
h_, sock_.get_executor());
}
@@ -393,6 +394,14 @@ public:
return asio_handler_is_continuation(
std::addressof(op->h_));
}
+
+ template<class Function>
+ friend
+ void asio_handler_invoke(Function&& f, write_some_win32_op* op)
+ {
+ using boost::asio::asio_handler_invoke;
+ asio_handler_invoke(f, std::addressof(op->h_));
+ }
};
template<
@@ -407,25 +416,28 @@ operator()()
{
header_ = true;
sr_.split(true);
- return detail::async_write_some(
+ return detail::async_write_some_impl(
sock_, sr_, std::move(*this));
}
if(sr_.get().chunked())
{
- return detail::async_write_some(
+ return detail::async_write_some_impl(
sock_, sr_, std::move(*this));
}
- auto& r = sr_.reader_impl();
+ 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>)(r.body_.last_ - r.pos_, sr_.limit()),
+ (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(), *this};
+ 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(r.pos_);
- ov.OffsetHigh = highPart(r.pos_);
+ ov.Offset = lowPart(w.pos_);
+ ov.OffsetHigh = highPart(w.pos_);
auto const bSuccess = ::TransmitFile(
sock_.native_handle(),
sr_.get().body().file_.native_handle(),
@@ -434,14 +446,13 @@ operator()()
overlapped.get(),
nullptr,
0);
- auto const dwError = ::GetLastError();
+ 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>(
- boost::winapi::GetLastError()),
+ overlapped.complete(error_code{static_cast<int>(dwError),
system_category()}, 0);
return;
}
@@ -465,10 +476,10 @@ operator()(
header_ = false;
return (*this)();
}
- auto& r = sr_.reader_impl();
- r.pos_ += bytes_transferred;
- BOOST_ASSERT(r.pos_ <= r.body_.last_);
- if(r.pos_ >= r.body_.last_)
+ 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);
@@ -496,7 +507,7 @@ write_some(
{
sr.split(true);
auto const bytes_transferred =
- detail::write_some(sock, sr, ec);
+ detail::write_some_impl(sock, sr, ec);
if(ec)
return bytes_transferred;
return bytes_transferred;
@@ -504,23 +515,23 @@ write_some(
if(sr.get().chunked())
{
auto const bytes_transferred =
- detail::write_some(sock, sr, ec);
+ detail::write_some_impl(sock, sr, ec);
if(ec)
return bytes_transferred;
return bytes_transferred;
}
- auto& r = sr.reader_impl();
- r.body_.file_.seek(r.pos_, ec);
+ auto& w = sr.writer_impl();
+ w.body_.file_.seek(w.pos_, ec);
if(ec)
return 0;
boost::winapi::DWORD_ const nNumberOfBytesToWrite =
static_cast<boost::winapi::DWORD_>(
(std::min<std::uint64_t>)(
- (std::min<std::uint64_t>)(r.body_.last_ - r.pos_, sr.limit()),
+ (std::min<std::uint64_t>)(w.body_.last_ - w.pos_, sr.limit()),
(std::numeric_limits<boost::winapi::DWORD_>::max)()));
auto const bSuccess = ::TransmitFile(
sock.native_handle(),
- r.body_.file_.native_handle(),
+ w.body_.file_.native_handle(),
nNumberOfBytesToWrite,
0,
nullptr,
@@ -533,9 +544,9 @@ write_some(
system_category());
return 0;
}
- r.pos_ += nNumberOfBytesToWrite;
- BOOST_ASSERT(r.pos_ <= r.body_.last_);
- if(r.pos_ < r.body_.last_)
+ w.pos_ += nNumberOfBytesToWrite;
+ BOOST_ASSERT(w.pos_ <= w.body_.last_);
+ if(w.pos_ < w.body_.last_)
{
ec.assign(0, ec.category());
}
@@ -562,14 +573,14 @@ async_write_some(
basic_file_body<file_win32>, Fields>& sr,
WriteHandler&& handler)
{
- boost::asio::async_completion<WriteHandler,
- void(error_code)> init{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>{
- init.completion_handler, sock, sr}();
+ std::move(init.completion_handler), sock, sr}();
return init.result.get();
}
diff --git a/boost/beast/http/impl/parser.ipp b/boost/beast/http/impl/parser.ipp
index 99745da3f0..8a6cab30af 100644
--- a/boost/beast/http/impl/parser.ipp
+++ b/boost/beast/http/impl/parser.ipp
@@ -20,7 +20,26 @@ namespace http {
template<bool isRequest, class Body, class Allocator>
parser<isRequest, Body, Allocator>::
parser()
- : wr_(m_)
+ : parser{detail::has_deprecated_body_reader<Body>{}}
+{
+}
+
+template<bool isRequest, class Body, class Allocator>
+parser<isRequest, Body, Allocator>::
+parser(std::true_type)
+ : rd_(m_)
+{
+#ifndef BOOST_BEAST_ALLOW_DEPRECATED
+ // Deprecated BodyReader Concept (v1.66)
+ static_assert(sizeof(Body) == 0,
+ BOOST_BEAST_DEPRECATION_STRING);
+#endif
+}
+
+template<bool isRequest, class Body, class Allocator>
+parser<isRequest, Body, Allocator>::
+parser(std::false_type)
+ : rd_(m_.base(), m_.body())
{
}
@@ -28,21 +47,82 @@ template<bool isRequest, class Body, class Allocator>
template<class Arg1, class... ArgN, class>
parser<isRequest, Body, Allocator>::
parser(Arg1&& arg1, ArgN&&... argn)
+ : parser(std::forward<Arg1>(arg1),
+ detail::has_deprecated_body_reader<Body>{},
+ std::forward<ArgN>(argn)...)
+{
+}
+
+// VFALCO arg1 comes before `true_type` to make
+// the signature unambiguous.
+template<bool isRequest, class Body, class Allocator>
+template<class Arg1, class... ArgN, class>
+parser<isRequest, Body, Allocator>::
+parser(Arg1&& arg1, std::true_type, ArgN&&... argn)
: m_(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
- , wr_(m_)
+ , rd_(m_)
{
m_.clear();
+#ifndef BOOST_BEAST_ALLOW_DEPRECATED
+ /* Deprecated BodyWriter Concept (v1.66) */
+ static_assert(sizeof(Body) == 0,
+ BOOST_BEAST_DEPRECATION_STRING);
+#endif // BOOST_BEAST_ALLOW_DEPRECATED
+}
+
+// VFALCO arg1 comes before `false_type` to make
+// the signature unambiguous.
+template<bool isRequest, class Body, class Allocator>
+template<class Arg1, class... ArgN, class>
+parser<isRequest, Body, Allocator>::
+parser(Arg1&& arg1, std::false_type, ArgN&&... argn)
+ : m_(std::forward<Arg1>(arg1),
+ std::forward<ArgN>(argn)...)
+ , rd_(m_.base(), m_.body())
+{
+ m_.clear();
+}
+
+template<bool isRequest, class Body, class Allocator>
+template<class OtherBody, class... Args, class>
+parser<isRequest, Body, Allocator>::
+parser(
+ parser<isRequest, OtherBody, Allocator>&& other,
+ Args&&... args)
+ : parser(detail::has_deprecated_body_reader<Body>{},
+ std::move(other), std::forward<Args>(args)...)
+{
+}
+
+template<bool isRequest, class Body, class Allocator>
+template<class OtherBody, class... Args, class>
+parser<isRequest, Body, Allocator>::
+parser(std::true_type,
+ parser<isRequest, OtherBody, Allocator>&& other,
+ Args&&... args)
+ : base_type(std::move(other))
+ , m_(other.release(), std::forward<Args>(args)...)
+ , rd_(m_)
+{
+ if(other.rd_inited_)
+ BOOST_THROW_EXCEPTION(std::invalid_argument{
+ "moved-from parser has a body"});
+#ifndef BOOST_BEAST_ALLOW_DEPRECATED
+ // Deprecated BodyReader Concept (v1.66)
+ static_assert(sizeof(Body) == 0,
+ BOOST_BEAST_DEPRECATION_STRING);
+#endif
}
template<bool isRequest, class Body, class Allocator>
template<class OtherBody, class... Args, class>
parser<isRequest, Body, Allocator>::
-parser(parser<isRequest, OtherBody, Allocator>&& other,
+parser(std::false_type, parser<isRequest, OtherBody, Allocator>&& other,
Args&&... args)
: base_type(std::move(other))
, m_(other.release(), std::forward<Args>(args)...)
- , wr_(m_)
+ , rd_(m_.base(), m_.body())
{
if(other.rd_inited_)
BOOST_THROW_EXCEPTION(std::invalid_argument{
diff --git a/boost/beast/http/impl/read.ipp b/boost/beast/http/impl/read.ipp
index 5ecfae7d8b..28ff0a3c44 100644
--- a/boost/beast/http/impl/read.ipp
+++ b/boost/beast/http/impl/read.ipp
@@ -20,7 +20,9 @@
#include <boost/beast/core/type_traits.hpp>
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/coroutine.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>
@@ -38,19 +40,18 @@ namespace detail {
template<class Stream, class DynamicBuffer,
bool isRequest, class Derived, class Handler>
class read_some_op
+ : public boost::asio::coroutine
{
- int state_ = 0;
Stream& s_;
DynamicBuffer& b_;
basic_parser<isRequest, Derived>& p_;
- boost::optional<typename
- DynamicBuffer::mutable_buffers_type> mb_;
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&) = default;
+ read_some_op(read_some_op const&) = delete;
template<class DeducedHandler>
read_some_op(DeducedHandler&& h, Stream& s,
@@ -68,7 +69,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(h_);
+ return (boost::asio::get_associated_allocator)(h_);
}
using executor_type = boost::asio::associated_executor_t<
@@ -77,23 +78,32 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
h_, s_.get_executor());
}
void
operator()(
- error_code ec = {},
- std::size_t bytes_transferred = 0);
+ 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->state_ >= 2 ? true :
+ 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,
@@ -103,75 +113,69 @@ read_some_op<Stream, DynamicBuffer,
isRequest, Derived, Handler>::
operator()(
error_code ec,
- std::size_t bytes_transferred)
+ std::size_t bytes_transferred,
+ bool cont)
{
- switch(state_)
+ cont_ = cont;
+ boost::optional<typename
+ DynamicBuffer::mutable_buffers_type> mb;
+ BOOST_ASIO_CORO_REENTER(*this)
{
- case 0:
- state_ = 1;
if(b_.size() == 0)
goto do_read;
- goto do_parse;
-
- case 1:
- state_ = 2;
- case 2:
- if(ec == boost::asio::error::eof)
+ for(;;)
{
- BOOST_ASSERT(bytes_transferred == 0);
- if(p_.got_some())
+ // parse
{
- // 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;
+ auto const used = p_.put(b_.data(), ec);
+ bytes_transferred_ += used;
+ b_.consume(used);
}
- ec = error::end_of_stream;
- goto upcall;
- }
- if(ec)
- goto upcall;
- b_.commit(bytes_transferred);
-
- do_parse:
- {
- auto const used = p_.put(b_.data(), ec);
- bytes_transferred_ += used;
- b_.consume(used);
- if(! ec || ec != http::error::need_more)
- goto do_upcall;
- ec.assign(0, ec.category());
- }
+ if(ec != http::error::need_more)
+ break;
- do_read:
- try
- {
- mb_.emplace(b_.prepare(
- read_size_or_throw(b_, 65536)));
- }
- catch(std::length_error const&)
- {
- ec = error::buffer_overflow;
- goto do_upcall;
+ do_read:
+ try
+ {
+ mb.emplace(b_.prepare(
+ read_size_or_throw(b_, 65536)));
+ }
+ catch(std::length_error const&)
+ {
+ ec = error::buffer_overflow;
+ break;
+ }
+ BOOST_ASIO_CORO_YIELD
+ 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);
}
- return s_.async_read_some(*mb_, std::move(*this));
- do_upcall:
- if(state_ >= 2)
- goto upcall;
- state_ = 3;
- return boost::asio::post(
- s_.get_executor(),
- bind_handler(std::move(*this), ec, 0));
-
- case 3:
- break;
+ upcall:
+ if(! cont_)
+ return boost::asio::post(
+ s_.get_executor(),
+ bind_handler(std::move(h_),
+ ec, bytes_transferred_));
+ h_(ec, bytes_transferred_);
}
-upcall:
- h_(ec, bytes_transferred_);
}
//------------------------------------------------------------------------------
@@ -202,17 +206,18 @@ template<class Stream, class DynamicBuffer,
bool isRequest, class Derived, class Condition,
class Handler>
class read_op
+ : public boost::asio::coroutine
{
- int state_ = 0;
Stream& s_;
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&) = default;
+ read_op(read_op const&) = delete;
template<class DeducedHandler>
read_op(DeducedHandler&& h, Stream& s,
@@ -231,7 +236,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(h_);
+ return (boost::asio::get_associated_allocator)(h_);
}
using executor_type = boost::asio::associated_executor_t<
@@ -240,23 +245,32 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
h_, s_.get_executor());
}
void
operator()(
- error_code ec = {},
- std::size_t bytes_transferred = 0);
+ 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->state_ >= 3 ? true :
+ 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,
@@ -267,39 +281,33 @@ read_op<Stream, DynamicBuffer,
isRequest, Derived, Condition, Handler>::
operator()(
error_code ec,
- std::size_t bytes_transferred)
+ std::size_t bytes_transferred,
+ bool cont)
{
- switch(state_)
+ cont_ = cont;
+ BOOST_ASIO_CORO_REENTER(*this)
{
- case 0:
if(Condition{}(p_))
{
- state_ = 1;
- return boost::asio::post(
- s_.get_executor(),
+ BOOST_ASIO_CORO_YIELD
+ boost::asio::post(s_.get_executor(),
bind_handler(std::move(*this), ec));
- }
- state_ = 2;
-
- do_read:
- return async_read_some(
- s_, b_, p_, std::move(*this));
-
- case 1:
- goto upcall;
-
- case 2:
- case 3:
- if(ec)
- goto upcall;
- bytes_transferred_ += bytes_transferred;
- if(Condition{}(p_))
goto upcall;
- state_ = 3;
- goto do_read;
+ }
+ 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_);
}
-upcall:
- h_(ec, bytes_transferred_);
}
//------------------------------------------------------------------------------
@@ -308,6 +316,7 @@ 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>;
@@ -317,14 +326,14 @@ class read_msg_op
struct data
{
- int state = 0;
Stream& s;
DynamicBuffer& b;
message_type& m;
parser_type p;
std::size_t bytes_transferred = 0;
+ bool cont = false;
- data(Handler&, Stream& s_,
+ data(Handler const&, Stream& s_,
DynamicBuffer& b_, message_type& m_)
: s(s_)
, b(b_)
@@ -339,7 +348,7 @@ class read_msg_op
public:
read_msg_op(read_msg_op&&) = default;
- read_msg_op(read_msg_op const&) = default;
+ read_msg_op(read_msg_op const&) = delete;
template<class DeducedHandler, class... Args>
read_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
@@ -354,7 +363,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(d_.handler());
+ return (boost::asio::get_associated_allocator)(d_.handler());
}
using executor_type = boost::asio::associated_executor_t<
@@ -363,23 +372,32 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
d_.handler(), d_->s.get_executor());
}
void
operator()(
- error_code ec = {},
- std::size_t bytes_transferred = 0);
+ 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_->state >= 2 ? true :
+ 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,
@@ -390,35 +408,32 @@ read_msg_op<Stream, DynamicBuffer,
isRequest, Body, Allocator, Handler>::
operator()(
error_code ec,
- std::size_t bytes_transferred)
+ std::size_t bytes_transferred,
+ bool cont)
{
auto& d = *d_;
- switch(d.state)
+ d.cont = cont;
+ BOOST_ASIO_CORO_REENTER(*this)
{
- case 0:
- d.state = 1;
-
- do_read:
- return async_read_some(
- d.s, d.b, d.p, std::move(*this));
-
- case 1:
- case 2:
- if(ec)
- goto upcall;
- d.bytes_transferred +=
- bytes_transferred;
- if(d.p.is_done())
+ for(;;)
{
- d.m = d.p.release();
- goto upcall;
+ 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;
+ }
}
- d.state = 2;
- goto do_read;
+ upcall:
+ bytes_transferred = d.bytes_transferred;
+ d_.invoke(ec, bytes_transferred);
}
-upcall:
- bytes_transferred = d.bytes_transferred;
- d_.invoke(ec, bytes_transferred);
}
} // detail
@@ -536,12 +551,13 @@ async_read_some(
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
BOOST_ASSERT(! parser.is_done());
- boost::asio::async_completion<ReadHandler,
- void(error_code, std::size_t)> init{handler};
+ 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))>{
- init.completion_handler, stream, buffer, parser}();
+ std::move(init.completion_handler), stream, buffer, parser}(
+ {}, 0, false);
return init.result.get();
}
@@ -623,12 +639,13 @@ async_read_header(
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
parser.eager(false);
- boost::asio::async_completion<ReadHandler,
- void(error_code, std::size_t)> init{handler};
+ 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))>{
- init.completion_handler, stream, buffer, parser}();
+ std::move(init.completion_handler), stream,
+ buffer, parser}({}, 0, false);
return init.result.get();
}
@@ -710,13 +727,13 @@ async_read(
boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met");
parser.eager(true);
- boost::asio::async_completion<
- ReadHandler,
- void(error_code, std::size_t)> init{handler};
+ 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))>{
- init.completion_handler, stream, buffer, parser}();
+ std::move(init.completion_handler), stream, buffer, parser}(
+ {}, 0, false);
return init.result.get();
}
@@ -801,16 +818,16 @@ async_read(
"Body requirements not met");
static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met");
- boost::asio::async_completion<
- ReadHandler,
- void(error_code, std::size_t)> init{handler};
+ 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))>{
- init.completion_handler, stream, buffer, msg}();
+ std::move(init.completion_handler), stream, buffer, msg}(
+ {}, 0, false);
return init.result.get();
}
diff --git a/boost/beast/http/impl/serializer.ipp b/boost/beast/http/impl/serializer.ipp
index 11cf857845..b37856567f 100644
--- a/boost/beast/http/impl/serializer.ipp
+++ b/boost/beast/http/impl/serializer.ipp
@@ -25,18 +25,18 @@ template<
bool isRequest, class Body, class Fields>
void
serializer<isRequest, Body, Fields>::
-frdinit(std::true_type)
+fwrinit(std::true_type)
{
- frd_.emplace(m_, m_.version(), m_.method());
+ fwr_.emplace(m_, m_.version(), m_.method());
}
template<
bool isRequest, class Body, class Fields>
void
serializer<isRequest, Body, Fields>::
-frdinit(std::false_type)
+fwrinit(std::false_type)
{
- frd_.emplace(m_, m_.version(), m_.result_int());
+ fwr_.emplace(m_, m_.version(), m_.result_int());
}
template<
@@ -57,9 +57,31 @@ do_visit(error_code& ec, Visit& visit)
template<
bool isRequest, class Body, class Fields>
serializer<isRequest, Body, Fields>::
-serializer(value_type& m)
+serializer(value_type& m, std::true_type)
+ : m_(m)
+ , wr_(m_)
+{
+#ifndef BOOST_BEAST_ALLOW_DEPRECATED
+ // Deprecated BodyWriter Concept (v1.66)
+ static_assert(sizeof(Body) == 0,
+ BOOST_BEAST_DEPRECATION_STRING);
+#endif
+}
+
+template<
+ bool isRequest, class Body, class Fields>
+serializer<isRequest, Body, Fields>::
+serializer(value_type& m, std::false_type)
: m_(m)
- , rd_(m_)
+ , wr_(m_.base(), m_.body())
+{
+}
+
+template<
+ bool isRequest, class Body, class Fields>
+serializer<isRequest, Body, Fields>::
+serializer(value_type& m)
+ : serializer(m, detail::has_deprecated_body_writer<Body>{})
{
}
@@ -75,22 +97,22 @@ next(error_code& ec, Visit&& visit)
{
case do_construct:
{
- frdinit(std::integral_constant<bool,
+ fwrinit(std::integral_constant<bool,
isRequest>{});
if(m_.chunked())
goto go_init_c;
s_ = do_init;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case do_init:
{
- rd_.init(ec);
+ wr_.init(ec);
if(ec)
return;
if(split_)
goto go_header_only;
- auto result = rd_.get(ec);
+ auto result = wr_.get(ec);
if(ec == error::need_more)
goto go_header_only;
if(ec)
@@ -100,10 +122,10 @@ next(error_code& ec, Visit&& visit)
more_ = result->second;
v_.template emplace<2>(
boost::in_place_init,
- frd_->get(),
+ fwr_->get(),
result->first);
s_ = do_header;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case do_header:
@@ -111,20 +133,20 @@ next(error_code& ec, Visit&& visit)
break;
go_header_only:
- v_.template emplace<1>(frd_->get());
+ v_.template emplace<1>(fwr_->get());
s_ = do_header_only;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_header_only:
do_visit<1>(ec, visit);
break;
case do_body:
s_ = do_body + 1;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_body + 1:
{
- auto result = rd_.get(ec);
+ auto result = wr_.get(ec);
if(ec)
return;
if(! result)
@@ -132,7 +154,7 @@ next(error_code& ec, Visit&& visit)
more_ = result->second;
v_.template emplace<3>(result->first);
s_ = do_body + 2;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case do_body + 2:
@@ -143,15 +165,15 @@ next(error_code& ec, Visit&& visit)
go_init_c:
s_ = do_init_c;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_init_c:
{
- rd_.init(ec);
+ wr_.init(ec);
if(ec)
return;
if(split_)
goto go_header_only_c;
- auto result = rd_.get(ec);
+ auto result = wr_.get(ec);
if(ec == error::need_more)
goto go_header_only_c;
if(ec)
@@ -164,7 +186,7 @@ next(error_code& ec, Visit&& visit)
// do it all in one buffer
v_.template emplace<7>(
boost::in_place_init,
- frd_->get(),
+ fwr_->get(),
buffer_size(result->first),
boost::asio::const_buffer{nullptr, 0},
chunk_crlf{},
@@ -177,14 +199,14 @@ next(error_code& ec, Visit&& visit)
}
v_.template emplace<4>(
boost::in_place_init,
- frd_->get(),
+ fwr_->get(),
buffer_size(result->first),
boost::asio::const_buffer{nullptr, 0},
chunk_crlf{},
result->first,
chunk_crlf{});
s_ = do_header_c;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case do_header_c:
@@ -192,19 +214,21 @@ next(error_code& ec, Visit&& visit)
break;
go_header_only_c:
- v_.template emplace<1>(frd_->get());
+ v_.template emplace<1>(fwr_->get());
s_ = do_header_only_c;
+ BOOST_FALLTHROUGH;
+
case do_header_only_c:
do_visit<1>(ec, visit);
break;
case do_body_c:
s_ = do_body_c + 1;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_body_c + 1:
{
- auto result = rd_.get(ec);
+ auto result = wr_.get(ec);
if(ec)
return;
if(! result)
@@ -233,7 +257,7 @@ next(error_code& ec, Visit&& visit)
result->first,
chunk_crlf{});
s_ = do_body_c + 2;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
}
case do_body_c + 2:
@@ -242,14 +266,14 @@ next(error_code& ec, Visit&& visit)
go_body_final_c:
s_ = do_body_final_c;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_body_final_c:
do_visit<6>(ec, visit);
break;
go_all_c:
s_ = do_all_c;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_all_c:
do_visit<7>(ec, visit);
break;
@@ -262,7 +286,7 @@ next(error_code& ec, Visit&& visit)
boost::asio::const_buffer{nullptr, 0},
chunk_crlf{});
s_ = do_final_c + 1;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case do_final_c + 1:
do_visit<8>(ec, visit);
@@ -309,7 +333,7 @@ consume(std::size_t n)
v_.template get<1>().consume(n);
if(buffer_size(v_.template get<1>()) > 0)
break;
- frd_ = boost::none;
+ fwr_ = boost::none;
header_done_ = true;
if(! split_)
goto go_complete;
@@ -353,7 +377,7 @@ consume(std::size_t n)
v_.template get<1>().consume(n);
if(buffer_size(v_.template get<1>()) > 0)
break;
- frd_ = boost::none;
+ fwr_ = boost::none;
header_done_ = true;
if(! split_)
{
diff --git a/boost/beast/http/impl/status.ipp b/boost/beast/http/impl/status.ipp
index 1cc8f34b63..7d37919423 100644
--- a/boost/beast/http/impl/status.ipp
+++ b/boost/beast/http/impl/status.ipp
@@ -28,7 +28,7 @@ int_to_status(unsigned v)
case status::continue_:
case status::switching_protocols:
case status::processing:
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
// 2xx
case status::ok:
@@ -41,7 +41,7 @@ int_to_status(unsigned v)
case status::multi_status:
case status::already_reported:
case status::im_used:
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
// 3xx
case status::multiple_choices:
@@ -52,7 +52,7 @@ int_to_status(unsigned v)
case status::use_proxy:
case status::temporary_redirect:
case status::permanent_redirect:
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
// 4xx
case status::bad_request:
@@ -84,7 +84,7 @@ int_to_status(unsigned v)
case status::connection_closed_without_response:
case status::unavailable_for_legal_reasons:
case status::client_closed_request:
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
// 5xx
case status::internal_server_error:
diff --git a/boost/beast/http/impl/verb.ipp b/boost/beast/http/impl/verb.ipp
index 820609165b..8f8b2e33bf 100644
--- a/boost/beast/http/impl/verb.ipp
+++ b/boost/beast/http/impl/verb.ipp
@@ -72,6 +72,10 @@ verb_to_string(verb v)
}
BOOST_THROW_EXCEPTION(std::invalid_argument{"unknown verb"});
+
+ // Help some compilers which don't know the next line is
+ // unreachable, otherwise spurious warnings are generated.
+ return "<unknown>";
}
template<class = void>
@@ -159,7 +163,7 @@ string_to_verb(string_view v)
return verb::connect;
if(eq(v, "PY"))
return verb::copy;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
default:
break;
@@ -220,7 +224,7 @@ string_to_verb(string_view v)
case 'O':
if(eq(v, "VE"))
return verb::move;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
default:
break;
@@ -264,7 +268,7 @@ string_to_verb(string_view v)
return verb::purge;
if(eq(v, "T"))
return verb::put;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
default:
break;
diff --git a/boost/beast/http/impl/write.ipp b/boost/beast/http/impl/write.ipp
index 9d5be277ec..af31cd9be9 100644
--- a/boost/beast/http/impl/write.ipp
+++ b/boost/beast/http/impl/write.ipp
@@ -19,6 +19,7 @@
#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/associated_executor.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>
@@ -67,7 +68,7 @@ class write_some_op
public:
write_some_op(write_some_op&&) = default;
- write_some_op(write_some_op const&) = default;
+ write_some_op(write_some_op const&) = delete;
template<class DeducedHandler>
write_some_op(DeducedHandler&& h, Stream& s,
@@ -84,7 +85,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(h_);
+ return (boost::asio::get_associated_allocator)(h_);
}
using executor_type = boost::asio::associated_executor_t<
@@ -93,7 +94,7 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
h_, s_.get_executor());
}
@@ -112,6 +113,14 @@ public:
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_));
+ }
};
template<
@@ -203,7 +212,7 @@ class write_op
public:
write_op(write_op&&) = default;
- write_op(write_op const&) = default;
+ write_op(write_op const&) = delete;
template<class DeducedHandler>
write_op(DeducedHandler&& h, Stream& s,
@@ -220,7 +229,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(h_);
+ return (boost::asio::get_associated_allocator)(h_);
}
using executor_type = boost::asio::associated_executor_t<
@@ -229,7 +238,7 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
h_, s_.get_executor());
}
@@ -246,6 +255,14 @@ public:
asio_handler_is_continuation(
std::addressof(op->h_));
}
+
+ 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<
@@ -280,7 +297,7 @@ operator()(
case 2:
state_ = 3;
- BOOST_BEAST_FALLTHROUGH;
+ BOOST_FALLTHROUGH;
case 3:
{
@@ -306,7 +323,7 @@ class write_msg_op
Stream& s;
serializer<isRequest, Body, Fields> sr;
- data(Handler&, Stream& s_, message<
+ data(Handler const&, Stream& s_, message<
isRequest, Body, Fields>& m_)
: s(s_)
, sr(m_)
@@ -318,7 +335,7 @@ class write_msg_op
public:
write_msg_op(write_msg_op&&) = default;
- write_msg_op(write_msg_op const&) = default;
+ write_msg_op(write_msg_op const&) = delete;
template<class DeducedHandler, class... Args>
write_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
@@ -333,7 +350,7 @@ public:
allocator_type
get_allocator() const noexcept
{
- return boost::asio::get_associated_allocator(d_.handler());
+ return (boost::asio::get_associated_allocator)(d_.handler());
}
using executor_type = boost::asio::associated_executor_t<
@@ -342,7 +359,7 @@ public:
executor_type
get_executor() const noexcept
{
- return boost::asio::get_associated_executor(
+ return (boost::asio::get_associated_executor)(
d_.handler(), d_->s.get_executor());
}
@@ -360,6 +377,14 @@ public:
return asio_handler_is_continuation(
std::addressof(op->d_.handler()));
}
+
+ 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()));
+ }
};
template<class Stream, class Handler,
@@ -441,7 +466,7 @@ template<
class SyncWriteStream,
bool isRequest, class Body, class Fields>
std::size_t
-write_some(
+write_some_impl(
SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
error_code& ec)
@@ -466,20 +491,19 @@ template<
class WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(
WriteHandler, void(error_code, std::size_t))
-async_write_some(
+async_write_some_impl(
AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr,
WriteHandler&& handler)
{
- boost::asio::async_completion<
- WriteHandler,
- void(error_code, std::size_t)> init{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>{
- init.completion_handler, stream, sr}();
+ std::move(init.completion_handler), stream, sr}();
return init.result.get();
}
@@ -524,7 +548,7 @@ write_some(
"Body requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
- return detail::write_some(stream, sr, ec);
+ return detail::write_some_impl(stream, sr, ec);
}
template<
@@ -545,7 +569,7 @@ async_write_some(
"Body requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
- return detail::async_write_some(stream, sr,
+ return detail::async_write_some_impl(stream, sr,
std::forward<WriteHandler>(handler));
}
@@ -629,16 +653,15 @@ async_write_header(
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
sr.split(true);
- boost::asio::async_completion<
- WriteHandler,
- void(error_code, std::size_t)> init{handler};
+ 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>{
- init.completion_handler, stream, sr}();
+ std::move(init.completion_handler), stream, sr}();
return init.result.get();
}
@@ -706,16 +729,15 @@ async_write(
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
sr.split(false);
- boost::asio::async_completion<
- WriteHandler,
- void(error_code, std::size_t)> init{handler};
+ 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>{
- init.completion_handler, stream, sr}();
+ std::move(init.completion_handler), stream, sr}();
return init.result.get();
}
@@ -780,15 +802,14 @@ async_write(
"Body requirements not met");
static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met");
- boost::asio::async_completion<
- WriteHandler,
- void(error_code, std::size_t)> init{handler};
+ 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>{
- init.completion_handler, stream, msg}();
+ std::move(init.completion_handler), stream, msg}();
return init.result.get();
}
diff --git a/boost/beast/http/message.hpp b/boost/beast/http/message.hpp
index 5cf5d94dc9..0455042786 100644
--- a/boost/beast/http/message.hpp
+++ b/boost/beast/http/message.hpp
@@ -862,7 +862,8 @@ struct message
#endif
body()& noexcept
{
- return this->member();
+ return this->beast::detail::empty_base_optimization<
+ typename Body::value_type>::member();
}
/// Returns the body
@@ -873,7 +874,9 @@ struct message
#endif
body()&& noexcept
{
- return std::move(this->member());
+ return std::move(
+ this->beast::detail::empty_base_optimization<
+ typename Body::value_type>::member());
}
/// Returns the body
@@ -884,7 +887,8 @@ struct message
#endif
body() const& noexcept
{
- return this->member();
+ return this->beast::detail::empty_base_optimization<
+ typename Body::value_type>::member();
}
private:
diff --git a/boost/beast/http/parser.hpp b/boost/beast/http/parser.hpp
index 47e1003533..69d93cf03c 100644
--- a/boost/beast/http/parser.hpp
+++ b/boost/beast/http/parser.hpp
@@ -63,7 +63,7 @@ class parser
parser<isRequest, Body, Allocator>>;
message<isRequest, Body, basic_fields<Allocator>> m_;
- typename Body::reader wr_;
+ typename Body::reader rd_;
bool rd_inited_ = false;
std::function<void(
@@ -84,21 +84,17 @@ public:
/// Destructor
~parser() = default;
- /// Constructor
- parser();
-
- /// Constructor
+ /// Constructor (disallowed)
parser(parser const&) = delete;
- /// Assignment
+ /// Assignment (disallowed)
parser& operator=(parser const&) = delete;
- /** Constructor
+ /// Constructor (disallowed)
+ parser(parser&& other) = delete;
- After the move, the only valid operation
- on the moved-from object is destruction.
- */
- parser(parser&& other) = default;
+ /// Constructor
+ parser();
/** Constructor
@@ -303,6 +299,39 @@ public:
private:
friend class basic_parser<isRequest, parser>;
+ parser(std::true_type);
+ parser(std::false_type);
+
+ template<class OtherBody, class... Args,
+ class = typename std::enable_if<
+ ! std::is_same<Body, OtherBody>::value>::type>
+ parser(
+ std::true_type,
+ parser<isRequest, OtherBody, Allocator>&& parser,
+ Args&&... args);
+
+ template<class OtherBody, class... Args,
+ class = typename std::enable_if<
+ ! std::is_same<Body, OtherBody>::value>::type>
+ parser(
+ std::false_type,
+ parser<isRequest, OtherBody, Allocator>&& parser,
+ Args&&... args);
+
+ template<class Arg1, class... ArgN,
+ class = typename std::enable_if<
+ ! detail::is_parser<typename
+ std::decay<Arg1>::type>::value>::type>
+ explicit
+ parser(Arg1&& arg1, std::true_type, ArgN&&... argn);
+
+ template<class Arg1, class... ArgN,
+ class = typename std::enable_if<
+ ! detail::is_parser<typename
+ std::decay<Arg1>::type>::value>::type>
+ explicit
+ parser(Arg1&& arg1, std::false_type, ArgN&&... argn);
+
void
on_request_impl(
verb method,
@@ -376,7 +405,7 @@ private:
boost::optional<std::uint64_t> const& content_length,
error_code& ec)
{
- wr_.init(content_length, ec);
+ rd_.init(content_length, ec);
rd_inited_ = true;
}
@@ -385,7 +414,7 @@ private:
string_view body,
error_code& ec)
{
- return wr_.put(boost::asio::buffer(
+ return rd_.put(boost::asio::buffer(
body.data(), body.size()), ec);
}
@@ -408,14 +437,14 @@ private:
{
if(cb_b_)
return cb_b_(remain, body, ec);
- return wr_.put(boost::asio::buffer(
+ return rd_.put(boost::asio::buffer(
body.data(), body.size()), ec);
}
void
on_finish_impl(error_code& ec)
{
- wr_.finish(ec);
+ rd_.finish(ec);
}
};
diff --git a/boost/beast/http/read.hpp b/boost/beast/http/read.hpp
index 4f159aec2b..a4f0efe400 100644
--- a/boost/beast/http/read.hpp
+++ b/boost/beast/http/read.hpp
@@ -175,8 +175,8 @@ read_some(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the request
- completes. Copies will be made of the handler as required.
+ @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
@@ -361,8 +361,8 @@ read_header(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the request
- completes. Copies will be made of the handler as required.
+ @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,
@@ -545,8 +545,8 @@ read(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the request
- completes. Copies will be made of the handler as required.
+ @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,
@@ -731,8 +731,8 @@ read(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the operation
- completes. Copies will be made of the handler as required.
+ @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,
diff --git a/boost/beast/http/serializer.hpp b/boost/beast/http/serializer.hpp
index 50e58185a9..bbb562a620 100644
--- a/boost/beast/http/serializer.hpp
+++ b/boost/beast/http/serializer.hpp
@@ -71,14 +71,20 @@ public:
#if BOOST_BEAST_DOXYGEN
using value_type = implementation_defined;
#else
- using value_type =
- typename std::conditional<
- std::is_constructible<typename Body::writer,
- message<isRequest, Body, Fields>&>::value &&
- ! std::is_constructible<typename Body::writer,
- message<isRequest, Body, Fields> const&>::value,
- message<isRequest, Body, Fields>,
- message<isRequest, Body, Fields> const>::type;
+ using value_type = typename std::conditional<
+ (std::is_constructible<typename Body::writer,
+ header<isRequest, Fields>&,
+ typename Body::value_type&>::value &&
+ ! std::is_constructible<typename Body::writer,
+ header<isRequest, Fields> const&,
+ typename Body::value_type const&>::value) ||
+ // Deprecated BodyWriter Concept (v1.66)
+ (std::is_constructible<typename Body::writer,
+ message<isRequest, Body, Fields>&>::value &&
+ ! std::is_constructible<typename Body::writer,
+ message<isRequest, Body, Fields> const&>::value),
+ message<isRequest, Body, Fields>,
+ message<isRequest, Body, Fields> const>::type;
#endif
private:
@@ -104,8 +110,8 @@ private:
do_complete = 120
};
- void frdinit(std::true_type);
- void frdinit(std::false_type);
+ void fwrinit(std::true_type);
+ void fwrinit(std::false_type);
template<std::size_t, class Visit>
void
@@ -173,8 +179,8 @@ private:
using pcb8_t = buffers_prefix_view<cb8_t const&>;
value_type& m_;
- writer rd_;
- boost::optional<typename Fields::writer> frd_;
+ writer wr_;
+ boost::optional<typename Fields::writer> fwr_;
beast::detail::variant<
cb1_t, cb2_t, cb3_t, cb4_t,
cb5_t ,cb6_t, cb7_t, cb8_t> v_;
@@ -188,6 +194,8 @@ private:
bool header_done_ = false;
bool more_;
+ serializer(value_type& msg, std::true_type);
+ serializer(value_type& msg, std::false_type);
public:
/// Constructor
serializer(serializer&&) = default;
@@ -336,7 +344,7 @@ public:
void
consume(std::size_t n);
- /** Provides low-level access to the associated @b BodyWriter
+ /** Provides low-level access to the associated @b BodyWriter (DEPRECATED)
This function provides access to the instance of the writer
associated with the body and created by the serializer
@@ -349,7 +357,27 @@ public:
writer&
reader_impl()
{
- return rd_;
+ #ifndef BOOST_BEAST_ALLOW_DEPRECATED
+ BOOST_STATIC_ASSERT_MSG(sizeof(Body) == 0,
+ BOOST_BEAST_DEPRECATION_STRING);
+ #endif
+ return wr_;
+ }
+
+ /** Provides low-level access to the associated @b BodyWriter
+
+ This function provides access to the instance of the writer
+ associated with the body and created by the serializer
+ upon construction. The behavior of accessing this object
+ is defined by the specification of the particular writer
+ and its associated body.
+
+ @return A reference to the writer.
+ */
+ writer&
+ writer_impl()
+ {
+ return wr_;
}
};
diff --git a/boost/beast/http/span_body.hpp b/boost/beast/http/span_body.hpp
index 6282ecc6d9..4688dc8741 100644
--- a/boost/beast/http/span_body.hpp
+++ b/boost/beast/http/span_body.hpp
@@ -73,9 +73,8 @@ public:
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest,
- span_body, Fields>& m)
- : body_(m.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -138,9 +137,8 @@ public:
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- span_body, Fields> const& msg)
- : body_(msg.body())
+ writer(header<isRequest, Fields> const&, value_type const& b)
+ : body_(b)
{
}
diff --git a/boost/beast/http/string_body.hpp b/boost/beast/http/string_body.hpp
index 18eda414e8..89447e50ff 100644
--- a/boost/beast/http/string_body.hpp
+++ b/boost/beast/http/string_body.hpp
@@ -81,9 +81,8 @@ public:
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest,
- basic_string_body, Fields>& m)
- : body_(m.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -166,9 +165,8 @@ public:
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- basic_string_body, Fields> const& msg)
- : body_(msg.body())
+ writer(header<isRequest, Fields> const&, value_type const& b)
+ : body_(b)
{
}
diff --git a/boost/beast/http/type_traits.hpp b/boost/beast/http/type_traits.hpp
index f90f16ffef..0c8210443e 100644
--- a/boost/beast/http/type_traits.hpp
+++ b/boost/beast/http/type_traits.hpp
@@ -89,11 +89,19 @@ struct is_body_writer<T, beast::detail::void_t<
std::declval<typename T::writer>().get(std::declval<error_code&>()),
(void)0)>> : std::integral_constant<bool,
boost::asio::is_const_buffer_sequence<
- typename T::writer::const_buffers_type>::value &&
+ typename T::writer::const_buffers_type>::value && (
+ (std::is_constructible<typename T::writer,
+ header<true, detail::fields_model>&,
+ typename T::value_type&>::value &&
std::is_constructible<typename T::writer,
+ header<false, detail::fields_model>&,
+ typename T::value_type&>::value) ||
+ // Deprecated BodyWriter Concept (v1.66)
+ (std::is_constructible<typename T::writer,
message<true, T, detail::fields_model>&>::value &&
std::is_constructible<typename T::writer,
- message<false, T, detail::fields_model>&>::value
+ message<false, T, detail::fields_model>&>::value)
+ )
> {};
#endif
@@ -136,11 +144,18 @@ struct is_body_reader<T, beast::detail::void_t<decltype(
std::declval<typename T::reader&>().finish(
std::declval<error_code&>()),
(void)0)>> : std::integral_constant<bool,
+ (std::is_constructible<typename T::reader,
+ header<true, detail::fields_model>&,
+ typename T::value_type&>::value &&
std::is_constructible<typename T::reader,
+ header<false,detail::fields_model>&,
+ typename T::value_type&>::value) ||
+ // Deprecated BodyReader Concept (v1.66)
+ (std::is_constructible<typename T::reader,
message<true, T, detail::fields_model>&>::value &&
std::is_constructible<typename T::reader,
- message<false, T, detail::fields_model>&>::value
- >
+ message<false, T, detail::fields_model>&>::value)
+ >
{
};
#endif
diff --git a/boost/beast/http/vector_body.hpp b/boost/beast/http/vector_body.hpp
index eb37145d61..40c885e43e 100644
--- a/boost/beast/http/vector_body.hpp
+++ b/boost/beast/http/vector_body.hpp
@@ -76,9 +76,8 @@ public:
public:
template<bool isRequest, class Fields>
explicit
- reader(message<isRequest,
- vector_body, Fields>& m)
- : body_(m.body())
+ reader(header<isRequest, Fields>&, value_type& b)
+ : body_(b)
{
}
@@ -155,9 +154,8 @@ public:
template<bool isRequest, class Fields>
explicit
- writer(message<isRequest,
- vector_body, Fields> const& msg)
- : body_(msg.body())
+ writer(header<isRequest, Fields> const&, value_type const& b)
+ : body_(b)
{
}
diff --git a/boost/beast/http/write.hpp b/boost/beast/http/write.hpp
index 755ed0b94b..3b916b1d7b 100644
--- a/boost/beast/http/write.hpp
+++ b/boost/beast/http/write.hpp
@@ -148,8 +148,8 @@ write_some(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the operation
- completes. Copies will be made of the handler as required.
+ @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
@@ -269,8 +269,8 @@ write_header(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the operation
- completes. Copies will be made of the handler as required.
+ @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
@@ -387,8 +387,8 @@ write(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the operation
- completes. Copies will be made of the handler as required.
+ @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
@@ -502,8 +502,8 @@ write(
The object must remain valid at least until the
handler is called; ownership is not transferred.
- @param handler The handler to be called when the operation
- completes. Copies will be made of the handler as required.
+ @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