mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge subtree Beast 1.0.0-b2:
Merge commit '6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99'
This commit is contained in:
@@ -16,13 +16,12 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Completion helper for implementing the extensible asynchronous model.
|
||||
/** 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 allows customization of
|
||||
the return type of the initiating function, and the type
|
||||
of the final handler.
|
||||
This class template is used to transform caller-provided completion
|
||||
tokens 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
|
||||
with specializations for customizing the return type (for example,
|
||||
@@ -30,14 +29,16 @@ namespace beast {
|
||||
|
||||
@tparam Signature The callable signature of the final completion handler.
|
||||
|
||||
Usage:
|
||||
Example:
|
||||
@code
|
||||
...
|
||||
template<class CompletionToken>
|
||||
typename async_completion<CompletionToken, Signature>::result_type
|
||||
typename async_completion<CompletionToken,
|
||||
void(boost::system::error_code)>::result_type
|
||||
async_initfn(..., CompletionToken&& token)
|
||||
{
|
||||
async_completion<CompletionToken, Signature> completion(token);
|
||||
async_completion<CompletionToken,
|
||||
void(boost::system::error_code)> completion(token);
|
||||
...
|
||||
return completion.result.get();
|
||||
}
|
||||
@@ -49,19 +50,19 @@ namespace beast {
|
||||
template <class CompletionToken, class Signature>
|
||||
struct async_completion
|
||||
{
|
||||
/** The type of the final handler.
|
||||
/** The type of the final handler called by the asynchronous initiation function.
|
||||
|
||||
Objects of this type will be callable with the
|
||||
specified signature.
|
||||
Objects of this type will be callable with the specified signature.
|
||||
*/
|
||||
using handler_type =
|
||||
typename boost::asio::handler_type<
|
||||
CompletionToken, Signature>::type;
|
||||
|
||||
/// The type of the value returned by the asynchronous initiation function.
|
||||
using result_type = typename
|
||||
boost::asio::async_result<handler_type>::type;
|
||||
|
||||
/** Construct the completion helper.
|
||||
/** Construct the helper.
|
||||
|
||||
@param token The completion token. Copies will be made as
|
||||
required. If `CompletionToken` is movable, it may also be moved.
|
||||
@@ -74,10 +75,10 @@ struct async_completion
|
||||
"Handler requirements not met");
|
||||
}
|
||||
|
||||
/** The final completion handler, callable with the specified signature. */
|
||||
/// The final completion handler, callable with the specified signature.
|
||||
handler_type handler;
|
||||
|
||||
/** The return value of the asynchronous initiation function. */
|
||||
/// The return value of the asynchronous initiation function.
|
||||
boost::asio::async_result<handler_type> result;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ class basic_streambuf
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/// The type of allocator used.
|
||||
using allocator_type = typename
|
||||
std::allocator_traits<Allocator>::
|
||||
template rebind_alloc<std::uint8_t>;
|
||||
@@ -73,10 +74,20 @@ private:
|
||||
size_type out_end_ = 0; // output end offset in list_.back()
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
|
||||
class mutable_buffers_type;
|
||||
|
||||
#endif
|
||||
|
||||
/// Destructor.
|
||||
~basic_streambuf();
|
||||
|
||||
@@ -175,7 +186,7 @@ public:
|
||||
template<class OtherAlloc>
|
||||
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const& other);
|
||||
|
||||
/** Construct a stream buffer.
|
||||
/** Default constructor.
|
||||
|
||||
@param alloc_size The size of buffer to allocate. This is a soft
|
||||
limit, calls to prepare for buffers exceeding this size will allocate
|
||||
@@ -258,60 +269,6 @@ private:
|
||||
debug_check() const;
|
||||
};
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::const_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_ = nullptr;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
const_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::mutable_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
mutable_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
/** Format output to a stream buffer.
|
||||
|
||||
@param streambuf The streambuf to write to.
|
||||
@@ -322,7 +279,7 @@ public:
|
||||
*/
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& buf, T const& t);
|
||||
operator<<(basic_streambuf<Alloc>& streambuf, T const& t);
|
||||
|
||||
/** Convert the entire basic_streambuf to a string.
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
|
||||
Example:
|
||||
@code
|
||||
template<class AsyncReadStream, ReadHandler>
|
||||
template<class AsyncReadStream, class ReadHandler>
|
||||
void
|
||||
do_cancel(AsyncReadStream& stream, ReadHandler&& handler)
|
||||
{
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
#define BEAST_BUFFERS_ADAPTER_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
@@ -70,19 +65,30 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
|
||||
class mutable_buffers_type;
|
||||
|
||||
// Move constructor.
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
buffers_adapter(buffers_adapter&& other);
|
||||
|
||||
// Copy constructor.
|
||||
/// Copy constructor.
|
||||
buffers_adapter(buffers_adapter const& other);
|
||||
|
||||
// Move assignment.
|
||||
/// Move assignment.
|
||||
buffers_adapter& operator=(buffers_adapter&& other);
|
||||
|
||||
// Copy assignment.
|
||||
/// Copy assignment.
|
||||
buffers_adapter& operator=(buffers_adapter const&);
|
||||
|
||||
/** Construct a buffers adapter.
|
||||
@@ -129,508 +135,8 @@ public:
|
||||
consume(std::size_t n);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
const_buffers_type(buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void const*>(*it_),
|
||||
(ba_->out_ == ba_->bs_.end() ||
|
||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->begin_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_ ==
|
||||
ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
mutable_buffers_type(
|
||||
buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void*>(*it_),
|
||||
it_ == std::prev(ba_->end_) ?
|
||||
ba_->out_end_ : buffer_size(*it_)} +
|
||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
, end_(bs_.begin())
|
||||
, max_size_(boost::asio::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::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())
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ != bs_.end())
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
if(n < size)
|
||||
{
|
||||
out_end_ = n;
|
||||
n = 0;
|
||||
++end_;
|
||||
break;
|
||||
}
|
||||
n -= size;
|
||||
out_end_ = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++end_;
|
||||
out_end_ = out_pos_ + n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
if(n > 0)
|
||||
throw std::length_error(
|
||||
"no space in buffers_adapter");
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::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_);
|
||||
while(out_ != last)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*out_) - out_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
return;
|
||||
}
|
||||
++out_;
|
||||
n -= avail;
|
||||
out_pos_ = 0;
|
||||
in_size_ += avail;
|
||||
max_size_ -= avail;
|
||||
}
|
||||
|
||||
n = std::min(n, out_end_ - out_pos_);
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
if(out_pos_ == buffer_size(*out_))
|
||||
{
|
||||
++out_;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(begin_ != out_)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*begin_) - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
in_size_ -= avail;
|
||||
in_pos_ = 0;
|
||||
++begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const avail = out_pos_ - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_size_ -= avail;
|
||||
if(out_pos_ != out_end_||
|
||||
out_ != std::prev(bs_.end()))
|
||||
{
|
||||
in_pos_ = out_pos_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the whole buffer now.
|
||||
in_pos_ = 0;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/buffers_adapter.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
namespace beast {
|
||||
namespace debug {
|
||||
|
||||
/** Diagnostic utility to convert a `ConstBufferSequence` to a string.
|
||||
|
||||
@note Carriage returns and linefeeds will have additional escape
|
||||
representations printed for visibility.
|
||||
*/
|
||||
template<class Buffers>
|
||||
std::string
|
||||
buffers_to_string(Buffers const& bs)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_CONSUMING_BUFFERS_HPP
|
||||
#define BEAST_CONSUMING_BUFFERS_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@@ -64,8 +63,15 @@ public:
|
||||
/// The type for each element in the list of buffers.
|
||||
using value_type = ValueType;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
using const_iterator = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_iterator;
|
||||
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
consuming_buffers(consuming_buffers&&);
|
||||
|
||||
@@ -104,194 +110,13 @@ public:
|
||||
consume(std::size_t n);
|
||||
};
|
||||
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
template<class Buffers, class ValueType>
|
||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
||||
{
|
||||
friend class consuming_buffers<Buffers, ValueType>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
consuming_buffers const* b_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->begin_)
|
||||
return *it_ + b_->skip_;
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(consuming_buffers const& b,
|
||||
iter_type it)
|
||||
: it_(it)
|
||||
, b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers&& other)
|
||||
: consuming_buffers(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers const& other)
|
||||
: consuming_buffers(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers&& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers const& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, begin_};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
void
|
||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||
{
|
||||
auto const len =
|
||||
buffer_size(*begin_) - skip_;
|
||||
if(n < len)
|
||||
{
|
||||
skip_ += n;
|
||||
break;
|
||||
}
|
||||
n -= len;
|
||||
skip_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a consumed buffer
|
||||
template<class Buffers>
|
||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
||||
{
|
||||
consuming_buffers<Buffers> cb(bs);
|
||||
cb.consume(n);
|
||||
return cb;
|
||||
}
|
||||
consumed_buffers(Buffers const& bs, std::size_t n);
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/consuming_buffers.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
146
src/beast/include/beast/detail/write_streambuf.hpp
Normal file
146
src/beast/include/beast/detail/write_streambuf.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// 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_WRITE_STREAMBUF_HPP
|
||||
#define BEAST_DETAIL_WRITE_STREAMBUF_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
// detects string literals.
|
||||
template<class T>
|
||||
struct is_string_literal : std::integral_constant<bool,
|
||||
! std::is_same<T, typename std::remove_extent<T>::type>::value &&
|
||||
std::is_same<char, typename std::remove_extent<T>::type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
// `true` if a call to boost::asio::buffer(T const&) is possible
|
||||
// note: we exclude string literals because boost::asio::buffer()
|
||||
// will include the null terminator, which we don't want.
|
||||
template<class T>
|
||||
class is_BufferConvertible
|
||||
{
|
||||
template<class U, class R = decltype(
|
||||
boost::asio::buffer(std::declval<U const&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template<class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<T>(0));
|
||||
public:
|
||||
static bool const value = type::value &&
|
||||
! is_string_literal<T>::value;
|
||||
};
|
||||
|
||||
template<class Streambuf>
|
||||
inline
|
||||
void
|
||||
write_streambuf(Streambuf&)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Streambuf>
|
||||
void
|
||||
write_streambuf(Streambuf& streambuf,
|
||||
boost::asio::const_buffer const& buffer)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(buffer_size(buffer)),
|
||||
buffer));
|
||||
}
|
||||
|
||||
template<class Streambuf>
|
||||
void
|
||||
write_streambuf(Streambuf& streambuf,
|
||||
boost::asio::mutable_buffer const& buffer)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(buffer_size(buffer)),
|
||||
buffer));
|
||||
}
|
||||
|
||||
template<class Streambuf, class T>
|
||||
typename std::enable_if<
|
||||
is_BufferConvertible<T>::value &&
|
||||
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
||||
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
||||
>::type
|
||||
write_streambuf(Streambuf& streambuf, T const& t)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
auto const buffers = boost::asio::buffer(t);
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(buffer_size(buffers)),
|
||||
buffers));
|
||||
}
|
||||
|
||||
template<class Streambuf, class Buffers>
|
||||
typename std::enable_if<
|
||||
is_ConstBufferSequence<Buffers>::value &&
|
||||
! is_BufferConvertible<Buffers>::value &&
|
||||
! std::is_convertible<Buffers, boost::asio::const_buffer>::value &&
|
||||
! std::is_convertible<Buffers, boost::asio::mutable_buffer>::value
|
||||
>::type
|
||||
write_streambuf(Streambuf& streambuf, Buffers const& buffers)
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(buffer_size(buffers)),
|
||||
buffers));
|
||||
}
|
||||
|
||||
template<class Streambuf, std::size_t N>
|
||||
void
|
||||
write_streambuf(Streambuf& streambuf, const char (&s)[N])
|
||||
{
|
||||
using boost::asio::buffer_copy;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(N - 1),
|
||||
boost::asio::buffer(s, N - 1)));
|
||||
}
|
||||
|
||||
template<class Streambuf, class T>
|
||||
typename std::enable_if<
|
||||
! is_string_literal<T>::value &&
|
||||
! is_ConstBufferSequence<T>::value &&
|
||||
! is_BufferConvertible<T>::value &&
|
||||
! std::is_convertible<T, boost::asio::const_buffer>::value &&
|
||||
! std::is_convertible<T, boost::asio::mutable_buffer>::value
|
||||
>::type
|
||||
write_streambuf(Streambuf& streambuf, T const& t)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
auto const s = boost::lexical_cast<std::string>(t);
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()), buffer(s)));
|
||||
}
|
||||
|
||||
template<class Streambuf, class T0, class T1, class... TN>
|
||||
void
|
||||
write_streambuf(Streambuf& streambuf, T0&& t0, T1&& t1, TN... tn)
|
||||
{
|
||||
write_streambuf(streambuf, std::forward<T0>(t0));
|
||||
write_streambuf(streambuf, std::forward<T1>(t1));
|
||||
write_streambuf(streambuf, std::forward<TN>(tn)...);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -22,12 +22,21 @@ namespace beast {
|
||||
/** An allocator that uses handler customizations.
|
||||
|
||||
This allocator uses the handler customizations `asio_handler_allocate`
|
||||
and `asio_handler_deallocate` to manage memory.
|
||||
and `asio_handler_deallocate` to manage memory. It meets the requirements
|
||||
of `Allocator` and can be used anywhere a `std::allocator` is
|
||||
accepted.
|
||||
|
||||
@tparam T The type of object
|
||||
@tparam T The type of objects allocated by the allocator.
|
||||
|
||||
@tparam Handler 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>
|
||||
class handler_alloc;
|
||||
#else
|
||||
template <class T, class Handler>
|
||||
class handler_alloc
|
||||
{
|
||||
@@ -132,6 +141,7 @@ public:
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/parse_error.hpp>
|
||||
#include <beast/http/parser.hpp>
|
||||
#include <beast/http/read.hpp>
|
||||
#include <beast/http/reason.hpp>
|
||||
@@ -22,7 +23,6 @@
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/http/streambuf_body.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/write.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
#define BEAST_HTTP_BASIC_HEADERS_HPP
|
||||
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/detail/ci_char_traits.hpp>
|
||||
#include <beast/detail/empty_base_optimization.hpp>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
203
src/beast/include/beast/http/detail/basic_parser.hpp
Normal file
203
src/beast/include/beast/http/detail/basic_parser.hpp
Normal file
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// 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_HTTP_DETAIL_BASIC_PARSER_HPP
|
||||
#define BEAST_HTTP_DETAIL_BASIC_PARSER_HPP
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
// '0'...'9'
|
||||
inline
|
||||
bool
|
||||
is_digit(char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
is_token(char c)
|
||||
{
|
||||
/* token = 1*<any CHAR except CTLs or separators>
|
||||
CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
sep = "(" | ")" | "<" | ">" | "@"
|
||||
| "," | ";" | ":" | "\" | <">
|
||||
| "/" | "[" | "]" | "?" | "="
|
||||
| "{" | "}" | SP | HT
|
||||
*/
|
||||
static std::array<char, 256> constexpr tab = {{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112
|
||||
}};
|
||||
return tab[static_cast<std::uint8_t>(c)] != 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
is_text(char c)
|
||||
{
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
static std::array<char, 256> constexpr tab = {{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 144
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 176
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 208
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 240
|
||||
}};
|
||||
return tab[static_cast<std::uint8_t>(c)] != 0;
|
||||
}
|
||||
|
||||
// converts to lower case,
|
||||
// returns 0 if not a valid token char
|
||||
//
|
||||
inline
|
||||
char
|
||||
to_field_char(char c)
|
||||
{
|
||||
/* token = 1*<any CHAR except CTLs or separators>
|
||||
CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
sep = "(" | ")" | "<" | ">" | "@"
|
||||
| "," | ";" | ":" | "\" | <">
|
||||
| "/" | "[" | "]" | "?" | "="
|
||||
| "{" | "}" | SP | HT
|
||||
*/
|
||||
static std::array<char, 256> constexpr tab = {{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, '!', 0, '#', '$', '%', '&', '\'', 0, 0, '*', '+', 0, '-', '.', 0,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
|
||||
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, '^', '_',
|
||||
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, '|', 0, '~', 0
|
||||
}};
|
||||
return tab[static_cast<std::uint8_t>(c)];
|
||||
}
|
||||
|
||||
// converts to lower case,
|
||||
// returns 0 if not a valid text char
|
||||
//
|
||||
inline
|
||||
char
|
||||
to_value_char(char c)
|
||||
{
|
||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
||||
static std::array<std::uint8_t, 256> constexpr tab = {{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, // 0
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 32
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 48
|
||||
64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 64
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, // 80
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 96
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0, // 112
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 128
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 144
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // 160
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // 176
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, // 192
|
||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, // 208
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 224
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // 240
|
||||
}};
|
||||
return static_cast<char>(tab[static_cast<std::uint8_t>(c)]);
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint8_t
|
||||
unhex(char c)
|
||||
{
|
||||
static std::array<std::int8_t, 256> constexpr tab = {{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 112
|
||||
}};
|
||||
return tab[static_cast<std::uint8_t>(c)];
|
||||
};
|
||||
|
||||
template<class = void>
|
||||
struct parser_str_t
|
||||
{
|
||||
static char constexpr close[6] = "close";
|
||||
static char constexpr chunked[8] = "chunked";
|
||||
static char constexpr keep_alive[11] = "keep-alive";
|
||||
|
||||
static char constexpr upgrade[8] = "upgrade";
|
||||
static char constexpr connection[11] = "connection";
|
||||
static char constexpr content_length[15] = "content-length";
|
||||
static char constexpr proxy_connection[17] = "proxy-connection";
|
||||
static char constexpr transfer_encoding[18] = "transfer-encoding";
|
||||
};
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::close[6];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::chunked[8];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::keep_alive[11];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::upgrade[8];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::connection[11];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::content_length[15];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::proxy_connection[17];
|
||||
|
||||
template<class _>
|
||||
char constexpr
|
||||
parser_str_t<_>::transfer_encoding[18];
|
||||
|
||||
using parser_str = parser_str_t<>;
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,71 +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_HTTP_DETAIL_ERROR_HPP
|
||||
#define BEAST_HTTP_DETAIL_ERROR_HPP
|
||||
|
||||
#include <beast/http/impl/http_parser.h>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
class message_category
|
||||
: public boost::system::error_category
|
||||
{
|
||||
public:
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "http error";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
return http_errno_description(
|
||||
static_cast<http_errno>(ev));
|
||||
}
|
||||
|
||||
boost::system::error_condition
|
||||
default_error_condition(int ev) const noexcept override
|
||||
{
|
||||
return boost::system::error_condition{ev, *this};
|
||||
}
|
||||
|
||||
bool
|
||||
equivalent(int ev,
|
||||
boost::system::error_condition const& condition
|
||||
) const noexcept override
|
||||
{
|
||||
return condition.value() == ev &&
|
||||
&condition.category() == this;
|
||||
}
|
||||
|
||||
bool
|
||||
equivalent(boost::system::error_code const& error,
|
||||
int ev) const noexcept override
|
||||
{
|
||||
return error.value() == ev &&
|
||||
&error.category() == this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class = void>
|
||||
boost::system::error_code
|
||||
make_error(int http_errno)
|
||||
{
|
||||
static message_category const mc{};
|
||||
return boost::system::error_code{http_errno, mc};
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
@@ -84,7 +85,7 @@ struct write_preparation
|
||||
|
||||
msg.write_firstline(sb);
|
||||
write_fields(sb, h);
|
||||
detail::write(sb, "\r\n");
|
||||
beast::write(sb, "\r\n");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,66 +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_HTTP_DETAIL_WRITES_HPP
|
||||
#define BEAST_HTTP_DETAIL_WRITES_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace detail {
|
||||
|
||||
template<class Streambuf, class T,
|
||||
class = typename std::enable_if<
|
||||
is_Streambuf<Streambuf>::value>::type>
|
||||
void
|
||||
write(Streambuf& streambuf, T&& t)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
auto const& s =
|
||||
boost::lexical_cast<std::string>(
|
||||
std::forward<T>(t));
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()), buffer(s)));
|
||||
}
|
||||
|
||||
template<class Streambuf, std::size_t N,
|
||||
class = typename std::enable_if< (N>0) &&
|
||||
is_Streambuf<Streambuf>::value>::type>
|
||||
void
|
||||
write(Streambuf& streambuf, char const(&s)[N])
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(N), buffer(s, N-1)));
|
||||
}
|
||||
|
||||
template<class Streambuf,
|
||||
class = typename std::enable_if<
|
||||
is_Streambuf<Streambuf>::value>::type>
|
||||
void
|
||||
write(Streambuf& streambuf, boost::string_ref const& s)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()),
|
||||
buffer(s.data(), s.size())));
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -22,9 +22,16 @@ namespace http {
|
||||
*/
|
||||
struct empty_body
|
||||
{
|
||||
struct value_type
|
||||
{
|
||||
};
|
||||
#if GENERATING_DOCS
|
||||
/// The type of the `message::body` member
|
||||
using value_type = void;
|
||||
#else
|
||||
struct value_type {};
|
||||
#endif
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
struct reader
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
|
||||
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,362 +0,0 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Also update SONAME in the Makefile whenever you change these. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 7
|
||||
#define HTTP_PARSER_VERSION_PATCH 0
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
||||
#include <BaseTsd.h>
|
||||
#include <stddef.h>
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
/* Maximium header size allowed. If the macro is not defined
|
||||
* before including this header then the default is used. To
|
||||
* change the maximum header size, define the macro in the build
|
||||
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
|
||||
* the effective limit on the size of the header, define the macro
|
||||
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
|
||||
*/
|
||||
#ifndef HTTP_MAX_HEADER_SIZE
|
||||
# define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||
#endif
|
||||
|
||||
typedef struct http_parser http_parser;
|
||||
typedef struct http_parser_settings http_parser_settings;
|
||||
|
||||
|
||||
/* Callbacks should return non-zero to indicate an error. The parser will
|
||||
* then halt execution.
|
||||
*
|
||||
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
|
||||
* returning '1' from on_headers_complete will tell the parser that it
|
||||
* should not expect a body. This is used when receiving a response to a
|
||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||
* chunked' headers that indicate the presence of a body.
|
||||
*
|
||||
* Returning `2` from on_headers_complete will tell parser that it should not
|
||||
* expect neither a body nor any futher responses on this connection. This is
|
||||
* useful for handling responses to a CONNECT request which may not contain
|
||||
* `Upgrade` or `Connection: upgrade` headers.
|
||||
*
|
||||
* http_data_cb does not return data chunks. It will be called arbitrarily
|
||||
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
||||
* each providing just a few characters more data.
|
||||
*/
|
||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
||||
typedef int (*http_cb) (http_parser*);
|
||||
|
||||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* WebDAV */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
/* subversion */ \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
/* CalDAV */ \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
/* RFC-2068, section 19.6.1.2 */ \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
#define XX(num, name, string) HTTP_##name = num,
|
||||
HTTP_METHOD_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||
|
||||
|
||||
/* Flag values for http_parser.flags field */
|
||||
enum flags
|
||||
{ F_CHUNKED = 1 << 0
|
||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||
, F_CONNECTION_CLOSE = 1 << 2
|
||||
, F_CONNECTION_UPGRADE = 1 << 3
|
||||
, F_TRAILING = 1 << 4
|
||||
, F_UPGRADE = 1 << 5
|
||||
, F_SKIPBODY = 1 << 6
|
||||
, F_CONTENTLENGTH = 1 << 7
|
||||
};
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
XX(CB_status, "the on_status callback failed") \
|
||||
XX(CB_chunk_header, "the on_chunk_header callback failed") \
|
||||
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(UNEXPECTED_CONTENT_LENGTH, \
|
||||
"unexpected content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||
enum http_errno {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
};
|
||||
#undef HTTP_ERRNO_GEN
|
||||
|
||||
|
||||
/* Get an http_errno value from an http_parser */
|
||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
||||
|
||||
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned int type : 2; /* enum http_parser_type */
|
||||
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned int state : 7; /* enum state from http_parser.c */
|
||||
unsigned int header_state : 7; /* enum header_state from http_parser.c */
|
||||
unsigned int index : 7; /* index into current matcher */
|
||||
unsigned int lenient_http_headers : 1;
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||
|
||||
/** READ-ONLY **/
|
||||
unsigned short http_major;
|
||||
unsigned short http_minor;
|
||||
unsigned int status_code : 16; /* responses only */
|
||||
unsigned int method : 8; /* requests only */
|
||||
unsigned int http_errno : 7;
|
||||
|
||||
/* 1 = Upgrade header was present and the parser has exited because of that.
|
||||
* 0 = No upgrade header present.
|
||||
* Should be checked when http_parser_execute() returns in addition to
|
||||
* error checking.
|
||||
*/
|
||||
unsigned int upgrade : 1;
|
||||
|
||||
/** PUBLIC **/
|
||||
void *data; /* A pointer to get hook to the "connection" or "socket" object */
|
||||
};
|
||||
|
||||
|
||||
struct http_parser_settings {
|
||||
http_cb on_message_begin;
|
||||
http_data_cb on_url;
|
||||
http_data_cb on_status;
|
||||
http_data_cb on_header_field;
|
||||
http_data_cb on_header_value;
|
||||
http_cb on_headers_complete;
|
||||
http_data_cb on_body;
|
||||
http_cb on_message_complete;
|
||||
/* When on_chunk_header is called, the current chunk length is stored
|
||||
* in parser->content_length.
|
||||
*/
|
||||
http_cb on_chunk_header;
|
||||
http_cb on_chunk_complete;
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_USERINFO = 6
|
||||
, UF_MAX = 7
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* Returns the library version. Bits 16-23 contain the major version number,
|
||||
* bits 8-15 the minor version number and bits 0-7 the patch level.
|
||||
* Usage example:
|
||||
*
|
||||
* unsigned long version = http_parser_version();
|
||||
* unsigned major = (version >> 16) & 255;
|
||||
* unsigned minor = (version >> 8) & 255;
|
||||
* unsigned patch = version & 255;
|
||||
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
|
||||
*/
|
||||
unsigned long http_parser_version(void);
|
||||
|
||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||
|
||||
|
||||
/* Initialize http_parser_settings members to 0
|
||||
*/
|
||||
void http_parser_settings_init(http_parser_settings *settings);
|
||||
|
||||
|
||||
/* Executes the parser. Returns number of parsed bytes. Sets
|
||||
* `parser->http_errno` on error. */
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
const http_parser_settings *settings,
|
||||
const char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* If http_should_keep_alive() in the on_headers_complete or
|
||||
* on_message_complete callback returns 0, then this should be
|
||||
* the last message on the connection.
|
||||
* If you are the server, respond with the "Connection: close" header.
|
||||
* If you are the client, close the connection.
|
||||
*/
|
||||
int http_should_keep_alive(const http_parser *parser);
|
||||
|
||||
/* Returns a string version of the HTTP method. */
|
||||
const char *http_method_str(enum http_method m);
|
||||
|
||||
/* Return a string name of the given error */
|
||||
const char *http_errno_name(enum http_errno err);
|
||||
|
||||
/* Return a string description of the given error */
|
||||
const char *http_errno_description(enum http_errno err);
|
||||
|
||||
/* Initialize all http_parser_url members to 0 */
|
||||
void http_parser_url_init(struct http_parser_url *u);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
/* Pause or un-pause the parser; a nonzero value pauses */
|
||||
void http_parser_pause(http_parser *parser, int paused);
|
||||
|
||||
/* Checks if this is the final chunk of the body. */
|
||||
int http_body_is_final(const http_parser *parser);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -9,11 +9,11 @@
|
||||
#define BEAST_HTTP_IMPL_MESSAGE_IPP
|
||||
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <condition_variable>
|
||||
@@ -26,16 +26,12 @@ template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message()
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(request_params params)
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(isRequest, "message is not a request");
|
||||
this->method = params.method;
|
||||
this->url = std::move(params.url);
|
||||
@@ -46,8 +42,6 @@ template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(response_params params)
|
||||
{
|
||||
static_assert(is_Body<Body>::value,
|
||||
"Body requirements not met");
|
||||
static_assert(! isRequest, "message is not a response");
|
||||
this->status = params.status;
|
||||
this->reason = std::move(params.reason);
|
||||
@@ -61,23 +55,23 @@ message<isRequest, Body, Headers>::
|
||||
write_firstline(Streambuf& streambuf,
|
||||
std::true_type) const
|
||||
{
|
||||
detail::write(streambuf, to_string(this->method));
|
||||
detail::write(streambuf, " ");
|
||||
detail::write(streambuf, this->url);
|
||||
write(streambuf, to_string(this->method));
|
||||
write(streambuf, " ");
|
||||
write(streambuf, this->url);
|
||||
switch(version)
|
||||
{
|
||||
case 10:
|
||||
detail::write(streambuf, " HTTP/1.0\r\n");
|
||||
write(streambuf, " HTTP/1.0\r\n");
|
||||
break;
|
||||
case 11:
|
||||
detail::write(streambuf, " HTTP/1.1\r\n");
|
||||
write(streambuf, " HTTP/1.1\r\n");
|
||||
break;
|
||||
default:
|
||||
detail::write(streambuf, " HTTP/");
|
||||
detail::write(streambuf, version / 10);
|
||||
detail::write(streambuf, ".");
|
||||
detail::write(streambuf, version % 10);
|
||||
detail::write(streambuf, "\r\n");
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, version % 10);
|
||||
write(streambuf, "\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -92,23 +86,23 @@ write_firstline(Streambuf& streambuf,
|
||||
switch(version)
|
||||
{
|
||||
case 10:
|
||||
detail::write(streambuf, "HTTP/1.0 ");
|
||||
write(streambuf, "HTTP/1.0 ");
|
||||
break;
|
||||
case 11:
|
||||
detail::write(streambuf, "HTTP/1.1 ");
|
||||
write(streambuf, "HTTP/1.1 ");
|
||||
break;
|
||||
default:
|
||||
detail::write(streambuf, " HTTP/");
|
||||
detail::write(streambuf, version / 10);
|
||||
detail::write(streambuf, ".");
|
||||
detail::write(streambuf, version % 10);
|
||||
detail::write(streambuf, " ");
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, version % 10);
|
||||
write(streambuf, " ");
|
||||
break;
|
||||
}
|
||||
detail::write(streambuf, this->status);
|
||||
detail::write(streambuf, " ");
|
||||
detail::write(streambuf, this->reason);
|
||||
detail::write(streambuf, "\r\n");
|
||||
write(streambuf, this->status);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, this->reason);
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -160,8 +154,6 @@ std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
error_code ec;
|
||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||
wp.init(ec);
|
||||
@@ -282,10 +274,10 @@ write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
||||
// "FieldSequence requirements not met");
|
||||
for(auto const& field : fields)
|
||||
{
|
||||
detail::write(streambuf, field.name());
|
||||
detail::write(streambuf, ": ");
|
||||
detail::write(streambuf, field.value());
|
||||
detail::write(streambuf, "\r\n");
|
||||
write(streambuf, field.name());
|
||||
write(streambuf, ": ");
|
||||
write(streambuf, field.value());
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <cassert>
|
||||
@@ -39,6 +38,7 @@ class read_op
|
||||
message_type& m;
|
||||
parser_type p;
|
||||
Handler h;
|
||||
bool started = false;
|
||||
bool cont;
|
||||
int state = 0;
|
||||
|
||||
@@ -130,6 +130,8 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
||||
bind_handler(std::move(*this), ec, 0));
|
||||
return;
|
||||
}
|
||||
if(used > 0)
|
||||
d.started = true;
|
||||
d.sb.consume(used);
|
||||
if(d.p.complete())
|
||||
{
|
||||
@@ -157,7 +159,7 @@ operator()(error_code ec, std::size_t bytes_transferred, bool again)
|
||||
{
|
||||
if(ec == boost::asio::error::eof)
|
||||
{
|
||||
if(! d.p.started())
|
||||
if(! d.started)
|
||||
{
|
||||
// call handler
|
||||
d.state = 99;
|
||||
@@ -219,9 +221,8 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
static_assert(is_ReadableBody<Body>::value,
|
||||
"ReadableBody requirements not met");
|
||||
parser<isRequest, Body, Headers> p;
|
||||
bool started = false;
|
||||
for(;;)
|
||||
{
|
||||
auto used =
|
||||
@@ -229,6 +230,8 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
if(ec)
|
||||
return;
|
||||
streambuf.consume(used);
|
||||
if(used > 0)
|
||||
started = true;
|
||||
if(p.complete())
|
||||
{
|
||||
m = p.release();
|
||||
@@ -241,7 +244,7 @@ read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
return;
|
||||
if(ec == boost::asio::error::eof)
|
||||
{
|
||||
if(! p.started())
|
||||
if(! started)
|
||||
return;
|
||||
// Caller will see eof on next read.
|
||||
ec = {};
|
||||
@@ -268,8 +271,6 @@ async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||
"AsyncReadStream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
static_assert(is_ReadableBody<Body>::value,
|
||||
"ReadableBody requirements not met");
|
||||
beast::async_completion<ReadHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::read_op<AsyncReadStream, Streambuf,
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
#include <beast/http/chunk_encode.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <beast/http/detail/writes.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
@@ -265,9 +263,9 @@ operator()(error_code ec, std::size_t, bool again)
|
||||
|
||||
case 4:
|
||||
// VFALCO Unfortunately the current interface to the
|
||||
// Writer concept prevents us from using coalescing the
|
||||
// Writer concept prevents us from coalescing the
|
||||
// final body chunk with the final chunk delimiter.
|
||||
//
|
||||
//
|
||||
// write final chunk
|
||||
d.state = 5;
|
||||
boost::asio::async_write(d.s,
|
||||
@@ -359,8 +357,6 @@ write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
detail::write_preparation<isRequest, Body, Headers> wp(msg);
|
||||
wp.init(ec);
|
||||
if(ec)
|
||||
@@ -447,8 +443,6 @@ async_write(AsyncWriteStream& stream,
|
||||
static_assert(
|
||||
is_AsyncWriteStream<AsyncWriteStream>::value,
|
||||
"AsyncWriteStream requirements not met");
|
||||
static_assert(is_WritableBody<Body>::value,
|
||||
"WritableBody requirements not met");
|
||||
beast::async_completion<WriteHandler,
|
||||
void(error_code)> completion(handler);
|
||||
detail::write_op<AsyncWriteStream, decltype(completion.handler),
|
||||
|
||||
@@ -35,6 +35,8 @@ struct response_fields
|
||||
|
||||
} // detail
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
struct request_params
|
||||
{
|
||||
http::method_t method;
|
||||
@@ -49,6 +51,8 @@ struct response_params
|
||||
int version;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** A HTTP message.
|
||||
|
||||
A message can be a request or response, depending on the `isRequest`
|
||||
@@ -110,7 +114,7 @@ struct message
|
||||
|
||||
/// Diagnostics only
|
||||
template<bool, class, class>
|
||||
friend
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message const& m);
|
||||
|
||||
157
src/beast/include/beast/http/parse_error.hpp
Normal file
157
src/beast/include/beast/http/parse_error.hpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// 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_HTTP_PARSE_ERROR_HPP
|
||||
#define BEAST_HTTP_PARSE_ERROR_HPP
|
||||
|
||||
#include <beast/http/error.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
enum class parse_error
|
||||
{
|
||||
connection_closed,
|
||||
|
||||
bad_method,
|
||||
bad_uri,
|
||||
bad_version,
|
||||
bad_crlf,
|
||||
bad_request,
|
||||
|
||||
bad_status_code,
|
||||
bad_status,
|
||||
|
||||
bad_field,
|
||||
bad_value,
|
||||
bad_content_length,
|
||||
illegal_content_length,
|
||||
bad_on_headers_rv,
|
||||
|
||||
invalid_chunk_size,
|
||||
|
||||
short_read
|
||||
};
|
||||
|
||||
class parse_error_category : public boost::system::error_category
|
||||
{
|
||||
public:
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "http";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
switch(static_cast<parse_error>(ev))
|
||||
{
|
||||
case parse_error::connection_closed:
|
||||
return "data after Connection close";
|
||||
|
||||
case parse_error::bad_method:
|
||||
return "bad method";
|
||||
|
||||
case parse_error::bad_uri:
|
||||
return "bad Request-URI";
|
||||
|
||||
case parse_error::bad_version:
|
||||
return "bad HTTP-Version";
|
||||
|
||||
case parse_error::bad_crlf:
|
||||
return "missing CRLF";
|
||||
|
||||
case parse_error::bad_request:
|
||||
return "bad Request-Line";
|
||||
|
||||
case parse_error::bad_status_code:
|
||||
return "bad Status-Code";
|
||||
|
||||
case parse_error::bad_status:
|
||||
return "bad Status-Line";
|
||||
|
||||
case parse_error::bad_field:
|
||||
return "bad field token";
|
||||
|
||||
case parse_error::bad_value:
|
||||
return "bad field-value";
|
||||
|
||||
case parse_error::bad_content_length:
|
||||
return "bad Content-Length";
|
||||
|
||||
case parse_error::illegal_content_length:
|
||||
return "illegal Content-Length with chunked Transfer-Encoding";
|
||||
|
||||
case parse_error::bad_on_headers_rv:
|
||||
return "on_headers returned an unknown value";
|
||||
|
||||
case parse_error::invalid_chunk_size:
|
||||
return "invalid chunk size";
|
||||
|
||||
case parse_error::short_read:
|
||||
return "unexpected end of data";
|
||||
|
||||
default:
|
||||
return "beast::http::parser error";
|
||||
}
|
||||
}
|
||||
|
||||
boost::system::error_condition
|
||||
default_error_condition(int ev) const noexcept override
|
||||
{
|
||||
return boost::system::error_condition(ev, *this);
|
||||
}
|
||||
|
||||
bool
|
||||
equivalent(int ev,
|
||||
boost::system::error_condition const& condition
|
||||
) const noexcept override
|
||||
{
|
||||
return condition.value() == ev &&
|
||||
&condition.category() == this;
|
||||
}
|
||||
|
||||
bool
|
||||
equivalent(error_code const& error, int ev) const noexcept override
|
||||
{
|
||||
return error.value() == ev &&
|
||||
&error.category() == this;
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
boost::system::error_category const&
|
||||
get_parse_error_category()
|
||||
{
|
||||
static parse_error_category const cat{};
|
||||
return cat;
|
||||
}
|
||||
|
||||
inline
|
||||
boost::system::error_code
|
||||
make_error_code(parse_error ev)
|
||||
{
|
||||
return error_code(static_cast<int>(ev),
|
||||
get_parse_error_category());
|
||||
}
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum<beast::http::parse_error>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -13,43 +13,51 @@
|
||||
#include <beast/http/message.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A HTTP parser.
|
||||
namespace detail {
|
||||
|
||||
struct parser_request
|
||||
{
|
||||
std::string method_;
|
||||
std::string uri_;
|
||||
};
|
||||
|
||||
struct parser_response
|
||||
{
|
||||
std::string reason_;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
The parser may only be used once.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
class parser
|
||||
: public basic_parser<parser<isRequest, Body, Headers>>
|
||||
: public basic_parser<isRequest,
|
||||
parser<isRequest, Body, Headers>>
|
||||
, private std::conditional<isRequest,
|
||||
detail::parser_request, detail::parser_response>::type
|
||||
{
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
|
||||
std::string field_;
|
||||
std::string value_;
|
||||
message_type m_;
|
||||
typename message_type::body_type::reader r_;
|
||||
bool started_ = false;
|
||||
|
||||
public:
|
||||
parser(parser&&) = default;
|
||||
|
||||
parser()
|
||||
: http::basic_parser<parser>(isRequest)
|
||||
, r_(m_)
|
||||
: r_(m_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns `true` if at least one byte has been processed
|
||||
bool
|
||||
started()
|
||||
{
|
||||
return started_;
|
||||
}
|
||||
|
||||
message_type
|
||||
release()
|
||||
{
|
||||
@@ -57,94 +65,165 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class http::basic_parser<parser>;
|
||||
friend class basic_parser<isRequest, parser>;
|
||||
|
||||
void
|
||||
on_start()
|
||||
void flush()
|
||||
{
|
||||
started_ = true;
|
||||
if(! value_.empty())
|
||||
{
|
||||
rfc2616::trim_right_in_place(value_);
|
||||
// VFALCO could std::move
|
||||
m_.headers.insert(field_, value_);
|
||||
field_.clear();
|
||||
value_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_field(std::string const& field, std::string const& value)
|
||||
void on_method(boost::string_ref const& s, error_code&)
|
||||
{
|
||||
m_.headers.insert(field, value);
|
||||
this->method_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
void
|
||||
on_headers_complete(error_code&)
|
||||
void on_uri(boost::string_ref const& s, error_code&)
|
||||
{
|
||||
// vFALCO TODO Decode the Content-Length and
|
||||
// Transfer-Encoding, see if we can reserve the buffer.
|
||||
//
|
||||
// r_.reserve(content_length)
|
||||
this->uri_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
void on_reason(boost::string_ref const& s, error_code&)
|
||||
{
|
||||
m_.method = method;
|
||||
m_.url = url;
|
||||
m_.version = major * 10 + minor;
|
||||
return true;
|
||||
this->reason_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t, std::string const&,
|
||||
int, int, bool, bool,
|
||||
std::false_type)
|
||||
void on_field(boost::string_ref const& s, error_code&)
|
||||
{
|
||||
return true;
|
||||
flush();
|
||||
field_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade)
|
||||
void on_value(boost::string_ref const& s, error_code&)
|
||||
{
|
||||
return on_request(method, url,
|
||||
major, minor, keep_alive, upgrade,
|
||||
typename message_type::is_request{});
|
||||
value_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int status, std::string const& reason,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
void set(std::true_type)
|
||||
{
|
||||
m_.status = status;
|
||||
m_.reason = reason;
|
||||
m_.version = major * 10 + minor;
|
||||
// VFALCO TODO return expect_body_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int, std::string const&, int, int, bool, bool,
|
||||
std::false_type)
|
||||
{
|
||||
return true;
|
||||
// VFALCO This is terrible for setting method
|
||||
auto m =
|
||||
[&](char const* s, method_t m)
|
||||
{
|
||||
if(this->method_ == s)
|
||||
{
|
||||
m_.method = m;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
do
|
||||
{
|
||||
if(m("DELETE", method_t::http_delete))
|
||||
break;
|
||||
if(m("GET", method_t::http_get))
|
||||
break;
|
||||
if(m("HEAD", method_t::http_head))
|
||||
break;
|
||||
if(m("POST", method_t::http_post))
|
||||
break;
|
||||
if(m("PUT", method_t::http_put))
|
||||
break;
|
||||
if(m("CONNECT", method_t::http_connect))
|
||||
break;
|
||||
if(m("OPTIONS", method_t::http_options))
|
||||
break;
|
||||
if(m("TRACE", method_t::http_trace))
|
||||
break;
|
||||
if(m("COPY", method_t::http_copy))
|
||||
break;
|
||||
if(m("LOCK", method_t::http_lock))
|
||||
break;
|
||||
if(m("MKCOL", method_t::http_mkcol))
|
||||
break;
|
||||
if(m("MOVE", method_t::http_move))
|
||||
break;
|
||||
if(m("PROPFIND", method_t::http_propfind))
|
||||
break;
|
||||
if(m("PROPPATCH", method_t::http_proppatch))
|
||||
break;
|
||||
if(m("SEARCH", method_t::http_search))
|
||||
break;
|
||||
if(m("UNLOCK", method_t::http_unlock))
|
||||
break;
|
||||
if(m("BIND", method_t::http_bind))
|
||||
break;
|
||||
if(m("REBID", method_t::http_rebind))
|
||||
break;
|
||||
if(m("UNBIND", method_t::http_unbind))
|
||||
break;
|
||||
if(m("ACL", method_t::http_acl))
|
||||
break;
|
||||
if(m("REPORT", method_t::http_report))
|
||||
break;
|
||||
if(m("MKACTIVITY", method_t::http_mkactivity))
|
||||
break;
|
||||
if(m("CHECKOUT", method_t::http_checkout))
|
||||
break;
|
||||
if(m("MERGE", method_t::http_merge))
|
||||
break;
|
||||
if(m("MSEARCH", method_t::http_msearch))
|
||||
break;
|
||||
if(m("NOTIFY", method_t::http_notify))
|
||||
break;
|
||||
if(m("SUBSCRIBE", method_t::http_subscribe))
|
||||
break;
|
||||
if(m("UNSUBSCRIBE",method_t::http_unsubscribe))
|
||||
break;
|
||||
if(m("PATCH", method_t::http_patch))
|
||||
break;
|
||||
if(m("PURGE", method_t::http_purge))
|
||||
break;
|
||||
if(m("MKCALENDAR", method_t::http_mkcalendar))
|
||||
break;
|
||||
if(m("LINK", method_t::http_link))
|
||||
break;
|
||||
if(m("UNLINK", method_t::http_unlink))
|
||||
break;
|
||||
}
|
||||
while(false);
|
||||
|
||||
m_.url = std::move(this->uri_);
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int status, std::string const& reason,
|
||||
int major, int minor, bool keep_alive, bool upgrade)
|
||||
void set(std::false_type)
|
||||
{
|
||||
return on_response(
|
||||
status, reason, major, minor, keep_alive, upgrade,
|
||||
std::integral_constant<bool, ! message_type::is_request::value>{});
|
||||
m_.status = this->status_code();
|
||||
m_.reason = this->reason_;
|
||||
}
|
||||
|
||||
void
|
||||
on_body(void const* data,
|
||||
std::size_t size, error_code& ec)
|
||||
int on_headers(error_code&)
|
||||
{
|
||||
r_.write(data, size, ec);
|
||||
flush();
|
||||
m_.version = 10 * this->http_major() + this->http_minor();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
on_complete()
|
||||
void on_request(error_code& ec)
|
||||
{
|
||||
set(std::integral_constant<
|
||||
bool, isRequest>{});
|
||||
}
|
||||
|
||||
void on_response(error_code& ec)
|
||||
{
|
||||
set(std::integral_constant<
|
||||
bool, isRequest>{});
|
||||
}
|
||||
|
||||
void on_body(boost::string_ref const& s, error_code& ec)
|
||||
{
|
||||
r_.write(s.data(), s.size(), ec);
|
||||
}
|
||||
|
||||
void on_complete(error_code&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <beast/async_completion.hpp>
|
||||
#include <beast/http/error.hpp>
|
||||
#include <beast/http/parser.hpp>
|
||||
#include <beast/http/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
/** Routines for performing RFC2616 compliance.
|
||||
RFC2616:
|
||||
Hypertext Transfer Protocol -- HTTP/1.1
|
||||
@@ -454,6 +456,8 @@ token_in_list(boost::string_ref const& value,
|
||||
|
||||
} // rfc2616
|
||||
|
||||
#endif
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
23
src/beast/include/beast/http/rfc7230.hpp
Normal file
23
src/beast/include/beast/http/rfc7230.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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_HTTP_RFC7230_HPP
|
||||
#define BEAST_HTTP_RFC7230_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
namespace rfc7230 {
|
||||
|
||||
|
||||
|
||||
} // rfc7230
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,13 @@ namespace http {
|
||||
template<class Streambuf>
|
||||
struct basic_streambuf_body
|
||||
{
|
||||
/// The type of the `message::body` member
|
||||
using value_type = Streambuf;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
class reader
|
||||
{
|
||||
value_type& sb_;
|
||||
|
||||
@@ -23,8 +23,13 @@ namespace http {
|
||||
*/
|
||||
struct string_body
|
||||
{
|
||||
/// The type of the `message::body` member
|
||||
using value_type = std::string;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
|
||||
class reader
|
||||
{
|
||||
value_type& s_;
|
||||
|
||||
@@ -1,49 +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_HTTP_TYPE_CHECK_HPP
|
||||
#define BEAST_HTTP_TYPE_CHECK_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/// Evaluates to std::true_type if `T` models Body
|
||||
template<class T>
|
||||
struct is_Body : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a reader
|
||||
template<class T>
|
||||
struct is_ReadableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a writer
|
||||
template<class T>
|
||||
struct is_WritableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `T` models HTTPMessage
|
||||
template<class T>
|
||||
struct is_HTTPMessage : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `HTTPMessage` is a request
|
||||
template<class HTTPMessage>
|
||||
struct is_HTTPRequest : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -115,6 +115,59 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::const_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_ = nullptr;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
const_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
/// Why?
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
class basic_streambuf<Allocator>::mutable_buffers_type
|
||||
{
|
||||
basic_streambuf const* sb_;
|
||||
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
mutable_buffers_type(basic_streambuf const& sb);
|
||||
|
||||
public:
|
||||
using value_type = mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Allocator>
|
||||
@@ -798,16 +851,16 @@ basic_streambuf<Allocator>::debug_check() const
|
||||
|
||||
template<class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<<(basic_streambuf<Alloc>& buf, T const& t)
|
||||
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();
|
||||
buf.commit(buffer_copy(buf.prepare(s.size()),
|
||||
boost::asio::buffer(s)));
|
||||
return buf;
|
||||
streambuf.commit(buffer_copy(
|
||||
streambuf.prepare(s.size()), buffer(s)));
|
||||
return streambuf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
520
src/beast/include/beast/impl/buffers_adapter.ipp
Normal file
520
src/beast/include/beast/impl/buffers_adapter.ipp
Normal file
@@ -0,0 +1,520 @@
|
||||
//
|
||||
// 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_IMPL_BUFFERS_ADAPTER_IPP
|
||||
#define BEAST_IMPL_BUFFERS_ADAPTER_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
const_buffers_type(buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::const_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void const*>(*it_),
|
||||
(ba_->out_ == ba_->bs_.end() ||
|
||||
it_ != ba_->out_) ? buffer_size(*it_) : ba_->out_pos_} +
|
||||
(it_ == ba_->begin_ ? ba_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->begin_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_ ==
|
||||
ba_->end_ ? ba_->end_ : std::next(ba_->out_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type
|
||||
{
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class buffers_adapter;
|
||||
|
||||
mutable_buffers_type(
|
||||
buffers_adapter const& ba)
|
||||
: ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
class buffers_adapter<Buffers>::mutable_buffers_type::const_iterator
|
||||
{
|
||||
iter_type it_;
|
||||
buffers_adapter const* ba_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return ba_ == other.ba_ &&
|
||||
it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
return value_type{buffer_cast<void*>(*it_),
|
||||
it_ == std::prev(ba_->end_) ?
|
||||
ba_->out_end_ : buffer_size(*it_)} +
|
||||
(it_ == ba_->out_ ? ba_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(buffers_adapter const& ba,
|
||||
iter_type iter)
|
||||
: it_(iter)
|
||||
, ba_(&ba)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->out_};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*ba_, ba_->end_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter&& other)
|
||||
: buffers_adapter(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
buffers_adapter const& other)
|
||||
: buffers_adapter(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.begin_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.out_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter&& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::operator=(
|
||||
buffers_adapter const& other) -> buffers_adapter&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
auto const nout = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.out_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
out_ = std::next(bs_.begin(), nout);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
max_size_ = other.max_size_;
|
||||
in_pos_ = other.in_pos_;
|
||||
in_size_ = other.in_size_;
|
||||
out_pos_ = other.out_pos_;
|
||||
out_end_ = other.out_end_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
buffers_adapter<Buffers>::buffers_adapter(
|
||||
Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
, out_(bs_.begin())
|
||||
, end_(bs_.begin())
|
||||
, max_size_(boost::asio::buffer_size(bs_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
auto
|
||||
buffers_adapter<Buffers>::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())
|
||||
{
|
||||
auto size = buffer_size(*end_) - out_pos_;
|
||||
if(n > size)
|
||||
{
|
||||
n -= size;
|
||||
while(++end_ != bs_.end())
|
||||
{
|
||||
size = buffer_size(*end_);
|
||||
if(n < size)
|
||||
{
|
||||
out_end_ = n;
|
||||
n = 0;
|
||||
++end_;
|
||||
break;
|
||||
}
|
||||
n -= size;
|
||||
out_end_ = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++end_;
|
||||
out_end_ = out_pos_ + n;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
if(n > 0)
|
||||
throw std::length_error(
|
||||
"no space in buffers_adapter");
|
||||
return mutable_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::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_);
|
||||
while(out_ != last)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*out_) - out_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
return;
|
||||
}
|
||||
++out_;
|
||||
n -= avail;
|
||||
out_pos_ = 0;
|
||||
in_size_ += avail;
|
||||
max_size_ -= avail;
|
||||
}
|
||||
|
||||
n = std::min(n, out_end_ - out_pos_);
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
max_size_ -= n;
|
||||
if(out_pos_ == buffer_size(*out_))
|
||||
{
|
||||
++out_;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
inline
|
||||
auto
|
||||
buffers_adapter<Buffers>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{*this};
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
void
|
||||
buffers_adapter<Buffers>::consume(std::size_t n)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(begin_ != out_)
|
||||
{
|
||||
auto const avail =
|
||||
buffer_size(*begin_) - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
in_size_ -= avail;
|
||||
in_pos_ = 0;
|
||||
++begin_;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const avail = out_pos_ - in_pos_;
|
||||
if(n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_size_ -= avail;
|
||||
if(out_pos_ != out_end_||
|
||||
out_ != std::prev(bs_.end()))
|
||||
{
|
||||
in_pos_ = out_pos_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the whole buffer now.
|
||||
in_pos_ = 0;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
211
src/beast/include/beast/impl/consuming_buffers.ipp
Normal file
211
src/beast/include/beast/impl/consuming_buffers.ipp
Normal file
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// 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_IMPL_CONSUMING_BUFFERS_IPP
|
||||
#define BEAST_IMPL_CONSUMING_BUFFERS_IPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
class consuming_buffers<Buffers, ValueType>::const_iterator
|
||||
{
|
||||
friend class consuming_buffers<Buffers, ValueType>;
|
||||
|
||||
using iter_type =
|
||||
typename Buffers::const_iterator;
|
||||
|
||||
iter_type it_;
|
||||
consuming_buffers const* b_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->begin_)
|
||||
return *it_ + b_->skip_;
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(consuming_buffers const& b,
|
||||
iter_type it)
|
||||
: it_(it)
|
||||
, b_(&b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers&& other)
|
||||
: consuming_buffers(std::move(other),
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(consuming_buffers const& other)
|
||||
: consuming_buffers(other,
|
||||
std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers&& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = std::move(other.bs_);
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
operator=(consuming_buffers const& other) ->
|
||||
consuming_buffers&
|
||||
{
|
||||
auto const nbegin = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.begin_);
|
||||
bs_ = other.bs_;
|
||||
begin_ = std::next(bs_.begin(), nbegin);
|
||||
skip_ = other.skip_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
consuming_buffers<Buffers, ValueType>::
|
||||
consuming_buffers(Buffers const& bs)
|
||||
: bs_(bs)
|
||||
, begin_(bs_.begin())
|
||||
{
|
||||
static_assert(is_BufferSequence<Buffers, ValueType>::value,
|
||||
"BufferSequence requirements not met");
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, begin_};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
auto
|
||||
consuming_buffers<Buffers, ValueType>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, bs_.end()};
|
||||
}
|
||||
|
||||
template<class Buffers, class ValueType>
|
||||
void
|
||||
consuming_buffers<Buffers, ValueType>::consume(std::size_t n)
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
for(;n > 0 && begin_ != bs_.end(); ++begin_)
|
||||
{
|
||||
auto const len =
|
||||
buffer_size(*begin_) - skip_;
|
||||
if(n < len)
|
||||
{
|
||||
skip_ += n;
|
||||
break;
|
||||
}
|
||||
n -= len;
|
||||
skip_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
consuming_buffers<Buffers, typename Buffers::value_type>
|
||||
consumed_buffers(Buffers const& bs, std::size_t n)
|
||||
{
|
||||
consuming_buffers<Buffers> cb(bs);
|
||||
cb.consume(n);
|
||||
return cb;
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
215
src/beast/include/beast/impl/prepare_buffers.ipp
Normal file
215
src/beast/include/beast/impl/prepare_buffers.ipp
Normal file
@@ -0,0 +1,215 @@
|
||||
//
|
||||
// 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_IMPL_PREPARE_BUFFERS_IPP
|
||||
#define BEAST_IMPL_PREPARE_BUFFERS_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class BufferSequence>
|
||||
void
|
||||
prepared_buffers<BufferSequence>::
|
||||
setup(std::size_t n)
|
||||
{
|
||||
for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
|
||||
{
|
||||
auto const len =
|
||||
boost::asio::buffer_size(*end_);
|
||||
if(n <= len)
|
||||
{
|
||||
size_ = n;
|
||||
back_ = end_++;
|
||||
return;
|
||||
}
|
||||
n -= len;
|
||||
}
|
||||
size_ = 0;
|
||||
back_ = end_;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
class prepared_buffers<BufferSequence>::const_iterator
|
||||
{
|
||||
friend class prepared_buffers<BufferSequence>;
|
||||
|
||||
using iter_type =
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
prepared_buffers const* b_;
|
||||
typename BufferSequence::const_iterator it_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->back_)
|
||||
return prepare_buffer(b_->size_, *it_);
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(prepared_buffers const& b,
|
||||
bool at_end)
|
||||
: b_(&b)
|
||||
, it_(at_end ? b.end_ : b.bs_.begin())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers&& other)
|
||||
: prepared_buffers(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers const& other)
|
||||
: prepared_buffers(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers&& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers const& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(std::size_t n, BufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
inline
|
||||
prepared_buffers<BufferSequence>
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers)
|
||||
{
|
||||
return prepared_buffers<BufferSequence>(n, buffers);
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
304
src/beast/include/beast/impl/static_streambuf.ipp
Normal file
304
src/beast/include/beast/impl/static_streambuf.ipp
Normal file
@@ -0,0 +1,304 @@
|
||||
//
|
||||
// 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_IMPL_STATIC_STREAMBUF_IPP
|
||||
#define BEAST_IMPL_STATIC_STREAMBUF_IPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class static_streambuf::const_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
const_buffers_type(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::const_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class static_streambuf::mutable_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
mutable_buffers_type(
|
||||
std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::mutable_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
if(n > static_cast<std::size_t>(end_ - out_))
|
||||
throw std::length_error("no space in streambuf");
|
||||
last_ = out_ + n;
|
||||
return mutable_buffers_type{out_, n};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{in_,
|
||||
static_cast<std::size_t>(out_ - in_)};
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -85,8 +85,15 @@ public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
using const_iterator = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_iterator;
|
||||
|
||||
#endif
|
||||
|
||||
/// Move constructor.
|
||||
prepared_buffers(prepared_buffers&&);
|
||||
|
||||
@@ -120,190 +127,9 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
setup(std::size_t n)
|
||||
{
|
||||
for(end_ = bs_.begin(); end_ != bs_.end(); ++end_)
|
||||
{
|
||||
auto const len =
|
||||
boost::asio::buffer_size(*end_);
|
||||
if(n <= len)
|
||||
{
|
||||
size_ = n;
|
||||
back_ = end_++;
|
||||
return;
|
||||
}
|
||||
n -= len;
|
||||
}
|
||||
size_ = 0;
|
||||
back_ = end_;
|
||||
}
|
||||
setup(std::size_t n);
|
||||
};
|
||||
|
||||
/// A bidirectional iterator type that may be used to read elements.
|
||||
template<class BufferSequence>
|
||||
class prepared_buffers<BufferSequence>::const_iterator
|
||||
{
|
||||
friend class prepared_buffers<BufferSequence>;
|
||||
|
||||
using iter_type =
|
||||
typename BufferSequence::const_iterator;
|
||||
|
||||
prepared_buffers const* b_;
|
||||
typename BufferSequence::const_iterator it_;
|
||||
|
||||
public:
|
||||
using value_type =
|
||||
typename std::iterator_traits<iter_type>::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return b_ == other.b_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
if(it_ == b_->back_)
|
||||
return prepare_buffer(b_->size_, *it_);
|
||||
return *it_;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
++it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
--it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
const_iterator(prepared_buffers const& b,
|
||||
bool at_end)
|
||||
: b_(&b)
|
||||
, it_(at_end ? b.end_ : b.bs_.begin())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers&& other)
|
||||
: prepared_buffers(std::move(other),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(prepared_buffers const& other)
|
||||
: prepared_buffers(other,
|
||||
std::distance<iter_type>(other.bs_.begin(), other.back_),
|
||||
std::distance<iter_type>(other.bs_.begin(), other.end_))
|
||||
{
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers&& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = std::move(other.bs_);
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::
|
||||
operator=(prepared_buffers const& other) ->
|
||||
prepared_buffers&
|
||||
{
|
||||
auto const nback = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.back_);
|
||||
auto const nend = std::distance<iter_type>(
|
||||
other.bs_.begin(), other.end_);
|
||||
bs_ = other.bs_;
|
||||
back_ = std::next(bs_.begin(), nback);
|
||||
end_ = std::next(bs_.begin(), nend);
|
||||
size_ = other.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
prepared_buffers<BufferSequence>::
|
||||
prepared_buffers(std::size_t n, BufferSequence const& bs)
|
||||
: bs_(bs)
|
||||
{
|
||||
setup(n);
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, false};
|
||||
}
|
||||
|
||||
template<class BufferSequence>
|
||||
auto
|
||||
prepared_buffers<BufferSequence>::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{*this, true};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Return a trimmed, wrapped buffer sequence.
|
||||
@@ -321,13 +147,11 @@ prepared_buffers<BufferSequence>::end() const ->
|
||||
will be made, but ownership of the underlying memory is not transferred.
|
||||
*/
|
||||
template<class BufferSequence>
|
||||
inline
|
||||
prepared_buffers<BufferSequence>
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers)
|
||||
{
|
||||
return prepared_buffers<BufferSequence>(n, buffers);
|
||||
}
|
||||
prepare_buffers(std::size_t n, BufferSequence const& buffers);
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/prepare_buffers.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
#ifndef BEAST_STATIC_STREAMBUF_HPP
|
||||
#define BEAST_STATIC_STREAMBUF_HPP
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -40,18 +38,23 @@ protected:
|
||||
std::uint8_t* end_;
|
||||
|
||||
public:
|
||||
#if GENERATING_DOCS
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
using const_buffers_type = implementation_defined;
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
using mutable_buffers_type = implementation_defined;
|
||||
|
||||
#else
|
||||
class const_buffers_type;
|
||||
class mutable_buffers_type;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
private:
|
||||
#endif
|
||||
static_streambuf(
|
||||
static_streambuf const& other) noexcept = delete;
|
||||
|
||||
static_streambuf& operator=(
|
||||
static_streambuf const&) noexcept = delete;
|
||||
#if GENERATING_DOCS
|
||||
public:
|
||||
|
||||
#endif
|
||||
|
||||
/// Returns the largest size output sequence possible.
|
||||
@@ -116,293 +119,6 @@ protected:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
class static_streambuf::const_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type(
|
||||
const_buffers_type const&) = default;
|
||||
const_buffers_type& operator=(
|
||||
const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
const_buffers_type(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::const_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t const* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class const_buffers_type;
|
||||
|
||||
const_iterator(
|
||||
std::uint8_t const* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::const_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
class static_streambuf::mutable_buffers_type
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type(
|
||||
mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator=(
|
||||
mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
private:
|
||||
friend class static_streambuf;
|
||||
|
||||
mutable_buffers_type(
|
||||
std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class static_streambuf::mutable_buffers_type::const_iterator
|
||||
{
|
||||
std::size_t n_;
|
||||
std::uint8_t* p_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::mutable_buffer;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator&& other) = default;
|
||||
const_iterator(const_iterator const& other) = default;
|
||||
const_iterator& operator=(const_iterator&& other) = default;
|
||||
const_iterator& operator=(const_iterator const& other) = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const
|
||||
{
|
||||
return p_ == other.p_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return value_type{p_, n_};
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const = delete;
|
||||
|
||||
const_iterator&
|
||||
operator++()
|
||||
{
|
||||
p_ += n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--()
|
||||
{
|
||||
p_ -= n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int)
|
||||
{
|
||||
auto temp = *this;
|
||||
--(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class mutable_buffers_type;
|
||||
|
||||
const_iterator(std::uint8_t* p, std::size_t n)
|
||||
: n_(n)
|
||||
, p_(p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::begin() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_, n_};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::mutable_buffers_type::end() const ->
|
||||
const_iterator
|
||||
{
|
||||
return const_iterator{p_ + n_, n_};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::prepare(std::size_t n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
if(n > static_cast<std::size_t>(end_ - out_))
|
||||
throw std::length_error("no space in streambuf");
|
||||
last_ = out_ + n;
|
||||
return mutable_buffers_type{out_, n};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
static_streambuf::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type{in_,
|
||||
static_cast<std::size_t>(out_ - in_)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A `Streambuf` with a fixed size internal buffer.
|
||||
|
||||
@tparam N The number of bytes in the internal buffer.
|
||||
@@ -456,4 +172,6 @@ public:
|
||||
|
||||
} // beast
|
||||
|
||||
#include <beast/impl/static_streambuf.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
21
src/beast/include/beast/version.hpp
Normal file
21
src/beast/include/beast/version.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// 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_VERSION_HPP
|
||||
#define BEAST_VERSION_HPP
|
||||
|
||||
// follows http://semver.org
|
||||
|
||||
// BEAST_VERSION % 100 is the patch level
|
||||
// BEAST_VERSION / 100 % 1000 is the minor version
|
||||
// BEAST_VERSION / 100000 is the major version
|
||||
//
|
||||
#define BEAST_VERSION 100000
|
||||
|
||||
#define BEAST_VERSION_STRING "1.0.0-b2"
|
||||
|
||||
#endif
|
||||
60
src/beast/include/beast/websocket/detail/endian.hpp
Normal file
60
src/beast/include/beast/websocket/detail/endian.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// 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_WEBSOCKET_DETAIL_ENDIAN_HPP
|
||||
#define BEAST_WEBSOCKET_DETAIL_ENDIAN_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
std::uint16_t
|
||||
big_uint16_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return (p[0]<<8) + p[1];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
big_uint64_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
(static_cast<std::uint64_t>(p[0])<<56) +
|
||||
(static_cast<std::uint64_t>(p[1])<<48) +
|
||||
(static_cast<std::uint64_t>(p[2])<<40) +
|
||||
(static_cast<std::uint64_t>(p[3])<<32) +
|
||||
(static_cast<std::uint64_t>(p[4])<<24) +
|
||||
(static_cast<std::uint64_t>(p[5])<<16) +
|
||||
(static_cast<std::uint64_t>(p[6])<< 8) +
|
||||
p[7];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint32_t
|
||||
little_uint32_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
p[0] +
|
||||
(static_cast<std::uint64_t>(p[1])<< 8) +
|
||||
(static_cast<std::uint64_t>(p[2])<<16) +
|
||||
(static_cast<std::uint64_t>(p[3])<<24);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <beast/websocket/rfc6455.hpp>
|
||||
#include <beast/websocket/static_string.hpp>
|
||||
#include <beast/websocket/detail/endian.hpp>
|
||||
#include <beast/websocket/detail/utf8_checker.hpp>
|
||||
#include <beast/consuming_buffers.hpp>
|
||||
#include <beast/static_streambuf.hpp>
|
||||
@@ -244,8 +245,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[2];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.len = reinterpret_cast<
|
||||
big_uint16_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.len = big_uint16_to_native(&b[0]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 126)
|
||||
{
|
||||
@@ -259,8 +265,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[8];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.len = reinterpret_cast<
|
||||
big_uint64_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.len = big_uint64_to_native(&b[0]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 65536)
|
||||
{
|
||||
@@ -275,8 +286,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[4];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.key = reinterpret_cast<
|
||||
little_uint32_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.key = little_uint32_to_native(&b[0]);
|
||||
#endif
|
||||
}
|
||||
code = close_code::none;
|
||||
}
|
||||
@@ -327,9 +343,15 @@ read(close_reason& cr,
|
||||
{
|
||||
std::uint8_t b[2];
|
||||
buffer_copy(buffer(b), cb);
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
cr.code = static_cast<close_code>(
|
||||
reinterpret_cast<
|
||||
big_uint16_buf_t const*>(&b[0])->value());
|
||||
#else
|
||||
cr.code = static_cast<close_code>(
|
||||
big_uint16_to_native(&b[0]));
|
||||
#endif
|
||||
cb.consume(2);
|
||||
n -= 2;
|
||||
if(! is_valid(cr.code))
|
||||
|
||||
@@ -68,10 +68,9 @@ class invokable
|
||||
void operator()(){}
|
||||
};
|
||||
|
||||
using buf_type = std::uint8_t[
|
||||
sizeof(holder<exemplar>)];
|
||||
using buf_type = char[sizeof(holder<exemplar>)];
|
||||
|
||||
bool b_ = false;
|
||||
base* base_ = nullptr;
|
||||
alignas(holder<exemplar>) buf_type buf_;
|
||||
|
||||
public:
|
||||
@@ -81,7 +80,7 @@ public:
|
||||
// Engaged invokables must be invoked before
|
||||
// destruction otherwise the io_service
|
||||
// invariants are broken w.r.t completions.
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -90,12 +89,12 @@ public:
|
||||
invokable& operator=(invokable const&) = delete;
|
||||
|
||||
invokable(invokable&& other)
|
||||
: b_(other.b_)
|
||||
{
|
||||
if(other.b_)
|
||||
if(other.base_)
|
||||
{
|
||||
other.get().move(buf_);
|
||||
other.b_ = false;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
other.base_->move(buf_);
|
||||
other.base_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,13 +104,13 @@ public:
|
||||
// Engaged invokables must be invoked before
|
||||
// assignment otherwise the io_service
|
||||
// invariants are broken w.r.t completions.
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
|
||||
if(other.b_)
|
||||
if(other.base_)
|
||||
{
|
||||
b_ = true;
|
||||
other.get().move(buf_);
|
||||
other.b_ = false;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
other.base_->move(buf_);
|
||||
other.base_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -123,19 +122,13 @@ public:
|
||||
void
|
||||
maybe_invoke()
|
||||
{
|
||||
if(b_)
|
||||
if(base_)
|
||||
{
|
||||
b_ = false;
|
||||
get()();
|
||||
auto const basep = base_;
|
||||
base_ = nullptr;
|
||||
(*basep)();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base&
|
||||
get()
|
||||
{
|
||||
return *reinterpret_cast<base*>(&buf_[0]);
|
||||
}
|
||||
};
|
||||
|
||||
template<class F>
|
||||
@@ -144,9 +137,9 @@ invokable::emplace(F&& f)
|
||||
{
|
||||
static_assert(sizeof(buf_type) >= sizeof(holder<F>),
|
||||
"buffer too small");
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
::new(buf_) holder<F>(std::forward<F>(f));
|
||||
b_ = true;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
|
||||
/// The type of error used by functions and completion handlers.
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
/// Error values
|
||||
|
||||
63
src/beast/include/beast/write_streambuf.hpp
Normal file
63
src/beast/include/beast/write_streambuf.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// 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_WRITE_STREAMBUF_HPP
|
||||
#define BEAST_WRITE_STREAMBUF_HPP
|
||||
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/detail/write_streambuf.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Write to a Streambuf.
|
||||
|
||||
This function appends the serialized representation of each provided
|
||||
argument into the stream buffer. It is capable of converting the
|
||||
following types of arguments:
|
||||
|
||||
@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 `ConstBufferSequence`
|
||||
|
||||
@li A type meeting the requirements of `MutableBufferSequence`
|
||||
|
||||
For all types not listed above, the function will invoke
|
||||
`boost::lexical_cast` on the argument in an attempt to convert to
|
||||
a string, which is then appended to the stream buffer.
|
||||
|
||||
When this function serializes numbers, it converts them to
|
||||
their text representation as if by a call to `std::to_string`.
|
||||
|
||||
@param streambuf The stream buffer to write to.
|
||||
|
||||
@param args A list of one or more arguments to write.
|
||||
|
||||
@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.
|
||||
*/
|
||||
template<class Streambuf, class... Args>
|
||||
#if GENERATING_DOCS
|
||||
void
|
||||
#else
|
||||
typename std::enable_if<is_Streambuf<Streambuf>::value>::type
|
||||
#endif
|
||||
write(Streambuf& streambuf, Args&&... args)
|
||||
{
|
||||
detail::write_streambuf(streambuf, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user