forked from boostorg/beast
Tidy up tests, build scripts, and documentation:
* Concepts split up into individual files * Function definitions moved to .ipp files * Add more tests to fill gaps in coverage * Fix documentation Xsl
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_ASYNC_COMPLETION_HPP
|
||||
#define BEAST_ASYNC_COMPLETION_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/handler_concepts.hpp>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/handler_type.hpp>
|
||||
#include <type_traits>
|
||||
@@ -19,11 +19,11 @@ namespace beast {
|
||||
/** Helper for customizing the return type of asynchronous initiation functions.
|
||||
|
||||
This class template is used to transform caller-provided completion
|
||||
tokens in calls to asynchronous initiation functions. The transformation
|
||||
handlers in calls to asynchronous initiation functions. The transformation
|
||||
allows customization of the return type of the initiating function, and the
|
||||
function signature of the final handler.
|
||||
|
||||
@tparam CompletionToken A CompletionHandler, or a user defined type
|
||||
@tparam CompletionHandler A completion handler, or a user defined type
|
||||
with specializations for customizing the return type (for example,
|
||||
`boost::asio::use_future` or `boost::asio::yield_context`).
|
||||
|
||||
@@ -32,22 +32,22 @@ namespace beast {
|
||||
Example:
|
||||
@code
|
||||
...
|
||||
template<class CompletionToken>
|
||||
typename async_completion<CompletionToken,
|
||||
template<class CompletionHandler>
|
||||
typename async_completion<CompletionHandler,
|
||||
void(boost::system::error_code)>::result_type
|
||||
async_initfn(..., CompletionToken&& token)
|
||||
async_initfn(..., CompletionHandler&& handler)
|
||||
{
|
||||
async_completion<CompletionToken,
|
||||
void(boost::system::error_code)> completion(token);
|
||||
async_completion<CompletionHandler,
|
||||
void(boost::system::error_code)> completion(handler);
|
||||
...
|
||||
return completion.result.get();
|
||||
}
|
||||
@endcode
|
||||
|
||||
See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
|
||||
@note See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf">
|
||||
Library Foundations For Asynchronous Operations</a>
|
||||
*/
|
||||
template <class CompletionToken, class Signature>
|
||||
template <class CompletionHandler, class Signature>
|
||||
struct async_completion
|
||||
{
|
||||
/** The type of the final handler called by the asynchronous initiation function.
|
||||
@@ -56,7 +56,7 @@ struct async_completion
|
||||
*/
|
||||
using handler_type =
|
||||
typename boost::asio::handler_type<
|
||||
CompletionToken, Signature>::type;
|
||||
CompletionHandler, Signature>::type;
|
||||
|
||||
/// The type of the value returned by the asynchronous initiation function.
|
||||
using result_type = typename
|
||||
@@ -64,14 +64,14 @@ struct async_completion
|
||||
|
||||
/** Construct the helper.
|
||||
|
||||
@param token The completion token. Copies will be made as
|
||||
required. If `CompletionToken` is movable, it may also be moved.
|
||||
@param token The completion handler. Copies will be made as
|
||||
required. If `CompletionHandler` is movable, it may also be moved.
|
||||
*/
|
||||
async_completion(typename std::remove_reference<CompletionToken>::type& token)
|
||||
: handler(std::forward<CompletionToken>(token))
|
||||
async_completion(typename std::remove_reference<CompletionHandler>::type& token)
|
||||
: handler(std::forward<CompletionHandler>(token))
|
||||
, result(handler)
|
||||
{
|
||||
static_assert(is_Handler<handler_type, Signature>::value,
|
||||
static_assert(is_CompletionHandler<handler_type, Signature>::value,
|
||||
"Handler requirements not met");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,15 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A `Streambuf` that uses multiple buffers internally.
|
||||
/** A @b `Streambuf` that uses multiple buffers internally.
|
||||
|
||||
The implementation uses a sequence of one or more character arrays
|
||||
of varying sizes. Additional character array objects are appended to
|
||||
the sequence to accommodate changes in the size of the character
|
||||
sequence.
|
||||
|
||||
@note Meets the requirements of @b Streambuf.
|
||||
|
||||
@tparam Allocator The allocator to use for managing memory.
|
||||
*/
|
||||
template<class Allocator>
|
||||
@@ -36,10 +38,14 @@ class basic_streambuf
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type of allocator used.
|
||||
using allocator_type = Allocator;
|
||||
#else
|
||||
using allocator_type = typename
|
||||
std::allocator_traits<Allocator>::
|
||||
template rebind_alloc<std::uint8_t>;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Storage for the list of buffers representing the input
|
||||
@@ -93,106 +99,104 @@ public:
|
||||
|
||||
/** Move constructor.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
The new object will have the input sequence of
|
||||
the other stream buffer, and an empty output sequence.
|
||||
|
||||
After the move, the moved-from object will have an
|
||||
empty input and output sequence, with no internal
|
||||
@note After the move, the moved-from object will have
|
||||
an empty input and output sequence, with no internal
|
||||
buffers allocated.
|
||||
|
||||
@param other The stream buffer to move from.
|
||||
*/
|
||||
basic_streambuf(basic_streambuf&& other);
|
||||
basic_streambuf(basic_streambuf&&);
|
||||
|
||||
/** Move constructor.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
The new object will have the input sequence of
|
||||
the other stream buffer, and an empty output sequence.
|
||||
|
||||
After the move, the moved-from object will have an
|
||||
empty input and output sequence, with no internal
|
||||
@note After the move, the moved-from object will have
|
||||
an empty input and output sequence, with no internal
|
||||
buffers allocated.
|
||||
|
||||
@param other The stream buffer to move from.
|
||||
|
||||
@param alloc The allocator to associate with the
|
||||
stream buffer.
|
||||
*/
|
||||
basic_streambuf(basic_streambuf&& other,
|
||||
basic_streambuf(basic_streambuf&&,
|
||||
allocator_type const& alloc);
|
||||
|
||||
/** Move assignment.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
This object will have the input sequence of
|
||||
the other stream buffer, and an empty output sequence.
|
||||
|
||||
After the move, the moved-from object will have an
|
||||
empty input and output sequence, with no internal
|
||||
@note After the move, the moved-from object will have
|
||||
an empty input and output sequence, with no internal
|
||||
buffers allocated.
|
||||
|
||||
@param other The stream buffer to move from.
|
||||
*/
|
||||
basic_streambuf&
|
||||
operator=(basic_streambuf&& other);
|
||||
|
||||
/// Copy constructor.
|
||||
basic_streambuf(basic_streambuf const& other);
|
||||
operator=(basic_streambuf&&);
|
||||
|
||||
/** Copy constructor.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
*/
|
||||
basic_streambuf(basic_streambuf const&);
|
||||
|
||||
@param other The stream buffer to copy.
|
||||
/** Copy constructor.
|
||||
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
|
||||
@param alloc The allocator to associate with the
|
||||
stream buffer.
|
||||
*/
|
||||
basic_streambuf(basic_streambuf const& other,
|
||||
basic_streambuf(basic_streambuf const&,
|
||||
allocator_type const& alloc);
|
||||
|
||||
/** Copy assignment.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
|
||||
@param other The stream buffer to copy.
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
*/
|
||||
basic_streambuf& operator=(basic_streambuf const& other);
|
||||
basic_streambuf& operator=(basic_streambuf const&);
|
||||
|
||||
/** Copy constructor.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
|
||||
@param other The stream buffer to copy.
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
*/
|
||||
template<class OtherAlloc>
|
||||
basic_streambuf(basic_streambuf<OtherAlloc> const& other);
|
||||
basic_streambuf(basic_streambuf<OtherAlloc> const&);
|
||||
|
||||
/** Copy constructor.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
|
||||
@param other The stream buffer to copy.
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
|
||||
@param alloc The allocator to associate with the
|
||||
stream buffer.
|
||||
*/
|
||||
template<class OtherAlloc>
|
||||
basic_streambuf(basic_streambuf<OtherAlloc> const& other,
|
||||
basic_streambuf(basic_streambuf<OtherAlloc> const&,
|
||||
allocator_type const& alloc);
|
||||
|
||||
/** Copy assignment.
|
||||
|
||||
The output sequence of this object will be empty.
|
||||
|
||||
@param other The stream buffer to copy.
|
||||
This object will have a copy of the other stream
|
||||
buffer's input sequence, and an empty output sequence.
|
||||
*/
|
||||
template<class OtherAlloc>
|
||||
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const& other);
|
||||
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const&);
|
||||
|
||||
/** Default constructor.
|
||||
/** Construct a stream buffer.
|
||||
|
||||
@param alloc_size The size of buffer to allocate. This is a soft
|
||||
limit, calls to prepare for buffers exceeding this size will allocate
|
||||
the larger size.
|
||||
@param alloc_size The size of buffer to allocate. This is a
|
||||
soft limit, calls to prepare for buffers exceeding this size
|
||||
will allocate the larger size. The default allocation size
|
||||
is 1KB (1024 bytes).
|
||||
|
||||
@param alloc The allocator to use.
|
||||
@param alloc The allocator to use. If this parameter is
|
||||
unspecified, a default constructed allocator will be used.
|
||||
*/
|
||||
explicit
|
||||
basic_streambuf(std::size_t alloc_size = 1024,
|
||||
@@ -219,15 +223,26 @@ public:
|
||||
return in_size_;
|
||||
}
|
||||
|
||||
/// Get a list of buffers that represents the output sequence, with the given size.
|
||||
/** Get a list of buffers that represents the output sequence, with the given size.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
mutable_buffers_type
|
||||
prepare(size_type n);
|
||||
|
||||
/// Move bytes from the output sequence to the input sequence.
|
||||
/** Move bytes from the output sequence to the input sequence.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
void
|
||||
commit(size_type n);
|
||||
|
||||
/// Get a list of buffers that represents the input sequence.
|
||||
/** Get a list of buffers that represents the input sequence.
|
||||
|
||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||
*/
|
||||
const_buffers_type
|
||||
data() const;
|
||||
|
||||
@@ -277,19 +292,9 @@ private:
|
||||
|
||||
@return The stream buffer.
|
||||
*/
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t);
|
||||
|
||||
/** Convert the entire basic_streambuf to a string.
|
||||
|
||||
@param streambuf The streambuf to convert.
|
||||
|
||||
@return A string representing the contents of the input sequence.
|
||||
*/
|
||||
template<class Allocator>
|
||||
std::string
|
||||
to_string(basic_streambuf<Allocator> const& streambuf);
|
||||
template<class Allocator, class T>
|
||||
basic_streambuf<Allocator>&
|
||||
operator<<(basic_streambuf<Allocator>& streambuf, T const& t);
|
||||
|
||||
} // beast
|
||||
|
||||
|
||||
@@ -8,110 +8,19 @@
|
||||
#ifndef BEAST_BIND_HANDLER_HPP
|
||||
#define BEAST_BIND_HANDLER_HPP
|
||||
|
||||
#include <beast/detail/integer_sequence.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <functional>
|
||||
#include <beast/handler_concepts.hpp>
|
||||
#include <beast/detail/bind_handler.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/* Nullary handler that calls Handler with bound arguments.
|
||||
|
||||
The bound handler provides the same io_service execution
|
||||
guarantees as the original handler.
|
||||
*/
|
||||
template<class Handler, class... Args>
|
||||
class bound_handler
|
||||
{
|
||||
private:
|
||||
using args_type = std::tuple<typename std::decay<Args>::type...>;
|
||||
|
||||
Handler h_;
|
||||
args_type args_;
|
||||
|
||||
template<class Tuple, std::size_t... S>
|
||||
static void invoke(Handler& h, Tuple& args,
|
||||
index_sequence<S...>)
|
||||
{
|
||||
h(std::get<S>(args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
using result_type = void;
|
||||
|
||||
template<class DeducedHandler>
|
||||
explicit
|
||||
bound_handler(DeducedHandler&& handler, Args&&... args)
|
||||
: h_(std::forward<DeducedHandler>(handler))
|
||||
, args_(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
}
|
||||
|
||||
void
|
||||
operator()() const
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate(
|
||||
std::size_t size, bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, h->h_);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate(
|
||||
void* p, std::size_t size, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, h->h_);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation (h->h_);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke(F&& f, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke(f, h->h_);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Bind parameters to a completion handler, creating a wrapped handler.
|
||||
|
||||
This function creates a new handler which invoked with no parameters
|
||||
calls the original handler with the list of bound arguments. The passed
|
||||
handler and arguments are forwarded into the returned handler, which
|
||||
provides the same `io_service` execution guarantees as the original
|
||||
This function creates a new handler which, when invoked with no
|
||||
parameters, calls the original handler with the list of bound arguments.
|
||||
The passed handler and arguments are forwarded into the returned handler,
|
||||
which provides the same `io_service` execution guarantees as the original
|
||||
handler.
|
||||
|
||||
Unlike `io_service::wrap`, the returned handler can be used in a
|
||||
@@ -145,6 +54,9 @@ detail::bound_handler<
|
||||
#endif
|
||||
bind_handler(CompletionHandler&& handler, Args&&... args)
|
||||
{
|
||||
static_assert(is_CompletionHandler<
|
||||
CompletionHandler, void(Args...)>::value,
|
||||
"CompletionHandler requirements not met");
|
||||
return detail::bound_handler<typename std::decay<
|
||||
CompletionHandler>::type, Args...>(std::forward<
|
||||
CompletionHandler>(handler),
|
||||
@@ -153,10 +65,4 @@ bind_handler(CompletionHandler&& handler, Args&&... args)
|
||||
|
||||
} // beast
|
||||
|
||||
namespace std {
|
||||
template<class Handler, class... Args>
|
||||
void bind(beast::detail::bound_handler<
|
||||
Handler, Args...>, ...) = delete;
|
||||
} // std
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_BUFFER_CAT_HPP
|
||||
#define BEAST_BUFFER_CAT_HPP
|
||||
|
||||
#include <beast/detail/buffer_cat.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -18,463 +19,9 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
class buffer_cat_helper
|
||||
{
|
||||
std::tuple<Bs...> bs_;
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
buffer_cat_helper(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper(buffer_cat_helper const&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper const&) = default;
|
||||
|
||||
explicit
|
||||
buffer_cat_helper(Bs const&... bs)
|
||||
: bs_(bs...)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
template<class U>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return sizeof(U);
|
||||
}
|
||||
|
||||
template<class U0, class U1, class... Us>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return
|
||||
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
class buffer_cat_helper<
|
||||
ValueType, Bs...>::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::tuple<Bs...> const* bs_;
|
||||
std::array<std::uint8_t,
|
||||
max_sizeof<typename Bs::const_iterator...>()> buf_;
|
||||
|
||||
friend class buffer_cat_helper<ValueType, Bs...>;
|
||||
|
||||
template<std::size_t I>
|
||||
using C = std::integral_constant<std::size_t, I>;
|
||||
|
||||
template<std::size_t I>
|
||||
using iter_t = typename std::tuple_element<
|
||||
I, std::tuple<Bs...>>::type::const_iterator;
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I>&
|
||||
iter()
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
iter_t<I>*>(buf_.data());
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I> const&
|
||||
iter() const
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
iter_t<I> const*>(buf_.data());
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
~const_iterator();
|
||||
const_iterator();
|
||||
const_iterator(const_iterator&& other);
|
||||
const_iterator(const_iterator const& other);
|
||||
const_iterator& operator=(const_iterator&& other);
|
||||
const_iterator& operator=(const_iterator const& other);
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const;
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++();
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--();
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end);
|
||||
|
||||
void
|
||||
construct(C<sizeof...(Bs)>)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
n_ = I;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
construct(C<I>)
|
||||
{
|
||||
if(std::get<I>(*bs_).begin() !=
|
||||
std::get<I>(*bs_).end())
|
||||
{
|
||||
n_ = I;
|
||||
new(buf_.data()) iter_t<I>{
|
||||
std::get<I>(*bs_).begin()};
|
||||
return;
|
||||
}
|
||||
construct(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
destroy(C<sizeof...(Bs)>)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
destroy(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
return;
|
||||
}
|
||||
destroy(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
move(C<sizeof...(Bs)>, const_iterator&&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
move(C<I>, const_iterator&& other)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
new(buf_.data()) iter_t<I>{
|
||||
std::move(other.iter<I>())};
|
||||
return;
|
||||
}
|
||||
move(C<I+1>{}, std::move(other));
|
||||
}
|
||||
|
||||
void
|
||||
copy(C<sizeof...(Bs)>, const_iterator const&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
copy(C<I>, const_iterator const& other)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
new(buf_.data()) iter_t<I>{
|
||||
other.iter<I>()};
|
||||
return;
|
||||
}
|
||||
copy(C<I+1>{}, other);
|
||||
}
|
||||
|
||||
bool
|
||||
equal(C<sizeof...(Bs)>,
|
||||
const_iterator const&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
bool
|
||||
equal(C<I>, const_iterator const& other) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return iter<I>() == other.iter<I>();
|
||||
return equal(C<I+1>{}, other);
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
reference
|
||||
dereference(C<sizeof...(Bs)>) const
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
reference
|
||||
dereference(C<I>) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return *iter<I>();
|
||||
return dereference(C<I+1>{});
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void
|
||||
increment(C<sizeof...(Bs)>)
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
increment(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(++iter<I>() !=
|
||||
std::get<I>(*bs_).end())
|
||||
return;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
return construct(C<I+1>{});
|
||||
}
|
||||
increment(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<sizeof...(Bs)>)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
if(n_ == I)
|
||||
{
|
||||
--n_;
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<0>)
|
||||
{
|
||||
auto constexpr I = 0;
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
}
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
decrement(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
}
|
||||
--n_;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::~const_iterator()
|
||||
{
|
||||
destroy(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator()
|
||||
: n_(sizeof...(Bs))
|
||||
, bs_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end)
|
||||
: bs_(&bs)
|
||||
{
|
||||
if(at_end)
|
||||
n_ = sizeof...(Bs);
|
||||
else
|
||||
construct(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(const_iterator&& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
{
|
||||
move(C<0>{}, std::move(other));
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(const_iterator const& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
{
|
||||
copy(C<0>{}, other);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator=(const_iterator&& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
if(&other == this)
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
move(C<0>{}, std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator=(const_iterator const& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
if(&other == this)
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
copy(C<0>{}, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
bool
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator==(const_iterator const& other) const
|
||||
{
|
||||
if(bs_ != other.bs_)
|
||||
return false;
|
||||
if(n_ != other.n_)
|
||||
return false;
|
||||
return equal(C<0>{}, other);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator*() const ->
|
||||
reference
|
||||
{
|
||||
return dereference(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator++() ->
|
||||
const_iterator&
|
||||
{
|
||||
increment(C<0>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator--() ->
|
||||
const_iterator&
|
||||
{
|
||||
decrement(C<sizeof...(Bs)>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, false);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, true);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Concatenate 2 or more buffer sequences to form a `ConstBufferSequence`.
|
||||
|
||||
This function returns a `ConstBufferSequence` that when iterated,
|
||||
This function returns a @b `ConstBufferSequence` that when iterated,
|
||||
efficiently concatenates the input buffer sequences. Copies of the
|
||||
arguments passed will be made; however, the returned object does
|
||||
not take ownership of the underlying memory. The application is still
|
||||
@@ -482,8 +29,8 @@ buffer_cat_helper<ValueType, Bs...>::end() const ->
|
||||
|
||||
@param buffers The list of buffer sequences to concatenate.
|
||||
|
||||
@return A new `ConstBufferSequence` that represents the concatenation
|
||||
of the input buffer sequences.
|
||||
@return A new @b `ConstBufferSequence` that represents the
|
||||
concatenation of the input buffer sequences.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template<class... BufferSequence>
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_BUFFER_CONCEPTS_HPP
|
||||
#define BEAST_BUFFER_CONCEPTS_HPP
|
||||
|
||||
#include <beast/detail/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `BufferSequence`.
|
||||
template<class T, class BufferType>
|
||||
#if GENERATING_DOCS
|
||||
struct is_BufferSequence : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_BufferSequence : detail::is_BufferSequence<T, BufferType>::type
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `ConstBufferSequence`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_ConstBufferSequence : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_ConstBufferSequence :
|
||||
is_BufferSequence<T, boost::asio::const_buffer>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `MutableBufferSequence`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_MutableBufferSequence : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_MutableBufferSequence :
|
||||
is_BufferSequence<T, boost::asio::mutable_buffer>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `Streambuf`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_Streambuf : std::integral_constant<bool, ...>
|
||||
#else
|
||||
struct is_Streambuf : detail::is_Streambuf<T>::type
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -8,15 +8,16 @@
|
||||
#ifndef BEAST_BUFFERS_ADAPTER_HPP
|
||||
#define BEAST_BUFFERS_ADAPTER_HPP
|
||||
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Adapts a `MutableBufferSequence` into a `Streambuf`.
|
||||
/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`.
|
||||
|
||||
This class wraps a `MutableBufferSequence` to meet the requirements
|
||||
of `Streambuf`. Upon construction the input and output sequences are
|
||||
This class wraps a @b `MutableBufferSequence` to meet the requirements
|
||||
of @b `Streambuf`. Upon construction the input and output sequences are
|
||||
empty. A copy of the mutable buffer sequence object is stored; however,
|
||||
ownership of the underlying memory is not transferred. The caller is
|
||||
responsible for making sure that referenced memory remains valid
|
||||
@@ -25,20 +26,18 @@ namespace beast {
|
||||
The size of the mutable buffer sequence determines the maximum
|
||||
number of bytes which may be prepared and committed.
|
||||
|
||||
@tparam Buffers The type of mutable buffer sequence to wrap.
|
||||
@tparam MutableBufferSequence The type of mutable buffer sequence to wrap.
|
||||
*/
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter
|
||||
{
|
||||
private:
|
||||
using buffers_type = typename std::decay<Buffers>::type;
|
||||
using iter_type = typename buffers_type::const_iterator;
|
||||
static_assert(is_MutableBufferSequence<MutableBufferSequence>::value,
|
||||
"MutableBufferSequence requirements not met");
|
||||
|
||||
static auto constexpr is_mutable =
|
||||
std::is_constructible<boost::asio::mutable_buffer,
|
||||
typename std::iterator_traits<iter_type>::value_type>::value;
|
||||
using iter_type = typename MutableBufferSequence::const_iterator;
|
||||
|
||||
Buffers bs_;
|
||||
MutableBufferSequence bs_;
|
||||
iter_type begin_;
|
||||
iter_type out_;
|
||||
iter_type end_;
|
||||
@@ -98,7 +97,7 @@ public:
|
||||
transferred.
|
||||
*/
|
||||
explicit
|
||||
buffers_adapter(Buffers const& buffers);
|
||||
buffers_adapter(MutableBufferSequence const& buffers);
|
||||
|
||||
/// Returns the largest size output sequence possible.
|
||||
std::size_t
|
||||
@@ -118,15 +117,25 @@ public:
|
||||
|
||||
@throws std::length_error if the size would exceed the limit
|
||||
imposed by the underlying mutable buffer sequence.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
mutable_buffers_type
|
||||
prepare(std::size_t n);
|
||||
|
||||
/// Move bytes from the output sequence to the input sequence.
|
||||
/** Move bytes from the output sequence to the input sequence.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
void
|
||||
commit(std::size_t n);
|
||||
|
||||
/// Get a list of buffers that represents the input sequence.
|
||||
/** Get a list of buffers that represents the input sequence.
|
||||
|
||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||
*/
|
||||
const_buffers_type
|
||||
data() const;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_CONSUMING_BUFFERS_HPP
|
||||
#define BEAST_CONSUMING_BUFFERS_HPP
|
||||
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -28,26 +29,29 @@ namespace beast {
|
||||
Ownership of the underlying memory is not transferred, the application
|
||||
is still responsible for managing its lifetime.
|
||||
|
||||
@tparam Buffers The buffer sequence to wrap.
|
||||
@tparam BufferSequence The buffer sequence to wrap.
|
||||
|
||||
@ptaram ValueType The type of buffer of the final buffer sequence. This
|
||||
@tparam ValueType The type of buffer of the final buffer sequence. This
|
||||
can be different from the buffer type of the wrapped sequence. For
|
||||
example, a `MutableBufferSequence` can be transformed into a
|
||||
consumable `ConstBufferSequence`. Violations of buffer const safety
|
||||
are not permitted, and will result in a compile error.
|
||||
*/
|
||||
template<class Buffers,
|
||||
class ValueType = typename Buffers::value_type>
|
||||
template<class BufferSequence,
|
||||
class ValueType = typename BufferSequence::value_type>
|
||||
class consuming_buffers
|
||||
{
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
static_assert(is_BufferSequence<BufferSequence, ValueType>::value,
|
||||
"BufferSequence requirements not met");
|
||||
|
||||
static_assert(std::is_constructible<ValueType,
|
||||
typename std::iterator_traits<iter_type>::value_type>::value,
|
||||
"ValueType requirements not met");
|
||||
|
||||
Buffers bs_;
|
||||
BufferSequence bs_;
|
||||
iter_type begin_;
|
||||
std::size_t skip_ = 0;
|
||||
|
||||
@@ -90,7 +94,7 @@ public:
|
||||
underlying memory is not transferred or copied.
|
||||
*/
|
||||
explicit
|
||||
consuming_buffers(Buffers const& buffers);
|
||||
consuming_buffers(BufferSequence const& buffers);
|
||||
|
||||
/// Get a bidirectional iterator to the first element.
|
||||
const_iterator
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_BIND_DETAIL_HANDLER_HPP
|
||||
#define BEAST_BIND_DETAIL_HANDLER_HPP
|
||||
|
||||
#include <beast/detail/integer_sequence.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
/* Nullary handler that calls Handler with bound arguments.
|
||||
|
||||
The bound handler provides the same io_service execution
|
||||
guarantees as the original handler.
|
||||
*/
|
||||
template<class Handler, class... Args>
|
||||
class bound_handler
|
||||
{
|
||||
private:
|
||||
using args_type = std::tuple<
|
||||
typename std::decay<Args>::type...>;
|
||||
|
||||
Handler h_;
|
||||
args_type args_;
|
||||
|
||||
template<class Tuple, std::size_t... S>
|
||||
static void invoke(Handler& h, Tuple& args,
|
||||
index_sequence<S...>)
|
||||
{
|
||||
h(std::get<S>(args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
using result_type = void;
|
||||
|
||||
template<class DeducedHandler>
|
||||
explicit
|
||||
bound_handler(DeducedHandler&& handler, Args&&... args)
|
||||
: h_(std::forward<DeducedHandler>(handler))
|
||||
, args_(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
}
|
||||
|
||||
void
|
||||
operator()() const
|
||||
{
|
||||
invoke(h_, args_,
|
||||
index_sequence_for<Args...> ());
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate(
|
||||
std::size_t size, bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate(size, h->h_);
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate(
|
||||
void* p, std::size_t size, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate(p, size, h->h_);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation(bound_handler* h)
|
||||
{
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation (h->h_);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke(F&& f, bound_handler* h)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke(f, h->h_);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#include <functional>
|
||||
namespace std {
|
||||
template<class Handler, class... Args>
|
||||
void bind(beast::detail::bound_handler<
|
||||
Handler, Args...>, ...) = delete;
|
||||
} // std
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,473 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_DETAIL_BUFFER_CAT_HPP
|
||||
#define BEAST_DETAIL_BUFFER_CAT_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
class buffer_cat_helper
|
||||
{
|
||||
std::tuple<Bs...> bs_;
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
buffer_cat_helper(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper(buffer_cat_helper const&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper&&) = default;
|
||||
buffer_cat_helper& operator=(buffer_cat_helper const&) = default;
|
||||
|
||||
explicit
|
||||
buffer_cat_helper(Bs const&... bs)
|
||||
: bs_(bs...)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
template<class U>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return sizeof(U);
|
||||
}
|
||||
|
||||
template<class U0, class U1, class... Us>
|
||||
std::size_t constexpr
|
||||
max_sizeof()
|
||||
{
|
||||
return
|
||||
max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
|
||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
class buffer_cat_helper<
|
||||
ValueType, Bs...>::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::tuple<Bs...> const* bs_;
|
||||
std::array<std::uint8_t,
|
||||
max_sizeof<typename Bs::const_iterator...>()> buf_;
|
||||
|
||||
friend class buffer_cat_helper<ValueType, Bs...>;
|
||||
|
||||
template<std::size_t I>
|
||||
using C = std::integral_constant<std::size_t, I>;
|
||||
|
||||
template<std::size_t I>
|
||||
using iter_t = typename std::tuple_element<
|
||||
I, std::tuple<Bs...>>::type::const_iterator;
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I>&
|
||||
iter()
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
iter_t<I>*>(buf_.data());
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
iter_t<I> const&
|
||||
iter() const
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
iter_t<I> const*>(buf_.data());
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
~const_iterator();
|
||||
const_iterator();
|
||||
const_iterator(const_iterator&& other);
|
||||
const_iterator(const_iterator const& other);
|
||||
const_iterator& operator=(const_iterator&& other);
|
||||
const_iterator& operator=(const_iterator const& other);
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const;
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++();
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--();
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end);
|
||||
|
||||
void
|
||||
construct(C<sizeof...(Bs)>)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
n_ = I;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
construct(C<I>)
|
||||
{
|
||||
if(std::get<I>(*bs_).begin() !=
|
||||
std::get<I>(*bs_).end())
|
||||
{
|
||||
n_ = I;
|
||||
new(buf_.data()) iter_t<I>{
|
||||
std::get<I>(*bs_).begin()};
|
||||
return;
|
||||
}
|
||||
construct(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
destroy(C<sizeof...(Bs)>)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
destroy(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
return;
|
||||
}
|
||||
destroy(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
move(C<sizeof...(Bs)>, const_iterator&&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
move(C<I>, const_iterator&& other)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
new(buf_.data()) iter_t<I>{
|
||||
std::move(other.iter<I>())};
|
||||
return;
|
||||
}
|
||||
move(C<I+1>{}, std::move(other));
|
||||
}
|
||||
|
||||
void
|
||||
copy(C<sizeof...(Bs)>, const_iterator const&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
copy(C<I>, const_iterator const& other)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
new(buf_.data()) iter_t<I>{
|
||||
other.iter<I>()};
|
||||
return;
|
||||
}
|
||||
copy(C<I+1>{}, other);
|
||||
}
|
||||
|
||||
bool
|
||||
equal(C<sizeof...(Bs)>,
|
||||
const_iterator const&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
bool
|
||||
equal(C<I>, const_iterator const& other) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return iter<I>() == other.iter<I>();
|
||||
return equal(C<I+1>{}, other);
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
reference
|
||||
dereference(C<sizeof...(Bs)>) const
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
reference
|
||||
dereference(C<I>) const
|
||||
{
|
||||
if(n_ == I)
|
||||
return *iter<I>();
|
||||
return dereference(C<I+1>{});
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void
|
||||
increment(C<sizeof...(Bs)>)
|
||||
{
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
increment(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(++iter<I>() !=
|
||||
std::get<I>(*bs_).end())
|
||||
return;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
return construct(C<I+1>{});
|
||||
}
|
||||
increment(C<I+1>{});
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<sizeof...(Bs)>)
|
||||
{
|
||||
auto constexpr I = sizeof...(Bs);
|
||||
if(n_ == I)
|
||||
{
|
||||
--n_;
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
|
||||
void
|
||||
decrement(C<0>)
|
||||
{
|
||||
auto constexpr I = 0;
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
}
|
||||
throw std::logic_error("invalid iterator");
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
void
|
||||
decrement(C<I>)
|
||||
{
|
||||
if(n_ == I)
|
||||
{
|
||||
if(iter<I>() != std::get<I>(*bs_).begin())
|
||||
{
|
||||
--iter<I>();
|
||||
return;
|
||||
}
|
||||
--n_;
|
||||
using Iter = iter_t<I>;
|
||||
iter<I>().~Iter();
|
||||
new(buf_.data()) iter_t<I-1>{
|
||||
std::get<I-1>(*bs_).end()};
|
||||
}
|
||||
decrement(C<I-1>{});
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::~const_iterator()
|
||||
{
|
||||
destroy(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator()
|
||||
: n_(sizeof...(Bs))
|
||||
, bs_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(
|
||||
std::tuple<Bs...> const& bs, bool at_end)
|
||||
: bs_(&bs)
|
||||
{
|
||||
if(at_end)
|
||||
n_ = sizeof...(Bs);
|
||||
else
|
||||
construct(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(const_iterator&& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
{
|
||||
move(C<0>{}, std::move(other));
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::const_iterator(const_iterator const& other)
|
||||
: n_(other.n_)
|
||||
, bs_(other.bs_)
|
||||
{
|
||||
copy(C<0>{}, other);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator=(const_iterator&& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
if(&other == this)
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
move(C<0>{}, std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator=(const_iterator const& other) ->
|
||||
const_iterator&
|
||||
{
|
||||
if(&other == this)
|
||||
return *this;
|
||||
destroy(C<0>{});
|
||||
n_ = other.n_;
|
||||
bs_ = other.bs_;
|
||||
copy(C<0>{}, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
bool
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator==(const_iterator const& other) const
|
||||
{
|
||||
if(bs_ != other.bs_)
|
||||
return false;
|
||||
if(n_ != other.n_)
|
||||
return false;
|
||||
return equal(C<0>{}, other);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator*() const ->
|
||||
reference
|
||||
{
|
||||
return dereference(C<0>{});
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator++() ->
|
||||
const_iterator&
|
||||
{
|
||||
increment(C<0>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::
|
||||
const_iterator::operator--() ->
|
||||
const_iterator&
|
||||
{
|
||||
decrement(C<sizeof...(Bs)>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, false);
|
||||
}
|
||||
|
||||
template<class ValueType, class... Bs>
|
||||
auto
|
||||
buffer_cat_helper<ValueType, Bs...>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator(bs_, true);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_DETAIL_BUFFER_CONCEPTS_HPP
|
||||
#define BEAST_DETAIL_BUFFER_CONCEPTS_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
// Types that meet the requirements,
|
||||
// for use with std::declval only.
|
||||
template<class BufferType>
|
||||
struct BufferSequence
|
||||
{
|
||||
using value_type = BufferType;
|
||||
using const_iterator = BufferType const*;
|
||||
~BufferSequence();
|
||||
BufferSequence(BufferSequence const&) = default;
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
};
|
||||
using ConstBufferSequence =
|
||||
BufferSequence<boost::asio::const_buffer>;
|
||||
using MutableBufferSequence =
|
||||
BufferSequence<boost::asio::mutable_buffer>;
|
||||
|
||||
template<class T, class BufferType>
|
||||
class is_BufferSequence
|
||||
{
|
||||
template<class U, class R = std::is_convertible<
|
||||
typename U::value_type, BufferType> >
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_base_of<
|
||||
#if 0
|
||||
std::bidirectional_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#else
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#endif
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
template<class U, class R = typename
|
||||
std::is_convertible<decltype(
|
||||
std::declval<U>().begin()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check3(int);
|
||||
template<class>
|
||||
static std::false_type check3(...);
|
||||
using type3 = decltype(check3<T>(0));
|
||||
|
||||
template<class U, class R = typename std::is_convertible<decltype(
|
||||
std::declval<U>().end()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check4(int);
|
||||
template<class>
|
||||
static std::false_type check4(...);
|
||||
using type4 = decltype(check4<T>(0));
|
||||
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
std::is_copy_constructible<T>::value &&
|
||||
std::is_destructible<T>::value &&
|
||||
type1::value && type2::value &&
|
||||
type3::value && type4::value>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_Streambuf
|
||||
{
|
||||
template<class U, class R = std::integral_constant<
|
||||
bool, is_BufferSequence<decltype(
|
||||
std::declval<U>().prepare(1)),
|
||||
boost::asio::mutable_buffer>::type::value>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::integral_constant<
|
||||
bool, is_BufferSequence<decltype(
|
||||
std::declval<U>().data()),
|
||||
boost::asio::const_buffer>::type::value>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().commit(1), std::true_type{})>
|
||||
static R check3(int);
|
||||
template<class>
|
||||
static std::false_type check3(...);
|
||||
using type3 = decltype(check3<T>(0));
|
||||
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().consume(1), std::true_type{})>
|
||||
static R check4(int);
|
||||
template<class>
|
||||
static std::false_type check4(...);
|
||||
using type4 = decltype(check4<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().size()), std::size_t>>
|
||||
static R check5(int);
|
||||
template<class>
|
||||
static std::false_type check5(...);
|
||||
using type5 = decltype(check5<T>(0));
|
||||
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
type1::value && type2::value &&
|
||||
type3::value && type4::value &&
|
||||
type5::value>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_DETAIL_STREAM_CONCEPTS_HPP
|
||||
#define BEAST_DETAIL_STREAM_CONCEPTS_HPP
|
||||
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
// Types that meet the requirements,
|
||||
// for use with std::declval only.
|
||||
struct StreamHandler
|
||||
{
|
||||
StreamHandler(StreamHandler const&) = default;
|
||||
void operator()(boost::system::error_code ec, std::size_t);
|
||||
};
|
||||
using ReadHandler = StreamHandler;
|
||||
using WriteHandler = StreamHandler;
|
||||
|
||||
template<class T>
|
||||
class has_get_io_service
|
||||
{
|
||||
template<class U, class R = typename std::is_same<
|
||||
decltype(std::declval<U>().get_io_service()),
|
||||
boost::asio::io_service&>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
public:
|
||||
using type = decltype(check<T>(0));
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_AsyncReadStream
|
||||
{
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().async_read_some(
|
||||
std::declval<MutableBufferSequence>(),
|
||||
std::declval<ReadHandler>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type1 = decltype(check<T>(0));
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
type1::value &&
|
||||
has_get_io_service<T>::type::value>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_AsyncWriteStream
|
||||
{
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().async_write_some(
|
||||
std::declval<ConstBufferSequence>(),
|
||||
std::declval<WriteHandler>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type1 = decltype(check<T>(0));
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
type1::value &&
|
||||
has_get_io_service<T>::type::value>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_SyncReadStream
|
||||
{
|
||||
using error_code =
|
||||
boost::system::error_code;
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().read_some(
|
||||
std::declval<MutableBufferSequence>())),
|
||||
std::size_t>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().read_some(
|
||||
std::declval<MutableBufferSequence>(),
|
||||
std::declval<error_code&>())), std::size_t>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
type1::value && type2::value>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class is_SyncWriteStream
|
||||
{
|
||||
using error_code =
|
||||
boost::system::error_code;
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().write_some(
|
||||
std::declval<ConstBufferSequence>())),
|
||||
std::size_t>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().write_some(
|
||||
std::declval<ConstBufferSequence>(),
|
||||
std::declval<error_code&>())), std::size_t>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
public:
|
||||
using type = std::integral_constant<bool,
|
||||
type1::value && type2::value>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
||||
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
||||
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <utility>
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_DOC_DEBUG_HPP
|
||||
#define BEAST_DOC_DEBUG_HPP
|
||||
|
||||
namespace beast {
|
||||
|
||||
#if GENERATING_DOCS
|
||||
|
||||
/// doc type (documentation debug helper)
|
||||
using doc_type = int;
|
||||
|
||||
/// doc enum (documentation debug helper)
|
||||
enum doc_enum
|
||||
{
|
||||
/// One (documentation debug helper)
|
||||
one,
|
||||
|
||||
/// Two (documentation debug helper)
|
||||
two
|
||||
};
|
||||
|
||||
/// doc enum class (documentation debug helper)
|
||||
enum class doc_enum_class : unsigned
|
||||
{
|
||||
/// one (documentation debug helper)
|
||||
one,
|
||||
|
||||
/// two (documentation debug helper)
|
||||
two
|
||||
};
|
||||
|
||||
/// doc func (documentation debug helper)
|
||||
void doc_func();
|
||||
|
||||
/// doc class (documentation debug helper)
|
||||
struct doc_class
|
||||
{
|
||||
/// doc class member func (documentation debug helper)
|
||||
void func();
|
||||
};
|
||||
|
||||
/// (documentation debug helper)
|
||||
namespace nested {
|
||||
|
||||
/// doc type (documentation debug helper)
|
||||
using nested_doc_type = int;
|
||||
|
||||
/// doc enum (documentation debug helper)
|
||||
enum nested_doc_enum
|
||||
{
|
||||
/// One (documentation debug helper)
|
||||
one,
|
||||
|
||||
/// Two (documentation debug helper)
|
||||
two
|
||||
};
|
||||
|
||||
/// doc enum class (documentation debug helper)
|
||||
enum class nested_doc_enum_class : unsigned
|
||||
{
|
||||
/// one (documentation debug helper)
|
||||
one,
|
||||
|
||||
/// two (documentation debug helper)
|
||||
two
|
||||
};
|
||||
|
||||
/// doc func (documentation debug helper)
|
||||
void nested_doc_func();
|
||||
|
||||
/// doc class (documentation debug helper)
|
||||
struct nested_doc_class
|
||||
{
|
||||
/// doc class member func (documentation debug helper)
|
||||
void func();
|
||||
};
|
||||
|
||||
} // nested
|
||||
|
||||
/** This is here to help troubleshoot doc/reference.xsl problems
|
||||
|
||||
Embedded references:
|
||||
|
||||
@li type @ref doc_type
|
||||
|
||||
@li enum @ref doc_enum
|
||||
|
||||
@li enum item @ref doc_enum::one
|
||||
|
||||
@li enum_class @ref doc_enum_class
|
||||
|
||||
@li enum_class item @ref doc_enum_class::one
|
||||
|
||||
@li func @ref doc_func
|
||||
|
||||
@li class @ref doc_class
|
||||
|
||||
@li class func @ref doc_class::func
|
||||
|
||||
@li nested type @ref nested::nested_doc_type
|
||||
|
||||
@li nested enum @ref nested::nested_doc_enum
|
||||
|
||||
@li nested enum item @ref nested::nested_doc_enum::one
|
||||
|
||||
@li nested enum_class @ref nested::nested_doc_enum_class
|
||||
|
||||
@li nested enum_class item @ref nested::nested_doc_enum_class::one
|
||||
|
||||
@li nested func @ref nested::nested_doc_func
|
||||
|
||||
@li nested class @ref nested::nested_doc_class
|
||||
|
||||
@li nested class func @ref nested::nested_doc_class::func
|
||||
*/
|
||||
void doc_debug();
|
||||
|
||||
namespace nested {
|
||||
|
||||
/** This is here to help troubleshoot doc/reference.xsl problems
|
||||
|
||||
Embedded references:
|
||||
|
||||
@li type @ref doc_type
|
||||
|
||||
@li enum @ref doc_enum
|
||||
|
||||
@li enum item @ref doc_enum::one
|
||||
|
||||
@li enum_class @ref doc_enum_class
|
||||
|
||||
@li enum_class item @ref doc_enum_class::one
|
||||
|
||||
@li func @ref doc_func
|
||||
|
||||
@li class @ref doc_class
|
||||
|
||||
@li class func @ref doc_class::func
|
||||
|
||||
@li nested type @ref nested_doc_type
|
||||
|
||||
@li nested enum @ref nested_doc_enum
|
||||
|
||||
@li nested enum item @ref nested_doc_enum::one
|
||||
|
||||
@li nested enum_class @ref nested_doc_enum_class
|
||||
|
||||
@li nested enum_class item @ref nested_doc_enum_class::one
|
||||
|
||||
@li nested func @ref nested_doc_func
|
||||
|
||||
@li nested class @ref nested_doc_class
|
||||
|
||||
@li nested class func @ref nested_doc_class::func
|
||||
*/
|
||||
void nested_doc_debug();
|
||||
|
||||
} // nested
|
||||
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -28,28 +28,28 @@ namespace beast {
|
||||
|
||||
@tparam T The type of objects allocated by the allocator.
|
||||
|
||||
@tparam Handler The type of handler.
|
||||
@tparam CompletionHandler The type of handler.
|
||||
|
||||
@note Allocated memory is only valid until the handler is called. The
|
||||
caller is still responsible for freeing memory.
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
template <class T, class Handler>
|
||||
template <class T, class CompletionHandler>
|
||||
class handler_alloc;
|
||||
#else
|
||||
template <class T, class Handler>
|
||||
template <class T, class CompletionHandler>
|
||||
class handler_alloc
|
||||
{
|
||||
private:
|
||||
// We want a partial template specialization as a friend
|
||||
// but that isn't allowed so we friend all versions. This
|
||||
// should produce a compile error if Handler is not
|
||||
// should produce a compile error if CompletionHandler is not
|
||||
// constructible from H.
|
||||
//
|
||||
template <class U, class H>
|
||||
friend class handler_alloc;
|
||||
|
||||
Handler h_;
|
||||
CompletionHandler h_;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
The handler is moved or copied into the allocator.
|
||||
*/
|
||||
explicit
|
||||
handler_alloc(Handler&& h)
|
||||
handler_alloc(CompletionHandler&& h)
|
||||
: h_(std::move(h))
|
||||
{
|
||||
}
|
||||
@@ -76,21 +76,21 @@ public:
|
||||
A copy of the handler is made.
|
||||
*/
|
||||
explicit
|
||||
handler_alloc(Handler const& h)
|
||||
handler_alloc(CompletionHandler const& h)
|
||||
: h_(h)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
handler_alloc(
|
||||
handler_alloc<U, Handler>&& other)
|
||||
handler_alloc<U, CompletionHandler>&& other)
|
||||
: h_(std::move(other.h_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
handler_alloc(
|
||||
handler_alloc<U, Handler> const& other)
|
||||
handler_alloc<U, CompletionHandler> const& other)
|
||||
: h_(other.h_)
|
||||
{
|
||||
}
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
friend
|
||||
bool
|
||||
operator==(handler_alloc const& lhs,
|
||||
handler_alloc<U, Handler> const& rhs)
|
||||
handler_alloc<U, CompletionHandler> const& rhs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
friend
|
||||
bool
|
||||
operator!=(handler_alloc const& lhs,
|
||||
handler_alloc<U, Handler> const& rhs)
|
||||
handler_alloc<U, CompletionHandler> const& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HANDLER_CONCEPTS_HPP
|
||||
#define BEAST_HANDLER_CONCEPTS_HPP
|
||||
|
||||
#include <beast/detail/is_call_possible.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `CompletionHandler`.
|
||||
template<class T, class Signature>
|
||||
#if GENERATING_DOCS
|
||||
using is_CompletionHandler = std::integral_constant<bool, ...>;
|
||||
#else
|
||||
using is_CompletionHandler = std::integral_constant<bool,
|
||||
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
||||
detail::is_call_possible<T, Signature>::value>;
|
||||
#endif
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -5,12 +5,12 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_HPP_INCLUDED
|
||||
#define BEAST_HTTP_HPP_INCLUDED
|
||||
#ifndef BEAST_HTTP_HPP
|
||||
#define BEAST_HTTP_HPP
|
||||
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/http/basic_parser_v1.hpp>
|
||||
#include <beast/http/body_writer.hpp>
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/http/empty_body.hpp>
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
#define BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/detail/ci_char_traits.hpp>
|
||||
#include <beast/detail/empty_base_optimization.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
@@ -237,9 +236,20 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Container to store HTTP headers.
|
||||
/** A container for storing HTTP headers.
|
||||
|
||||
Meets the requirements of `FieldSequence`.
|
||||
This container is designed to store the field value pairs that make
|
||||
up the headers and trailers in a HTTP message. Objects of this type
|
||||
are iterable, which each element holding the field name and field
|
||||
value.
|
||||
|
||||
Field names are stored as-is, but comparison are case-insensitive.
|
||||
The container preserves the order of insertion of fields with
|
||||
different names. For fields with the same name, the implementation
|
||||
concatenates values inserted with duplicate names as per the
|
||||
rules in rfc2616 section 4.2.
|
||||
|
||||
@note Meets the requirements of @b `FieldSequence`.
|
||||
*/
|
||||
template<class Allocator>
|
||||
class basic_headers
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <beast/http/parse_error.hpp>
|
||||
#include <beast/http/rfc7230.hpp>
|
||||
#include <beast/http/detail/basic_parser_v1.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
@@ -43,49 +42,49 @@ enum values
|
||||
if those members are present (detected through SFINAE). The
|
||||
signatures which can be present in the derived class are:<br>
|
||||
|
||||
@li `void on_method(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_method(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the Request-Method
|
||||
|
||||
@li `void on_uri(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_uri(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the Request-URI
|
||||
|
||||
@li `void on_reason(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_reason(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the reason-phrase
|
||||
|
||||
@li `void on_request(error_code& ec)`
|
||||
@li `void on_request(error_code&)`
|
||||
|
||||
Called after the entire Request-Line has been parsed successfully.
|
||||
|
||||
@li `void on_response(error_code& ec)`
|
||||
@li `void on_response(error_code&)`
|
||||
|
||||
Called after the entire Response-Line has been parsed successfully.
|
||||
|
||||
@li `void on_field(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_field(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the current header field.
|
||||
|
||||
@li `void on_value(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_value(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the current header value.
|
||||
|
||||
@li `int on_headers(error_code& ec)`
|
||||
@li `int on_headers(error_code&)`
|
||||
|
||||
Called when all the headers have been parsed successfully.
|
||||
|
||||
@li `void on_body(boost::string_ref const&, error_code& ec)`
|
||||
@li `void on_body(boost::string_ref const&, error_code&)`
|
||||
|
||||
Called for each piece of the body. If the headers indicated
|
||||
chunked encoding, the chunk encoding is removed from the
|
||||
buffer before being passed to the callback.
|
||||
|
||||
@li `void on_complete(error_code& ec)`
|
||||
@li `void on_complete(error_code&)`
|
||||
|
||||
Called when the entire message has been parsed successfully.
|
||||
At this point, basic_parser_v1::complete() returns `true`, and
|
||||
the parser is ready to parse another message if keep_alive()
|
||||
At this point, @ref basic_parser_v1::complete returns `true`, and
|
||||
the parser is ready to parse another message if keep_alive
|
||||
would return `true`.
|
||||
|
||||
The return value of `on_headers` is special, it controls whether
|
||||
@@ -101,7 +100,7 @@ enum values
|
||||
|
||||
The parser uses traits to determine if the callback is possible.
|
||||
If the Derived type omits one or more callbacks, they are simply
|
||||
skipped with no compilation error. The default behavior of on_body
|
||||
skipped with no compilation error. The default behavior of `on_body`
|
||||
when the derived class does not provide the member, is to specify that
|
||||
the body should not be skipped.
|
||||
|
||||
@@ -354,12 +353,15 @@ public:
|
||||
|
||||
@return The number of bytes consumed in the input sequence.
|
||||
*/
|
||||
template<class ConstBufferSequence,
|
||||
class = typename std::enable_if<
|
||||
! std::is_convertible<ConstBufferSequence,
|
||||
boost::asio::const_buffer>::value>::type
|
||||
>
|
||||
template<class ConstBufferSequence>
|
||||
#if GENERATING_DOCS
|
||||
std::size_t
|
||||
#else
|
||||
typename std::enable_if<
|
||||
! std::is_convertible<ConstBufferSequence,
|
||||
boost::asio::const_buffer>::value,
|
||||
std::size_t>::type
|
||||
#endif
|
||||
write(ConstBufferSequence const& buffers, error_code& ec);
|
||||
|
||||
/** Write a single buffer of data to the parser.
|
||||
@@ -380,8 +382,6 @@ public:
|
||||
Callbacks and errors will still be processed as usual.
|
||||
|
||||
@note This is typically called when a socket read returns eof.
|
||||
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
void
|
||||
write_eof(error_code& ec);
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_BODY_WRITER_HPP
|
||||
#define BEAST_HTTP_BODY_WRITER_HPP
|
||||
#ifndef BEAST_HTTP_BODY_TYPE_HPP
|
||||
#define BEAST_HTTP_BODY_TYPE_HPP
|
||||
|
||||
// Convenience header to include everything necessary for
|
||||
// declaring an object meeting the BodyWriter requirements.
|
||||
// Convenience header to include everything
|
||||
// needed when declarating a user defined Body type.
|
||||
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_HTTP_EMPTY_BODY_HPP
|
||||
#define BEAST_HTTP_EMPTY_BODY_HPP
|
||||
|
||||
#include <beast/http/body_writer.hpp>
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <memory>
|
||||
@@ -18,6 +18,8 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** An empty content-body.
|
||||
|
||||
Meets the requirements of @b `Body`.
|
||||
*/
|
||||
struct empty_body
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BEAST_HTTP_ERROR_HPP
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
@@ -32,8 +34,11 @@ keep_alive() const
|
||||
// Implementation inspired by nodejs/http-parser
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
template<class ConstBufferSequence, class>
|
||||
std::size_t
|
||||
template<class ConstBufferSequence>
|
||||
typename std::enable_if<
|
||||
! std::is_convertible<ConstBufferSequence,
|
||||
boost::asio::const_buffer>::value,
|
||||
std::size_t>::type
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/http/detail/has_content_length.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <beast/stream_concepts.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
#include <beast/http/detail/has_content_length.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <beast/stream_concepts.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define BEAST_HTTP_MESSAGE_HPP
|
||||
|
||||
#include <beast/http/basic_headers.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define BEAST_HTTP_MESSAGE_V1_HPP
|
||||
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -92,7 +91,7 @@ is_upgrade(message_v1<isRequest, Body, Headers> const& msg);
|
||||
|
||||
/** HTTP/1 connection prepare options.
|
||||
|
||||
@note These values are used with `prepare`.
|
||||
@note These values are used with @ref prepare.
|
||||
*/
|
||||
enum class connection
|
||||
{
|
||||
|
||||
+58
-20
@@ -19,17 +19,29 @@ namespace http {
|
||||
|
||||
/** Read a HTTP/1 message from a stream.
|
||||
|
||||
@param stream The stream to read the message from.
|
||||
This function is used to synchronously read a message from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
|
||||
@param streambuf A Streambuf used to hold unread bytes. The
|
||||
implementation may read past the end of the message. The extra
|
||||
bytes are stored here, to be presented in a subsequent call to
|
||||
read.
|
||||
@li A complete message is read in.
|
||||
|
||||
@param msg An object used to store the read message. Any
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to the
|
||||
stream's `read_some` function.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncReadStream` concept.
|
||||
|
||||
@param streambuf An object meeting the @b `Streambuf` type requirements
|
||||
used to hold unread bytes. The implementation may read past the end of
|
||||
the message. The extra bytes are stored here, to be presented in a
|
||||
subsequent call to @ref read.
|
||||
|
||||
@param msg An object used to store the message. Any
|
||||
contents will be overwritten.
|
||||
|
||||
@throws boost::system::system_error on failure.
|
||||
@throws boost::system::system_error Thrown on failure.
|
||||
*/
|
||||
template<class SyncReadStream, class Streambuf,
|
||||
bool isRequest, class Body, class Headers>
|
||||
@@ -43,17 +55,29 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
throw boost::system::system_error{ec};
|
||||
}
|
||||
|
||||
/** Read a HTTP message from a stream.
|
||||
/** Read a HTTP/1 message from a stream.
|
||||
|
||||
@param stream The stream to read the message from.
|
||||
This function is used to synchronously read a message from
|
||||
the stream. The call blocks until one of the following conditions
|
||||
is true:
|
||||
|
||||
@param streambuf A Streambuf used to hold unread bytes. The
|
||||
implementation may read past the end of the message. The extra
|
||||
bytes are stored here, to be presented in a subsequent call to
|
||||
read.
|
||||
@li A complete message is read in.
|
||||
|
||||
@param msg An object used to store the read message. Any
|
||||
contents will be overwritten.
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to the
|
||||
stream's `read_some` function.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncReadStream` concept.
|
||||
|
||||
@param streambuf An object meeting the @b `Streambuf` type requirements
|
||||
used to hold unread bytes. The implementation may read past the end of
|
||||
the message. The extra bytes are stored here, to be presented in a
|
||||
subsequent call to @ref read.
|
||||
|
||||
@param msg An object used to store the message. Any contents
|
||||
will be overwritten.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
@@ -64,17 +88,31 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
message_v1<isRequest, Body, Headers>& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start reading a HTTP message from a stream asynchronously.
|
||||
/** Start an asynchronous operation to read a HTTP/1 message from a stream.
|
||||
|
||||
This function is used to asynchronously read a message from the
|
||||
stream. The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
|
||||
@li A complete message is read in.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one 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 operations until this operation completes.
|
||||
|
||||
@param stream The stream to read the message from.
|
||||
The type must support the @b `AsyncReadStream` concept.
|
||||
|
||||
@param streambuf A Streambuf used to hold unread bytes. The
|
||||
implementation may read past the end of the message. The extra
|
||||
bytes are stored here, to be presented in a subsequent call to
|
||||
async_read.
|
||||
@ref async_read.
|
||||
|
||||
@param msg An object used to store the read message. Any
|
||||
contents will be overwritten.
|
||||
@param msg An object used to store the message. Any contents
|
||||
will be overwritten.
|
||||
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
@@ -85,7 +123,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
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_service::post().
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class AsyncReadStream, class Streambuf,
|
||||
bool isRequest, class Body, class Headers,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||
#define BEAST_HTTP_STREAMBUF_BODY_HPP
|
||||
|
||||
#include <beast/http/body_writer.hpp>
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <memory>
|
||||
@@ -17,7 +17,9 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A Body represented by a Streambuf
|
||||
/** A message body represented by a Streambuf
|
||||
|
||||
Meets the requirements of @b `Body`.
|
||||
*/
|
||||
template<class Streambuf>
|
||||
struct basic_streambuf_body
|
||||
@@ -34,10 +36,10 @@ private:
|
||||
value_type& sb_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Allocator>
|
||||
template<bool isRequest, class Headers>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
basic_streambuf_body, Allocator>& m) noexcept
|
||||
basic_streambuf_body, Headers>& m) noexcept
|
||||
: sb_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_HTTP_STRING_BODY_HPP
|
||||
#define BEAST_HTTP_STRING_BODY_HPP
|
||||
|
||||
#include <beast/http/body_writer.hpp>
|
||||
#include <beast/http/body_type.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <memory>
|
||||
@@ -18,6 +18,8 @@ namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A Body represented by a std::string.
|
||||
|
||||
Meets the requirements of @b `Body`.
|
||||
*/
|
||||
struct string_body
|
||||
{
|
||||
@@ -33,10 +35,10 @@ private:
|
||||
value_type& s_;
|
||||
|
||||
public:
|
||||
template<bool isRequest, class Allocator>
|
||||
template<bool isRequest, class Headers>
|
||||
explicit
|
||||
reader(message<isRequest,
|
||||
string_body, Allocator>& m) noexcept
|
||||
string_body, Headers>& m) noexcept
|
||||
: s_(m.body)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,13 +18,30 @@
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Write a HTTP/1 message to a stream.
|
||||
/** Write a HTTP/1 message on a stream.
|
||||
|
||||
@param stream The stream to send the message on.
|
||||
This function is used to write a message to a stream. The call
|
||||
will block until one of the following conditions is true:
|
||||
|
||||
@param msg The message to send.
|
||||
@li The entire message is sent.
|
||||
|
||||
@throws boost::system::error code on failure.
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls
|
||||
to the stream's `write_some` function.
|
||||
|
||||
The implementation will automatically perform chunk encoding if
|
||||
the contents of the message indicate that chunk encoding is required.
|
||||
If the semantics of the message indicate that the connection should
|
||||
be closed after the message is sent, the error returns from this
|
||||
function will be `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncWriteStream` concept.
|
||||
|
||||
@param msg The message to write.
|
||||
|
||||
@throws boost::system::error Thrown on failure.
|
||||
*/
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
@@ -32,11 +49,28 @@ void
|
||||
write(SyncWriteStream& stream,
|
||||
message_v1<isRequest, Body, Headers> const& msg);
|
||||
|
||||
/** Write a HTTP/1 message to a stream.
|
||||
/** Write a HTTP/1 message on a stream.
|
||||
|
||||
@param stream The stream to send the message on.
|
||||
This function is used to write a message to a stream. The call
|
||||
will block until one of the following conditions is true:
|
||||
|
||||
@param msg The message to send.
|
||||
@li The entire message is sent.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls
|
||||
to the stream's `write_some` function.
|
||||
|
||||
The implementation will automatically perform chunk encoding if
|
||||
the contents of the message indicate that chunk encoding is required.
|
||||
If the semantics of the message indicate that the connection should
|
||||
be closed after the message is sent, the error returns from this
|
||||
function will be `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `SyncWriteStream` concept.
|
||||
|
||||
@param msg The message to write.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
@@ -47,13 +81,35 @@ write(SyncWriteStream& stream,
|
||||
message_v1<isRequest, Body, Headers> const& msg,
|
||||
error_code& ec);
|
||||
|
||||
/** Start writing a HTTP/1 message to a stream asynchronously.
|
||||
/** Start an asynchronous operation to write a HTTP/1 message to a stream.
|
||||
|
||||
@param stream The stream to send the message on.
|
||||
This function is used to asynchronously write a message to a stream.
|
||||
The function call always returns immediately. The asynchronous
|
||||
operation will continue until one of the following conditions is true:
|
||||
|
||||
@li The entire message is sent.
|
||||
|
||||
@li An error occurs.
|
||||
|
||||
This operation is implemented in terms of one or more calls to the
|
||||
stream's `async_write_some` functions, and is known as a <em>composed
|
||||
operation</em>. The program must ensure that the stream performs no
|
||||
other write operations (such as @ref async_write, the stream's
|
||||
`async_write_some` function, or any other composed operations that
|
||||
perform writes) until this operation completes.
|
||||
|
||||
The implementation will automatically perform chunk encoding if
|
||||
the contents of the message indicate that chunk encoding is required.
|
||||
If the semantics of the message indicate that the connection should
|
||||
be closed after the message is sent, the operation will complete with
|
||||
the error set to `boost::asio::error::eof`.
|
||||
|
||||
@param stream The stream to which the data is to be written.
|
||||
The type must support the @b `AsyncWriteStream` concept.
|
||||
|
||||
@param msg The message to send.
|
||||
|
||||
@param token The handler to be called when the request completes.
|
||||
@param handler The handler to be called when the request completes.
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@code void handler(
|
||||
@@ -62,9 +118,9 @@ write(SyncWriteStream& stream,
|
||||
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_service::post().
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
|
||||
@note The message must remain valid at least until the
|
||||
@note The message object must remain valid at least until the
|
||||
completion handler is called, no copies are made.
|
||||
*/
|
||||
template<class AsyncWriteStream,
|
||||
@@ -85,6 +141,9 @@ async_write(AsyncWriteStream& stream,
|
||||
The function converts the message to its HTTP/1 serialized
|
||||
representation and stores the result in the output stream.
|
||||
|
||||
The implementation will automatically perform chunk encoding if
|
||||
the contents of the message indicate that chunk encoding is required.
|
||||
|
||||
@param os The ostream to write to.
|
||||
|
||||
@param msg The message to write.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||
#define BEAST_IMPL_BASIC_STREAMBUF_IPP
|
||||
|
||||
#include <beast/detail/write_streambuf.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
@@ -849,22 +850,6 @@ basic_streambuf<Allocator>::debug_check() const
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
auto const& s = ss.str();
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()), buffer(s)));
|
||||
return streambuf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Allocator>
|
||||
std::size_t
|
||||
read_size_helper(basic_streambuf<
|
||||
@@ -874,17 +859,12 @@ read_size_helper(basic_streambuf<
|
||||
std::max<std::size_t>(512, streambuf.prepare_size()));
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
std::string
|
||||
to_string(basic_streambuf<Allocator> const& streambuf)
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
std::string s;
|
||||
s.resize(streambuf.size());
|
||||
buffer_copy(
|
||||
buffer(&s[0], s.size()), streambuf.data());
|
||||
return s;
|
||||
detail::write_streambuf(streambuf, t);
|
||||
return streambuf;
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
@@ -48,8 +49,9 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
const_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_ = nullptr;
|
||||
@@ -136,19 +138,19 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
||||
buffers_adapter<MutableBufferSequence>::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->begin_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
buffers_adapter<MutableBufferSequence>::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_ ==
|
||||
@@ -157,8 +159,9 @@ buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
@@ -189,8 +192,9 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
||||
template<class MutableBufferSequence>
|
||||
class buffers_adapter<MutableBufferSequence>::
|
||||
mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_ = nullptr;
|
||||
@@ -277,19 +281,19 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
buffers_adapter<MutableBufferSequence>::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
@@ -297,8 +301,8 @@ buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
@@ -307,8 +311,8 @@ buffers_adapter<Buffers>::buffers_adapter(
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
@@ -317,9 +321,9 @@ buffers_adapter<Buffers>::buffers_adapter(
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter<MutableBufferSequence>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
@@ -340,9 +344,9 @@ buffers_adapter<Buffers>::operator=(
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter<MutableBufferSequence>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
@@ -363,9 +367,9 @@ buffers_adapter<Buffers>::operator=(
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
Buffers const& bs)
|
||||
template<class MutableBufferSequence>
|
||||
buffers_adapter<MutableBufferSequence>::buffers_adapter(
|
||||
MutableBufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
@@ -374,14 +378,12 @@ buffers_adapter<Buffers>::buffers_adapter(
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
auto
|
||||
buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
||||
buffers_adapter<MutableBufferSequence>::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
end_ = out_;
|
||||
if(end_ != bs_.end())
|
||||
{
|
||||
@@ -416,13 +418,11 @@ buffers_adapter<Buffers>::prepare(std::size_t n) ->
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
buffers_adapter<Buffers>::commit(std::size_t n)
|
||||
buffers_adapter<MutableBufferSequence>::commit(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
static_assert(is_mutable,
|
||||
"Operation not valid for ConstBufferSequence");
|
||||
if(out_ == end_)
|
||||
return;
|
||||
auto const last = std::prev(end_);
|
||||
@@ -456,18 +456,18 @@ buffers_adapter<Buffers>::commit(std::size_t n)
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::data() const ->
|
||||
buffers_adapter<MutableBufferSequence>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
||||
buffers_adapter<MutableBufferSequence>::consume(std::size_t n)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
||||
template<class BufferSequence, class ValueType>
|
||||
class consuming_buffers<BufferSequence, ValueType>::const_iterator
|
||||
{
|
||||
friend class consuming_buffers<Buffers, ValueType>;
|
||||
friend class consuming_buffers<BufferSequence, ValueType>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
consuming_buffers const* b_ = nullptr;
|
||||
@@ -105,8 +105,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
template<class BufferSequence, class ValueType>
|
||||
consuming_buffers<BufferSequence, ValueType>::
|
||||
consuming_buffers(consuming_buffers&& other)
|
||||
: consuming_buffers(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
@@ -114,8 +114,8 @@ consuming_buffers(consuming_buffers&& other)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
template<class BufferSequence, class ValueType>
|
||||
consuming_buffers<BufferSequence, ValueType>::
|
||||
consuming_buffers(consuming_buffers const& other)
|
||||
: consuming_buffers(other,
|
||||
std::distance<iter_type>(
|
||||
@@ -123,9 +123,9 @@ consuming_buffers(consuming_buffers const& other)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
template<class BufferSequence, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers<BufferSequence, ValueType>::
|
||||
operator=(consuming_buffers&& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
@@ -137,9 +137,9 @@ operator=(consuming_buffers&& other) ->
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
template<class BufferSequence, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers<BufferSequence, ValueType>::
|
||||
operator=(consuming_buffers const& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
@@ -151,35 +151,35 @@ operator=(consuming_buffers const& other) ->
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(Buffers const& bs)
|
||||
template<class BufferSequence, class ValueType>
|
||||
consuming_buffers<BufferSequence, ValueType>::
|
||||
consuming_buffers(BufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
{
|
||||
static_assert(is_BufferSequence<Buffers, ValueType>::value,
|
||||
static_assert(is_BufferSequence<BufferSequence, ValueType>::value,
|
||||
"BufferSequence requirements not met");
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
template<class BufferSequence, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
||||
consuming_buffers<BufferSequence, ValueType>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, begin_};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
template<class BufferSequence, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
||||
consuming_buffers<BufferSequence, ValueType>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
template<class BufferSequence, class ValueType>
|
||||
void
|
||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
consuming_buffers<BufferSequence, ValueType>::consume(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||
@@ -196,11 +196,11 @@ consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
||||
template<class BufferSequence>
|
||||
consuming_buffers<BufferSequence, typename BufferSequence::value_type>
|
||||
consumed_buffers(BufferSequence const& bs, std::size_t n)
|
||||
{
|
||||
consuming_buffers<Buffers> cb(bs);
|
||||
consuming_buffers<BufferSequence> cb(bs);
|
||||
cb.consume(n);
|
||||
return cb;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
#define BEAST_IMPL_STREAMBUF_READSTREAM_IPP
|
||||
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_concepts.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -157,8 +160,6 @@ streambuf_readstream<Stream, Streambuf>::
|
||||
streambuf_readstream(Args&&... args)
|
||||
: next_layer_(std::forward<Args>(args)...)
|
||||
{
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
}
|
||||
|
||||
template<class Stream, class Streambuf>
|
||||
@@ -175,7 +176,7 @@ async_write_some(ConstBufferSequence const& buffers,
|
||||
static_assert(is_ConstBufferSequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
static_assert(is_Handler<WriteHandler,
|
||||
static_assert(is_CompletionHandler<WriteHandler,
|
||||
void(error_code, std::size_t)>::value,
|
||||
"WriteHandler requirements not met");
|
||||
return next_layer_.async_write_some(buffers,
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A `Streambuf` with a fixed size internal buffer.
|
||||
/** A @b `Streambuf` with a fixed size internal buffer.
|
||||
|
||||
Ownership of the underlying storage belongs to the derived class.
|
||||
|
||||
@note Variables are usually declared using the template class
|
||||
`static_streambuf_n`; however, to reduce the number of instantiations
|
||||
@ref static_streambuf_n; however, to reduce the number of instantiations
|
||||
of template functions receiving static stream buffer arguments in a
|
||||
deduced context, the signature of the receiving function should use
|
||||
`static_streambuf`.
|
||||
@ref static_streambuf.
|
||||
*/
|
||||
class static_streambuf
|
||||
{
|
||||
@@ -75,18 +75,28 @@ public:
|
||||
|
||||
@throws std::length_error if the size would exceed the limit
|
||||
imposed by the underlying mutable buffer sequence.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
mutable_buffers_type
|
||||
prepare(std::size_t n);
|
||||
|
||||
/// Move bytes from the output sequence to the input sequence.
|
||||
/** Move bytes from the output sequence to the input sequence.
|
||||
|
||||
@note Buffers representing the input sequence acquired prior to
|
||||
this call remain valid.
|
||||
*/
|
||||
void
|
||||
commit(std::size_t n)
|
||||
{
|
||||
out_ += std::min<std::size_t>(n, last_ - out_);
|
||||
}
|
||||
|
||||
/// Get a list of buffers that represents the input sequence.
|
||||
/** Get a list of buffers that represents the input sequence.
|
||||
|
||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
||||
*/
|
||||
const_buffers_type
|
||||
data() const;
|
||||
|
||||
@@ -129,9 +139,11 @@ protected:
|
||||
*/
|
||||
template<std::size_t N>
|
||||
class static_streambuf_n
|
||||
: private boost::base_from_member<
|
||||
: public static_streambuf
|
||||
#if ! GENERATING_DOCS
|
||||
, private boost::base_from_member<
|
||||
std::array<std::uint8_t, N>>
|
||||
, public static_streambuf
|
||||
#endif
|
||||
{
|
||||
using member_type = boost::base_from_member<
|
||||
std::array<std::uint8_t, N>>;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -28,13 +27,11 @@
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/** A string with a fixed-size storage area.
|
||||
|
||||
`static_string` objects behave like `std::string` except that
|
||||
the storage is not dynamically allocated but rather fixed in
|
||||
size.
|
||||
These objects behave like `std::string` except that the storage
|
||||
is not dynamically allocated but rather fixed in size.
|
||||
|
||||
These strings offer performance advantages when a protocol
|
||||
imposes a natural small upper limit on the size of a value.
|
||||
@@ -281,7 +278,7 @@ public:
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
|
||||
/// Reduces memory usage by freeing unused memory.
|
||||
void
|
||||
shrink_to_fit()
|
||||
@@ -401,7 +398,7 @@ operator=(const CharT (&s)[M]) ->
|
||||
static_assert(M-1 <= N,
|
||||
"static_string overflow");
|
||||
n_ = M-1;
|
||||
std::copy(&s[0], &s[M], &s_[0]);
|
||||
Traits::copy(&s_[0], &s[0], M);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -690,7 +687,6 @@ bool operator>=(
|
||||
|
||||
#endif
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_STREAM_CONCEPTS_HPP
|
||||
#define BEAST_STREAM_CONCEPTS_HPP
|
||||
|
||||
#include <beast/detail/stream_concepts.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/// Determine if `T` has the `get_io_service` member.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct has_get_io_service : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using has_get_io_service = typename detail::has_get_io_service<T>::type;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `AsyncReadStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_AsyncReadStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_AsyncReadStream = typename detail::is_AsyncReadStream<T>::type;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `AsyncWriteStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_AsyncWriteStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_AsyncWriteStream = typename detail::is_AsyncWriteStream<T>::type;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `SyncReadStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_SyncReadStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_SyncReadStream = typename detail::is_SyncReadStream<T>::type;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `SyncWriterStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_SyncWriteStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_SyncWriteStream = typename detail::is_SyncWriteStream<T>::type;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `AsyncStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_AsyncStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_AsyncStream = std::integral_constant<bool,
|
||||
is_AsyncReadStream<T>::value && is_AsyncWriteStream<T>::value>;
|
||||
#endif
|
||||
|
||||
/// Determine if `T` meets the requirements of @b `SyncStream`.
|
||||
template<class T>
|
||||
#if GENERATING_DOCS
|
||||
struct is_SyncStream : std::integral_constant<bool, ...>{};
|
||||
#else
|
||||
using is_SyncStream = std::integral_constant<bool,
|
||||
is_SyncReadStream<T>::value && is_SyncWriteStream<T>::value>;
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,15 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A @b `Streambuf` that uses multiple buffers internally.
|
||||
|
||||
The implementation uses a sequence of one or more character arrays
|
||||
of varying sizes. Additional character array objects are appended to
|
||||
the sequence to accommodate changes in the size of the character
|
||||
sequence.
|
||||
|
||||
@note Meets the requirements of @b `Streambuf`.
|
||||
*/
|
||||
using streambuf = basic_streambuf<std::allocator<char>>;
|
||||
|
||||
} // beast
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
#define BEAST_STREAMBUF_READSTREAM_HPP
|
||||
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <beast/stream_concepts.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/detail/get_lowest_layer.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
@@ -20,11 +21,11 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A `Stream` with attached `Streambuf` to buffer reads.
|
||||
/** A @b `Stream` with attached @b `Streambuf` to buffer reads.
|
||||
|
||||
This wraps a `Stream` implementation so that calls to write are
|
||||
This wraps a @b `Stream` implementation so that calls to write are
|
||||
passed through to the underlying stream, while calls to read will
|
||||
first consume the input sequence stored in a `Streambuf` which
|
||||
first consume the input sequence stored in a @b `Streambuf` which
|
||||
is part of the object.
|
||||
|
||||
The use-case for this class is different than that of the
|
||||
@@ -37,10 +38,10 @@ namespace beast {
|
||||
|
||||
Uses:
|
||||
|
||||
* Transparently leave untouched input acquired in calls
|
||||
@li Transparently leave untouched input acquired in calls
|
||||
to `boost::asio::read_until` behind for subsequent callers.
|
||||
|
||||
* "Preload" a stream with handshake input data acquired
|
||||
@li "Preload" a stream with handshake input data acquired
|
||||
from other sources.
|
||||
|
||||
Example:
|
||||
@@ -88,6 +89,9 @@ namespace beast {
|
||||
template<class Stream, class Streambuf>
|
||||
class streambuf_readstream
|
||||
{
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
template<class Buffers, class Handler>
|
||||
@@ -107,8 +111,12 @@ public:
|
||||
|
||||
/// The type of the lowest layer.
|
||||
using lowest_layer_type =
|
||||
#if GENERATING_DOCS
|
||||
implementation_defined;
|
||||
#else
|
||||
typename detail::get_lowest_layer<
|
||||
next_layer_type>::type;
|
||||
#endif
|
||||
|
||||
/** Move constructor.
|
||||
|
||||
@@ -233,8 +241,11 @@ public:
|
||||
/// Start an asynchronous write. The data being written must be valid for the
|
||||
/// lifetime of the asynchronous operation.
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_write_some(ConstBufferSequence const& buffers,
|
||||
WriteHandler&& handler);
|
||||
|
||||
@@ -254,8 +265,11 @@ public:
|
||||
/// Start an asynchronous read. The buffer into which the data will be read
|
||||
/// must be valid for the lifetime of the asynchronous operation.
|
||||
template<class MutableBufferSequence, class ReadHandler>
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<ReadHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_read_some(MutableBufferSequence const& buffers,
|
||||
ReadHandler&& handler);
|
||||
};
|
||||
|
||||
@@ -8,24 +8,24 @@
|
||||
#ifndef BEAST_TO_STRING_HPP
|
||||
#define BEAST_TO_STRING_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Convert a `ConstBufferSequence` to a `std::string`.
|
||||
/** Convert a @b `ConstBufferSequence` to a `std::string`.
|
||||
|
||||
This function will convert the octets in a buffer sequence to a string.
|
||||
All octets will be inserted into the resulting string, including null
|
||||
or unprintable characters.
|
||||
|
||||
@param buffers The buffer sequence to convert.
|
||||
|
||||
@returns A string representing the contents of the input area.
|
||||
|
||||
@return A string representing the contents of the input area.
|
||||
|
||||
@note This function participates in overload resolution only if
|
||||
the streambuf parameter meets the requirements of Streambuf.
|
||||
the streambuf parameter meets the requirements of @b `Streambuf`.
|
||||
*/
|
||||
template<class ConstBufferSequence
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_TYPE_CHECK_HPP
|
||||
#define BEAST_TYPE_CHECK_HPP
|
||||
|
||||
#include <beast/detail/is_call_possible.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Types that meet the requirements,
|
||||
// for use with std::declval only.
|
||||
//
|
||||
|
||||
#if GENERATING_DOCS
|
||||
namespace detail {
|
||||
#else
|
||||
namespace concept {
|
||||
#endif
|
||||
|
||||
template<class BufferType>
|
||||
struct BufferSequence
|
||||
{
|
||||
using value_type = BufferType;
|
||||
using const_iterator = BufferType const*;
|
||||
~BufferSequence();
|
||||
BufferSequence(BufferSequence const&) = default;
|
||||
const_iterator
|
||||
begin() const noexcept;
|
||||
const_iterator
|
||||
end() const noexcept;
|
||||
};
|
||||
|
||||
using ConstBufferSequence =
|
||||
BufferSequence<boost::asio::const_buffer>;
|
||||
|
||||
using MutableBufferSequence =
|
||||
BufferSequence<boost::asio::mutable_buffer>;
|
||||
|
||||
struct StreamHandler
|
||||
{
|
||||
StreamHandler(StreamHandler const&) = default;
|
||||
void
|
||||
operator()(boost::system::error_code ec,
|
||||
std::size_t);
|
||||
};
|
||||
|
||||
using ReadHandler = StreamHandler;
|
||||
using WriteHandler = StreamHandler;
|
||||
|
||||
} // concept
|
||||
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html
|
||||
//
|
||||
/// Determine if `T` meets the requirements of `BufferSequence`.
|
||||
template<class T, class BufferType>
|
||||
class is_BufferSequence
|
||||
{
|
||||
template<class U, class R = std::is_convertible<
|
||||
typename U::value_type, BufferType> >
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_base_of<
|
||||
#if 0
|
||||
std::bidirectional_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#else
|
||||
// workaround:
|
||||
// boost::asio::detail::consuming_buffers::const_iterator
|
||||
// is not bidirectional
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<
|
||||
typename U::const_iterator>::iterator_category>>
|
||||
#endif
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
template<class U, class R = typename
|
||||
std::is_convertible<decltype(
|
||||
std::declval<U>().begin()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check3(int);
|
||||
template<class>
|
||||
static std::false_type check3(...);
|
||||
using type3 = decltype(check3<T>(0));
|
||||
|
||||
template<class U, class R = typename std::is_convertible<decltype(
|
||||
std::declval<U>().end()),
|
||||
typename U::const_iterator>::type>
|
||||
static R check4(int);
|
||||
template<class>
|
||||
static std::false_type check4(...);
|
||||
using type4 = decltype(check4<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
std::is_copy_constructible<T>::value &&
|
||||
std::is_destructible<T>::value &&
|
||||
type1::value && type2::value &&
|
||||
type3::value && type4::value;
|
||||
};
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
/// Determine if `T` meets the requirements of `ConstBufferSequence`.
|
||||
template<class T>
|
||||
using is_ConstBufferSequence =
|
||||
is_BufferSequence<T, boost::asio::const_buffer>;
|
||||
static_assert(is_ConstBufferSequence<concept::ConstBufferSequence>::value, "");
|
||||
static_assert(! is_ConstBufferSequence<int>::value, "");
|
||||
|
||||
/// Determine if `T` meets the requirements of `MutableBufferSequence`.
|
||||
template<class C>
|
||||
using is_MutableBufferSequence =
|
||||
is_BufferSequence<C, boost::asio::mutable_buffer>;
|
||||
static_assert(is_MutableBufferSequence<concept::MutableBufferSequence>::value, "");
|
||||
static_assert(! is_MutableBufferSequence<int>::value, "");
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Determine if `T` has the `get_io_service` member.
|
||||
template<class T>
|
||||
class has_get_io_service
|
||||
{
|
||||
template<class U, class R = typename std::is_same<
|
||||
decltype(std::declval<U>().get_io_service()),
|
||||
boost::asio::io_service&>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value = type::value;
|
||||
};
|
||||
static_assert(! has_get_io_service<int>::value, "");
|
||||
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html
|
||||
//
|
||||
/// Determine if `T` meets the requirements of `AsyncReadStream`.
|
||||
template<class T>
|
||||
class is_AsyncReadStream
|
||||
{
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().async_read_some(
|
||||
std::declval<concept::MutableBufferSequence>(),
|
||||
std::declval<concept::ReadHandler>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
has_get_io_service<T>::value && type::value;
|
||||
};
|
||||
static_assert(! is_AsyncReadStream<int>::value, "");
|
||||
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html
|
||||
//
|
||||
/// Determine if `T` meets the requirements of `AsyncWriteStream`.
|
||||
template<class T>
|
||||
class is_AsyncWriteStream
|
||||
{
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().async_write_some(
|
||||
std::declval<concept::ConstBufferSequence>(),
|
||||
std::declval<concept::WriteHandler>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
has_get_io_service<T>::value && type::value;
|
||||
};
|
||||
static_assert(! is_AsyncWriteStream<int>::value, "");
|
||||
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html
|
||||
//
|
||||
/// Determine if `T` meets the requirements of `SyncReadStream`.
|
||||
template<class T>
|
||||
class is_SyncReadStream
|
||||
{
|
||||
using error_code =
|
||||
boost::system::error_code;
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().read_some(
|
||||
std::declval<concept::MutableBufferSequence>())),
|
||||
std::size_t>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().read_some(
|
||||
std::declval<concept::MutableBufferSequence>(),
|
||||
std::declval<error_code&>())), std::size_t>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
type1::value && type2::value;
|
||||
};
|
||||
static_assert(! is_SyncReadStream<int>::value, "");
|
||||
|
||||
// http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html
|
||||
//
|
||||
/// Determine if `T` meets the requirements of `SyncWriterStream`.
|
||||
template<class T>
|
||||
class is_SyncWriteStream
|
||||
{
|
||||
using error_code =
|
||||
boost::system::error_code;
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().write_some(
|
||||
std::declval<concept::ConstBufferSequence>())),
|
||||
std::size_t>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().write_some(
|
||||
std::declval<concept::ConstBufferSequence>(),
|
||||
std::declval<error_code&>())), std::size_t>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
type1::value && type2::value;
|
||||
};
|
||||
static_assert(! is_SyncWriteStream<int>::value, "");
|
||||
|
||||
/// Determine if `T` meets the requirements of `SyncStream`.
|
||||
template<class T>
|
||||
struct is_SyncStream
|
||||
{
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
is_SyncReadStream<T>::value &&
|
||||
is_SyncWriteStream<T>::value;
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of `SyncStream`.
|
||||
template<class T>
|
||||
struct is_AsyncStream
|
||||
{
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
is_AsyncReadStream<T>::value &&
|
||||
is_AsyncWriteStream<T>::value;
|
||||
};
|
||||
|
||||
/// Determine if `T` meets the requirements of `Streambuf`.
|
||||
template<class T>
|
||||
class is_Streambuf
|
||||
{
|
||||
template<class U, class R = std::integral_constant<
|
||||
bool, is_MutableBufferSequence<decltype(
|
||||
std::declval<U>().prepare(1))>::value>>
|
||||
static R check1(int);
|
||||
template<class>
|
||||
static std::false_type check1(...);
|
||||
using type1 = decltype(check1<T>(0));
|
||||
|
||||
template<class U, class R = std::integral_constant<
|
||||
bool, is_ConstBufferSequence<decltype(
|
||||
std::declval<U>().data())>::value>>
|
||||
static R check2(int);
|
||||
template<class>
|
||||
static std::false_type check2(...);
|
||||
using type2 = decltype(check2<T>(0));
|
||||
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().commit(1), std::true_type{})>
|
||||
static R check3(int);
|
||||
template<class>
|
||||
static std::false_type check3(...);
|
||||
using type3 = decltype(check3<T>(0));
|
||||
|
||||
template<class U, class R = decltype(
|
||||
std::declval<U>().consume(1), std::true_type{})>
|
||||
static R check4(int);
|
||||
template<class>
|
||||
static std::false_type check4(...);
|
||||
using type4 = decltype(check4<T>(0));
|
||||
|
||||
template<class U, class R = std::is_same<decltype(
|
||||
std::declval<U>().size()), std::size_t>>
|
||||
static R check5(int);
|
||||
template<class>
|
||||
static std::false_type check5(...);
|
||||
using type5 = decltype(check5<T>(0));
|
||||
|
||||
public:
|
||||
/// `true` if `T` meets the requirements.
|
||||
static bool const value =
|
||||
type1::value && type2::value &&
|
||||
type3::value && type4::value &&
|
||||
type5::value;
|
||||
};
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
/// Determine if `T` meets the requirements of `CompletionHandler`.
|
||||
template<class T, class Signature>
|
||||
using is_Handler = std::integral_constant<bool,
|
||||
std::is_copy_constructible<typename std::decay<T>::type>::value &&
|
||||
detail::is_call_possible<T, Signature>::value>;
|
||||
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -17,10 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_WSPROTO_DEBUG_H_INCLUDED
|
||||
#define BEAST_WSPROTO_DEBUG_H_INCLUDED
|
||||
#ifndef BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||
#define BEAST_WEBSOCKET_DETAIL_DEBUG_HPP
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
@@ -82,7 +81,7 @@ format(std::string s)
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // wsproto
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "wsproto";
|
||||
return "websocket";
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
case error::request_invalid: return "upgrade request invalid";
|
||||
case error::request_denied: return "upgrade request denied";
|
||||
default:
|
||||
return "wsproto.error";
|
||||
return "websocket error";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BEAST_WEBSOCKET_ERROR_HPP
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
@@ -16,7 +17,7 @@ namespace websocket {
|
||||
/// The type of error used by functions and completion handlers.
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
/// Error values
|
||||
/// Error codes returned from @ref stream operations.
|
||||
enum class error
|
||||
{
|
||||
/// Both sides performed a WebSocket close
|
||||
@@ -50,8 +51,10 @@ enum class error
|
||||
request_denied
|
||||
};
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
error_code
|
||||
make_error_code(error e);
|
||||
#endif
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
@@ -396,7 +396,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
// teardown
|
||||
case 11:
|
||||
d.state = 12;
|
||||
wsproto_helpers::call_async_teardown(
|
||||
websocket_helpers::call_async_teardown(
|
||||
d.ws.next_layer(), std::move(*this));
|
||||
return;
|
||||
|
||||
@@ -482,7 +482,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
// teardown
|
||||
case 19:
|
||||
d.state = 20;
|
||||
wsproto_helpers::call_async_teardown(
|
||||
websocket_helpers::call_async_teardown(
|
||||
d.ws.next_layer(), std::move(*this));
|
||||
return;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define BEAST_WEBSOCKET_IMPL_SSL_IPP_INCLUDED
|
||||
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/handler_concepts.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
@@ -144,7 +144,7 @@ async_teardown(
|
||||
boost::asio::ssl::stream<AsyncStream>& stream,
|
||||
TeardownHandler&& handler)
|
||||
{
|
||||
static_assert(beast::is_Handler<
|
||||
static_assert(beast::is_CompletionHandler<
|
||||
TeardownHandler, void(error_code)>::value,
|
||||
"TeardownHandler requirements not met");
|
||||
detail::teardown_ssl_op<AsyncStream, typename std::decay<
|
||||
|
||||
@@ -18,16 +18,17 @@
|
||||
#include <beast/websocket/impl/response_op.ipp>
|
||||
#include <beast/websocket/impl/write_op.ipp>
|
||||
#include <beast/websocket/impl/write_frame_op.ipp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/consuming_buffers.hpp>
|
||||
#include <beast/prepare_buffers.hpp>
|
||||
#include <beast/static_streambuf.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
#include <beast/http/reason.hpp>
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <beast/consuming_buffers.hpp>
|
||||
#include <beast/prepare_buffers.hpp>
|
||||
#include <beast/static_streambuf.hpp>
|
||||
#include <beast/stream_concepts.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -613,7 +614,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
if(error_)
|
||||
return;
|
||||
}
|
||||
wsproto_helpers::call_teardown(next_layer(), ec);
|
||||
websocket_helpers::call_teardown(next_layer(), ec);
|
||||
error_ = ec != 0;
|
||||
if(error_)
|
||||
return;
|
||||
@@ -622,7 +623,7 @@ read_frame(frame_info& fi, Streambuf& streambuf, error_code& ec)
|
||||
return;
|
||||
}
|
||||
if(! ec)
|
||||
wsproto_helpers::call_teardown(next_layer(), ec);
|
||||
websocket_helpers::call_teardown(next_layer(), ec);
|
||||
if(! ec)
|
||||
ec = error::closed;
|
||||
error_ = ec != 0;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
|
||||
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/handler_concepts.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
@@ -157,7 +157,7 @@ async_teardown(
|
||||
boost::asio::ip::tcp::socket& socket,
|
||||
TeardownHandler&& handler)
|
||||
{
|
||||
static_assert(beast::is_Handler<
|
||||
static_assert(beast::is_CompletionHandler<
|
||||
TeardownHandler, void(error_code)>::value,
|
||||
"TeardownHandler requirements not met");
|
||||
detail::teardown_tcp_op<typename std::decay<
|
||||
|
||||
@@ -19,17 +19,17 @@ namespace websocket {
|
||||
|
||||
/** Automatic fragmentation size option.
|
||||
|
||||
Sets the maximum size of fragments generated when sending
|
||||
messages on a WebSocket socket.
|
||||
Sets the maximum size of fragments generated when sending messages
|
||||
on a WebSocket stream.
|
||||
|
||||
When the automatic fragmentation size is non-zero, messages
|
||||
exceeding the size will be split into multiple frames no
|
||||
larger than the size. This setting does not affect frames
|
||||
send explicitly using `write_frame` or `async_write_frame`.
|
||||
When the automatic fragmentation size is non-zero, messages exceeding
|
||||
the size will be split into multiple frames no larger than the size.
|
||||
This setting does not affect frames sent explicitly using
|
||||
@ref stream::write_frame or @ref stream::async_write_frame.
|
||||
|
||||
The default setting is to fragment messages into 16KB frames.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the automatic fragmentation size option:
|
||||
@@ -61,18 +61,20 @@ struct auto_fragment_size
|
||||
Server or User-Agent fields. The default setting applies no
|
||||
transformation to the HTTP message.
|
||||
|
||||
For synchronous operations, the implementation will call the
|
||||
decorator before the function call to perform the operation
|
||||
returns.
|
||||
The context in which the decorator is called depends on the
|
||||
type of operation performed:
|
||||
|
||||
For asynchronous operations, the implementation guarantees that
|
||||
calls to the decorator will be made from the same implicit or
|
||||
explicit strand used to call the asynchronous initiation
|
||||
@li For synchronous operations, the implementation will call the
|
||||
decorator before the operation unblocks.
|
||||
|
||||
@li For asynchronous operations, the implementation guarantees
|
||||
that calls to the decorator will be made from the same implicit
|
||||
or explicit strand used to call the asynchronous initiation
|
||||
function.
|
||||
|
||||
The default setting is no decorator.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the decorator.
|
||||
@@ -121,7 +123,7 @@ decorate(Decorator&& d)
|
||||
The default setting is to close connections after a failed
|
||||
upgrade request.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the keep alive option.
|
||||
@@ -155,7 +157,7 @@ struct keep_alive
|
||||
|
||||
The default setting is opcode::text.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the message type to binary.
|
||||
@@ -191,7 +193,7 @@ struct message_type
|
||||
|
||||
The default is no buffering.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the read buffer size.
|
||||
@@ -224,7 +226,7 @@ struct read_buffer_size
|
||||
|
||||
The default setting is 16 megabytes.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the maximum read message size.
|
||||
@@ -262,7 +264,7 @@ struct read_message_max
|
||||
|
||||
The default setting is 4096. The minimum value is 1024.
|
||||
|
||||
@note Objects of this type are passed to socket::set_option.
|
||||
@note Objects of this type are passed to @ref stream::set_option.
|
||||
|
||||
@par Example
|
||||
Setting the write buffer size.
|
||||
|
||||
@@ -41,19 +41,24 @@ enum class opcode : std::uint8_t
|
||||
|
||||
These codes accompany close frames.
|
||||
|
||||
@see RFC 6455 7.4.1 Defined Status Codes
|
||||
https://tools.ietf.org/html/rfc6455#section-7.4.1
|
||||
@see <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455 7.4.1 Defined Status Codes</a>
|
||||
|
||||
*/
|
||||
#if GENERATING_DOCS
|
||||
enum close_code
|
||||
#else
|
||||
namespace close_code {
|
||||
using value = std::uint16_t;
|
||||
enum
|
||||
#endif
|
||||
{
|
||||
// used internally to mean "no error"
|
||||
/// used internally to mean "no error"
|
||||
none = 0,
|
||||
|
||||
normal = 1000,
|
||||
going_away = 1001,
|
||||
protocol_error = 1002,
|
||||
|
||||
unknown_data = 1003,
|
||||
bad_payload = 1007,
|
||||
policy_error = 1008,
|
||||
@@ -71,17 +76,15 @@ enum
|
||||
|
||||
last = 5000 // satisfy warnings
|
||||
};
|
||||
#if ! GENERATING_DOCS
|
||||
} // close_code
|
||||
#endif
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
using reason_string_type =
|
||||
static_string<123, char>;
|
||||
|
||||
/// Payload type for pings and pongs
|
||||
using ping_payload_type =
|
||||
static_string<125, char>;
|
||||
|
||||
#endif
|
||||
|
||||
/** Description of the close reason.
|
||||
|
||||
@@ -25,14 +25,14 @@ namespace websocket {
|
||||
`boost::asio::ssl::stream`, callers are responsible for
|
||||
providing a suitable overload of this function.
|
||||
|
||||
@param socket The stream to tear down.
|
||||
@param stream The stream to tear down.
|
||||
|
||||
@param ec Set to the error if any occurred.
|
||||
*/
|
||||
template<class AsyncStream>
|
||||
template<class SyncStream>
|
||||
void
|
||||
teardown(
|
||||
boost::asio::ssl::stream<AsyncStream>& stream,
|
||||
boost::asio::ssl::stream<SyncStream>& stream,
|
||||
error_code& ec);
|
||||
|
||||
/** Start tearing down a `boost::asio::ssl::stream`.
|
||||
|
||||
+528
-243
File diff suppressed because it is too large
Load Diff
@@ -30,8 +30,8 @@ namespace websocket {
|
||||
/** Tear down a connection.
|
||||
|
||||
This tears down a connection. The implementation will call
|
||||
the overload of this function based on the `Stream` parameter
|
||||
used to consruct the socket. When `Stream` is a user defined
|
||||
the overload of this function based on the `Socket` parameter
|
||||
used to consruct the socket. When `Socket` is a user defined
|
||||
type, and not a `boost::asio::ip::tcp::socket` or any
|
||||
`boost::asio::ssl::stream`, callers are responsible for
|
||||
providing a suitable overload of this function.
|
||||
@@ -48,7 +48,7 @@ teardown(Socket& socket, error_code& ec) = delete;
|
||||
|
||||
This begins tearing down a connection asynchronously.
|
||||
The implementation will call the overload of this function
|
||||
based on the `Stream` parameter used to consruct the socket.
|
||||
based on the `Socket` parameter used to consruct the socket.
|
||||
When `Stream` is a user defined type, and not a
|
||||
`boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`,
|
||||
callers are responsible for providing a suitable overload
|
||||
@@ -68,9 +68,9 @@ teardown(Socket& socket, error_code& ec) = delete;
|
||||
manner equivalent to using boost::asio::io_service::post().
|
||||
|
||||
*/
|
||||
template<class AsyncSocket, class TeardownHandler>
|
||||
template<class Socket, class TeardownHandler>
|
||||
void
|
||||
async_teardown(AsyncSocket& socket, TeardownHandler&& handler) = delete;
|
||||
async_teardown(Socket& socket, TeardownHandler&& handler) = delete;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -126,11 +126,11 @@ async_teardown(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace wsproto_helpers {
|
||||
namespace websocket_helpers {
|
||||
|
||||
// Calls to teardown and async_teardown must be made from
|
||||
// a namespace that does not contain any overloads of these
|
||||
// functions. The wsproto_helpers namespace is defined here
|
||||
// functions. The websocket_helpers namespace is defined here
|
||||
// for that purpose.
|
||||
|
||||
template<class Socket>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef BEAST_WRITE_STREAMBUF_HPP
|
||||
#define BEAST_WRITE_STREAMBUF_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/buffer_concepts.hpp>
|
||||
#include <beast/detail/write_streambuf.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -21,15 +21,15 @@ namespace beast {
|
||||
argument into the stream buffer. It is capable of converting the
|
||||
following types of arguments:
|
||||
|
||||
@li `boost::asio::const_buffer`
|
||||
@li `boost::asio::const_buffer`
|
||||
|
||||
@li `boost::asio::mutable_buffer`
|
||||
|
||||
@li A type for which the call to `boost::asio::buffer()` is defined
|
||||
@li A type meeting the requirements of @b `ConvertibleToConstBuffer`
|
||||
|
||||
@li A type meeting the requirements of `ConstBufferSequence`
|
||||
@li A type meeting the requirements of @b `ConstBufferSequence`
|
||||
|
||||
@li A type meeting the requirements of `MutableBufferSequence`
|
||||
@li A type meeting the requirements of @b `MutableBufferSequence`
|
||||
|
||||
For all types not listed above, the function will invoke
|
||||
`boost::lexical_cast` on the argument in an attempt to convert to
|
||||
@@ -45,7 +45,7 @@ namespace beast {
|
||||
@throws unspecified Any exceptions thrown by `boost::lexical_cast`.
|
||||
|
||||
@note This function participates in overload resolution only if
|
||||
the `streambuf` parameter meets the requirements of Streambuf.
|
||||
the `streambuf` parameter meets the requirements of @b `Streambuf`.
|
||||
*/
|
||||
template<class Streambuf, class... Args>
|
||||
#if GENERATING_DOCS
|
||||
|
||||
Reference in New Issue
Block a user