mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Dynamic buffers improvements:
fix #1305 Applies to: flat_buffer flat_static_buffer multi_buffer static_buffer Changes: * Revised all javadocs * Move construction does not invalidate in some cases * non-const data() returns a mutable buffer sequence * Add cdata() to also return constant readable bytes * Eligible member functions are declared noexcept
This commit is contained in:
@ -4,6 +4,7 @@ Version 194:
|
|||||||
* Add net namespace alias
|
* Add net namespace alias
|
||||||
* Don't use-after-free in test
|
* Don't use-after-free in test
|
||||||
* Tidy up ssl_stream (experimental)
|
* Tidy up ssl_stream (experimental)
|
||||||
|
* Dynamic buffer improvements
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -20,18 +20,30 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A linear dynamic buffer.
|
/** A dynamic buffer providing buffer sequences of length one.
|
||||||
|
|
||||||
|
A dynamic buffer encapsulates memory storage that may be
|
||||||
|
automatically resized as required, where the memory is
|
||||||
|
divided into two regions: readable bytes followed by
|
||||||
|
writable bytes. These memory regions are internal to
|
||||||
|
the dynamic buffer, but direct access to the elements
|
||||||
|
is provided to permit them to be efficiently used with
|
||||||
|
I/O operations.
|
||||||
|
|
||||||
Objects of this type meet the requirements of @b DynamicBuffer
|
Objects of this type meet the requirements of @b DynamicBuffer
|
||||||
and offer additional invariants:
|
and have the following additional properties:
|
||||||
|
|
||||||
@li Buffer sequences returned by @ref data and @ref prepare
|
@li A mutable buffer sequence representing the readable
|
||||||
will always be of length one.
|
bytes is returned by @ref data when `this` is non-const.
|
||||||
|
|
||||||
@li A configurable maximum buffer size may be set upon
|
@li A configurable maximum buffer size may be set upon
|
||||||
construction. Attempts to exceed the buffer size will throw
|
construction. Attempts to exceed the buffer size will throw
|
||||||
`std::length_error`.
|
`std::length_error`.
|
||||||
|
|
||||||
|
@li Buffer sequences representing the readable and writable
|
||||||
|
bytes, returned by @ref data and @ref prepare, will have
|
||||||
|
length one.
|
||||||
|
|
||||||
Upon construction, a maximum size for the buffer may be
|
Upon construction, a maximum size for the buffer may be
|
||||||
specified. If this limit is exceeded, the `std::length_error`
|
specified. If this limit is exceeded, the `std::length_error`
|
||||||
exception will be thrown.
|
exception will be thrown.
|
||||||
@ -65,7 +77,6 @@ class basic_flat_buffer
|
|||||||
detail::allocator_traits<base_alloc_type>;
|
detail::allocator_traits<base_alloc_type>;
|
||||||
|
|
||||||
static
|
static
|
||||||
inline
|
|
||||||
std::size_t
|
std::size_t
|
||||||
dist(char const* first, char const* last)
|
dist(char const* first, char const* last)
|
||||||
{
|
{
|
||||||
@ -83,24 +94,18 @@ public:
|
|||||||
/// The type of allocator used.
|
/// The type of allocator used.
|
||||||
using allocator_type = Allocator;
|
using allocator_type = Allocator;
|
||||||
|
|
||||||
/// The type used to represent the input sequence as a list of buffers.
|
|
||||||
using const_buffers_type = boost::asio::const_buffer;
|
|
||||||
|
|
||||||
/// The type used to represent the output sequence as a list of buffers.
|
|
||||||
using mutable_buffers_type = boost::asio::mutable_buffer;
|
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~basic_flat_buffer();
|
~basic_flat_buffer();
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
Upon construction, capacity will be zero.
|
Upon construction, @ref capacity will return zero.
|
||||||
*/
|
*/
|
||||||
basic_flat_buffer();
|
basic_flat_buffer();
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
Upon construction, capacity will be zero.
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param limit The setting for @ref max_size.
|
@param limit The setting for @ref max_size.
|
||||||
*/
|
*/
|
||||||
@ -109,7 +114,7 @@ public:
|
|||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
Upon construction, capacity will be zero.
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param alloc The allocator to construct with.
|
@param alloc The allocator to construct with.
|
||||||
*/
|
*/
|
||||||
@ -118,7 +123,7 @@ public:
|
|||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
Upon construction, capacity will be zero.
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param limit The setting for @ref max_size.
|
@param limit The setting for @ref max_size.
|
||||||
|
|
||||||
@ -127,36 +132,55 @@ public:
|
|||||||
basic_flat_buffer(
|
basic_flat_buffer(
|
||||||
std::size_t limit, Allocator const& alloc);
|
std::size_t limit, Allocator const& alloc);
|
||||||
|
|
||||||
/** Constructor
|
/** Move Constructor
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Constructs the container with the contents of other
|
||||||
|
using move semantics. After the move, other is
|
||||||
|
guaranteed to be empty.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data
|
||||||
|
or @ref prepare are not invalidated after the move.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
The object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
*/
|
*/
|
||||||
basic_flat_buffer(basic_flat_buffer&& other);
|
basic_flat_buffer(basic_flat_buffer&& other);
|
||||||
|
|
||||||
/** Constructor
|
/** Move Constructor
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Using alloc as the allocator for the new container, the
|
||||||
|
contents of other are moved. If `alloc != other.get_allocator()`,
|
||||||
|
this results in a copy. After the move, other is
|
||||||
|
guaranteed to be empty.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
The object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
|
|
||||||
@param alloc The allocator to use.
|
@param alloc The allocator to use for the newly
|
||||||
|
constructed object.
|
||||||
*/
|
*/
|
||||||
basic_flat_buffer(
|
basic_flat_buffer(
|
||||||
basic_flat_buffer&& other, Allocator const& alloc);
|
basic_flat_buffer&& other, Allocator const& alloc);
|
||||||
|
|
||||||
/** Constructor
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
allocator and contents of other, and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
basic_flat_buffer(basic_flat_buffer const& other);
|
basic_flat_buffer(basic_flat_buffer const& other);
|
||||||
|
|
||||||
/** Constructor
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
specified allocator, a copy of the contents of other,
|
||||||
|
and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
|
|
||||||
@ -165,7 +189,10 @@ public:
|
|||||||
basic_flat_buffer(basic_flat_buffer const& other,
|
basic_flat_buffer(basic_flat_buffer const& other,
|
||||||
Allocator const& alloc);
|
Allocator const& alloc);
|
||||||
|
|
||||||
/** Constructor
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
contents of other, and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -173,7 +200,11 @@ public:
|
|||||||
basic_flat_buffer(
|
basic_flat_buffer(
|
||||||
basic_flat_buffer<OtherAlloc> const& other);
|
basic_flat_buffer<OtherAlloc> const& other);
|
||||||
|
|
||||||
/** Constructor
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
specified allocator, a copy of the contents of other,
|
||||||
|
and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
|
|
||||||
@ -184,20 +215,28 @@ public:
|
|||||||
basic_flat_buffer<OtherAlloc> const& other,
|
basic_flat_buffer<OtherAlloc> const& other,
|
||||||
Allocator const& alloc);
|
Allocator const& alloc);
|
||||||
|
|
||||||
/** Assignment
|
/** Move Assignment
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Assigns the container with the contents of other
|
||||||
|
using move semantics. After the move, other is
|
||||||
|
guaranteed to be empty. The previous contents of
|
||||||
|
this container are deleted.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data
|
||||||
|
or @ref prepare are not invalidated after the move.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
the object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
*/
|
*/
|
||||||
basic_flat_buffer&
|
basic_flat_buffer&
|
||||||
operator=(basic_flat_buffer&& other);
|
operator=(basic_flat_buffer&& other);
|
||||||
|
|
||||||
/** Assignment
|
/** Copy Assignment
|
||||||
|
|
||||||
After the copy, `*this` will have an empty output sequence.
|
The assigned object will have a copy of the allocator
|
||||||
|
and contents of other, and zero writable bytes. The
|
||||||
|
previous contents of this container are deleted.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -206,7 +245,9 @@ public:
|
|||||||
|
|
||||||
/** Copy assignment
|
/** Copy assignment
|
||||||
|
|
||||||
After the copy, `*this` will have an empty output sequence.
|
The assigned object will have a copy of the contents
|
||||||
|
of other, and zero writable bytes. The previous contents
|
||||||
|
of this container are deleted.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -214,123 +255,149 @@ public:
|
|||||||
basic_flat_buffer&
|
basic_flat_buffer&
|
||||||
operator=(basic_flat_buffer<OtherAlloc> const& other);
|
operator=(basic_flat_buffer<OtherAlloc> const& other);
|
||||||
|
|
||||||
/// Returns a copy of the associated allocator.
|
/// Returns a copy of the allocator used.
|
||||||
allocator_type
|
allocator_type
|
||||||
get_allocator() const
|
get_allocator() const
|
||||||
{
|
{
|
||||||
return this->get();
|
return this->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size of the input sequence.
|
/** Reallocate the buffer to fit the readable bytes exactly.
|
||||||
std::size_t
|
|
||||||
size() const
|
|
||||||
{
|
|
||||||
return dist(in_, out_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the maximum sum of the input and output sequence sizes.
|
All buffers sequences previously obtained using
|
||||||
std::size_t
|
@ref data or @ref prepare are invalidated.
|
||||||
max_size() const
|
|
||||||
{
|
|
||||||
return max_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the maximum sum of input and output sizes that can be held without an allocation.
|
|
||||||
std::size_t
|
|
||||||
capacity() const
|
|
||||||
{
|
|
||||||
return dist(begin_, end_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a list of buffers that represent the input sequence.
|
|
||||||
const_buffers_type
|
|
||||||
data() const
|
|
||||||
{
|
|
||||||
return {in_, dist(in_, out_)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a list of buffers that represent the output sequence, with the given size.
|
|
||||||
|
|
||||||
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
|
||||||
|
|
||||||
@note All previous buffers sequences obtained from
|
|
||||||
calls to @ref data or @ref prepare are invalidated.
|
|
||||||
*/
|
|
||||||
mutable_buffers_type
|
|
||||||
prepare(std::size_t n);
|
|
||||||
|
|
||||||
/** Move bytes from the output sequence to the input sequence.
|
|
||||||
|
|
||||||
@param n The number of bytes to move. If this is larger than
|
|
||||||
the number of bytes in the output sequences, then the entire
|
|
||||||
output sequences is moved.
|
|
||||||
|
|
||||||
@note All previous buffers sequences obtained from
|
|
||||||
calls to @ref data or @ref prepare are invalidated.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
commit(std::size_t n)
|
|
||||||
{
|
|
||||||
out_ += (std::min)(n, dist(out_, last_));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove bytes from the input sequence.
|
|
||||||
|
|
||||||
If `n` is greater than the number of bytes in the input
|
|
||||||
sequence, all bytes in the input sequence are removed.
|
|
||||||
|
|
||||||
@note All previous buffers sequences obtained from
|
|
||||||
calls to @ref data or @ref prepare are invalidated.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
consume(std::size_t n);
|
|
||||||
|
|
||||||
/** Reallocate the buffer to fit the input sequence.
|
|
||||||
|
|
||||||
@note All previous buffers sequences obtained from
|
|
||||||
calls to @ref data or @ref prepare are invalidated.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
shrink_to_fit();
|
shrink_to_fit();
|
||||||
|
|
||||||
/// Exchange two flat buffers
|
/// Exchange two dynamic buffers
|
||||||
template<class Alloc>
|
template<class Alloc>
|
||||||
friend
|
friend
|
||||||
void
|
void
|
||||||
swap(
|
swap(
|
||||||
basic_flat_buffer<Alloc>& lhs,
|
basic_flat_buffer<Alloc>&,
|
||||||
basic_flat_buffer<Alloc>& rhs);
|
basic_flat_buffer<Alloc>&);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// The ConstBufferSequence used to represent the readable bytes.
|
||||||
|
using const_buffers_type = boost::asio::const_buffer;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the readable bytes.
|
||||||
|
using mutable_data_type = boost::asio::mutable_buffer;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the writable bytes.
|
||||||
|
using mutable_buffers_type = boost::asio::mutable_buffer;
|
||||||
|
|
||||||
|
/// Returns the number of readable bytes.
|
||||||
|
std::size_t
|
||||||
|
size() const noexcept
|
||||||
|
{
|
||||||
|
return dist(in_, out_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||||
|
std::size_t
|
||||||
|
max_size() const noexcept
|
||||||
|
{
|
||||||
|
return max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||||
|
std::size_t
|
||||||
|
capacity() const noexcept
|
||||||
|
{
|
||||||
|
return dist(begin_, end_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
const_buffers_type
|
||||||
|
data() const noexcept
|
||||||
|
{
|
||||||
|
return {in_, dist(in_, out_)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
const_buffers_type
|
||||||
|
cdata() const noexcept
|
||||||
|
{
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable buffer sequence representing the readable bytes
|
||||||
|
mutable_data_type
|
||||||
|
data() noexcept
|
||||||
|
{
|
||||||
|
return {in_, dist(in_, out_)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a mutable buffer sequence representing writable bytes.
|
||||||
|
|
||||||
|
Returns a mutable buffer sequence representing the writable
|
||||||
|
bytes containing exactly `n` bytes of storage. Memory may be
|
||||||
|
reallocated as needed.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The desired number of bytes in the returned buffer
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||||
|
*/
|
||||||
|
mutable_buffers_type
|
||||||
|
prepare(std::size_t n);
|
||||||
|
|
||||||
|
/** Append writable bytes to the readable bytes.
|
||||||
|
|
||||||
|
Appends n bytes from the start of the writable bytes to the
|
||||||
|
end of the readable bytes. The remainder of the writable bytes
|
||||||
|
are discarded. If n is greater than the number of writable
|
||||||
|
bytes, all writable bytes are appended to the readable bytes.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to append. If this number
|
||||||
|
is greater than the number of writable bytes, all
|
||||||
|
writable bytes are appended.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
commit(std::size_t n) noexcept
|
||||||
|
{
|
||||||
|
out_ += (std::min)(n, dist(out_, last_));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove bytes from beginning of the readable bytes.
|
||||||
|
|
||||||
|
Removes n bytes from the beginning of the readable bytes.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to remove. If this number
|
||||||
|
is greater than the number of readable bytes, all
|
||||||
|
readable bytes are removed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
consume(std::size_t n) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void
|
void
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
void
|
void copy_from(DynamicBuffer const& other);
|
||||||
copy_from(DynamicBuffer const& other);
|
void move_assign(basic_flat_buffer&, std::true_type);
|
||||||
|
void move_assign(basic_flat_buffer&, std::false_type);
|
||||||
void
|
void copy_assign(basic_flat_buffer const&, std::true_type);
|
||||||
move_assign(basic_flat_buffer&, std::true_type);
|
void copy_assign(basic_flat_buffer const&, std::false_type);
|
||||||
|
void swap(basic_flat_buffer&);
|
||||||
void
|
void swap(basic_flat_buffer&, std::true_type);
|
||||||
move_assign(basic_flat_buffer&, std::false_type);
|
void swap(basic_flat_buffer&, std::false_type);
|
||||||
|
|
||||||
void
|
|
||||||
copy_assign(basic_flat_buffer const&, std::true_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
copy_assign(basic_flat_buffer const&, std::false_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_flat_buffer&);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_flat_buffer&, std::true_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_flat_buffer&, std::false_type);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A flat buffer which uses the default allocator.
|
||||||
using flat_buffer =
|
using flat_buffer =
|
||||||
basic_flat_buffer<std::allocator<char>>;
|
basic_flat_buffer<std::allocator<char>>;
|
||||||
|
|
||||||
|
@ -19,20 +19,32 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A flat @b DynamicBuffer with a fixed size internal buffer.
|
/** A dynamic buffer using a fixed size internal buffer.
|
||||||
|
|
||||||
Buffer sequences returned by @ref data and @ref prepare
|
A dynamic buffer encapsulates memory storage that may be
|
||||||
will always be of length one.
|
automatically resized as required, where the memory is
|
||||||
Ownership of the underlying storage belongs to the derived class.
|
divided into two regions: readable bytes followed by
|
||||||
|
writable bytes. These memory regions are internal to
|
||||||
|
the dynamic buffer, but direct access to the elements
|
||||||
|
is provided to permit them to be efficiently used with
|
||||||
|
I/O operations.
|
||||||
|
|
||||||
|
Objects of this type meet the requirements of @b DynamicBuffer
|
||||||
|
and have the following additional properties:
|
||||||
|
|
||||||
|
@li A mutable buffer sequence representing the readable
|
||||||
|
bytes is returned by @ref data when `this` is non-const.
|
||||||
|
|
||||||
|
@li Buffer sequences representing the readable and writable
|
||||||
|
bytes, returned by @ref data and @ref prepare, will have
|
||||||
|
length one.
|
||||||
|
|
||||||
|
@li Ownership of the underlying storage belongs to the
|
||||||
|
derived class.
|
||||||
|
|
||||||
@note Variables are usually declared using the template class
|
@note Variables are usually declared using the template class
|
||||||
@ref flat_static_buffer; however, to reduce the number of instantiations
|
@ref flat_static_buffer; however, to reduce the number of template
|
||||||
of template functions receiving static stream buffer arguments in a
|
instantiations, objects should be passed `flat_static_buffer_base&`.
|
||||||
deduced context, the signature of the receiving function should use
|
|
||||||
@ref flat_static_buffer_base.
|
|
||||||
|
|
||||||
When used with @ref flat_static_buffer this implements a dynamic
|
|
||||||
buffer using no memory allocations.
|
|
||||||
|
|
||||||
@see @ref flat_static_buffer
|
@see @ref flat_static_buffer
|
||||||
*/
|
*/
|
||||||
@ -44,22 +56,12 @@ class flat_static_buffer_base
|
|||||||
char* last_;
|
char* last_;
|
||||||
char* end_;
|
char* end_;
|
||||||
|
|
||||||
flat_static_buffer_base(flat_static_buffer_base const& other) = delete;
|
flat_static_buffer_base(
|
||||||
flat_static_buffer_base& operator=(flat_static_buffer_base const&) = delete;
|
flat_static_buffer_base const& other) = delete;
|
||||||
|
flat_static_buffer_base& operator=(
|
||||||
|
flat_static_buffer_base const&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** The type used to represent the input sequence as a list of buffers.
|
|
||||||
|
|
||||||
This buffer sequence is guaranteed to have length 1.
|
|
||||||
*/
|
|
||||||
using const_buffers_type = boost::asio::const_buffer;
|
|
||||||
|
|
||||||
/** The type used to represent the output sequence as a list of buffers.
|
|
||||||
|
|
||||||
This buffer sequence is guaranteed to have length 1.
|
|
||||||
*/
|
|
||||||
using mutable_buffers_type = boost::asio::mutable_buffer;
|
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
This creates a dynamic buffer using the provided storage area.
|
This creates a dynamic buffer using the provided storage area.
|
||||||
@ -68,71 +70,129 @@ public:
|
|||||||
|
|
||||||
@param n The number of valid bytes pointed to by `p`.
|
@param n The number of valid bytes pointed to by `p`.
|
||||||
*/
|
*/
|
||||||
flat_static_buffer_base(void* p, std::size_t n)
|
flat_static_buffer_base(
|
||||||
|
void* p, std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
reset_impl(p, n);
|
reset(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the size of the input sequence.
|
/// Change the number of readable and writable bytes to zero.
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
clear() noexcept;
|
||||||
|
|
||||||
|
// VFALCO Deprecate this
|
||||||
|
/// Change the number of readable and writable bytes to zero.
|
||||||
|
void
|
||||||
|
reset() noexcept
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// The ConstBufferSequence used to represent the readable bytes.
|
||||||
|
using const_buffers_type = boost::asio::const_buffer;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the readable bytes.
|
||||||
|
using mutable_data_type = boost::asio::mutable_buffer;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the writable bytes.
|
||||||
|
using mutable_buffers_type = boost::asio::mutable_buffer;
|
||||||
|
|
||||||
|
/// Returns the number of readable bytes.
|
||||||
std::size_t
|
std::size_t
|
||||||
size() const
|
size() const noexcept
|
||||||
{
|
{
|
||||||
return out_ - in_;
|
return out_ - in_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the maximum sum of the input and output sequence sizes.
|
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||||
std::size_t
|
std::size_t
|
||||||
max_size() const
|
max_size() const noexcept
|
||||||
{
|
{
|
||||||
return dist(begin_, end_);
|
return dist(begin_, end_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the maximum sum of input and output sizes that can be held without an allocation.
|
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||||
std::size_t
|
std::size_t
|
||||||
capacity() const
|
capacity() const noexcept
|
||||||
{
|
{
|
||||||
return max_size();
|
return max_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get a list of buffers that represent the input sequence.
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
|
||||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
|
||||||
*/
|
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const noexcept
|
||||||
|
{
|
||||||
|
return {in_, dist(in_, out_)};
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the input and output sequences to size 0
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
void
|
const_buffers_type
|
||||||
reset();
|
cdata() const noexcept
|
||||||
|
{
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a list of buffers that represent the output sequence, with the given size.
|
/// Returns a mutable buffer sequence representing the readable bytes
|
||||||
|
mutable_data_type
|
||||||
|
data() noexcept
|
||||||
|
{
|
||||||
|
return {in_, dist(in_, out_)};
|
||||||
|
}
|
||||||
|
|
||||||
@throws std::length_error if the size would exceed the limit
|
/** Returns a mutable buffer sequence representing writable bytes.
|
||||||
imposed by the underlying mutable buffer sequence.
|
|
||||||
|
Returns a mutable buffer sequence representing the writable
|
||||||
|
bytes containing exactly `n` bytes of storage.
|
||||||
|
|
||||||
@note Buffers representing the input sequence acquired prior to
|
All buffers sequences previously obtained using
|
||||||
this call remain valid.
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The desired number of bytes in the returned buffer
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||||
*/
|
*/
|
||||||
|
inline
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(std::size_t n);
|
prepare(std::size_t n);
|
||||||
|
|
||||||
/** Move bytes from the output sequence to the input sequence.
|
/** Append writable bytes to the readable bytes.
|
||||||
|
|
||||||
@note Buffers representing the input sequence acquired prior to
|
Appends n bytes from the start of the writable bytes to the
|
||||||
this call remain valid.
|
end of the readable bytes. The remainder of the writable bytes
|
||||||
|
are discarded. If n is greater than the number of writable
|
||||||
|
bytes, all writable bytes are appended to the readable bytes.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to append. If this number
|
||||||
|
is greater than the number of writable bytes, all
|
||||||
|
writable bytes are appended.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
commit(std::size_t n)
|
commit(std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
out_ += (std::min<std::size_t>)(n, last_ - out_);
|
out_ += (std::min<std::size_t>)(n, last_ - out_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove bytes from the input sequence.
|
/** Remove bytes from beginning of the readable bytes.
|
||||||
|
|
||||||
|
Removes n bytes from the beginning of the readable bytes.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to remove. If this number
|
||||||
|
is greater than the number of readable bytes, all
|
||||||
|
readable bytes are removed.
|
||||||
|
*/
|
||||||
|
inline
|
||||||
void
|
void
|
||||||
consume(std::size_t n)
|
consume(std::size_t n) noexcept;
|
||||||
{
|
|
||||||
consume_impl(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Constructor
|
/** Constructor
|
||||||
@ -154,33 +214,17 @@ protected:
|
|||||||
|
|
||||||
@param n The number of valid bytes pointed to by `p`.
|
@param n The number of valid bytes pointed to by `p`.
|
||||||
*/
|
*/
|
||||||
|
inline
|
||||||
void
|
void
|
||||||
reset(void* p, std::size_t n);
|
reset(void* p, std::size_t n) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static
|
static
|
||||||
inline
|
|
||||||
std::size_t
|
std::size_t
|
||||||
dist(char const* first, char const* last)
|
dist(char const* first, char const* last)
|
||||||
{
|
{
|
||||||
return static_cast<std::size_t>(last - first);
|
return static_cast<std::size_t>(last - first);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class = void>
|
|
||||||
void
|
|
||||||
reset_impl();
|
|
||||||
|
|
||||||
template<class = void>
|
|
||||||
void
|
|
||||||
reset_impl(void* p, std::size_t n);
|
|
||||||
|
|
||||||
template<class = void>
|
|
||||||
mutable_buffers_type
|
|
||||||
prepare_impl(std::size_t n);
|
|
||||||
|
|
||||||
template<class = void>
|
|
||||||
void
|
|
||||||
consume_impl(std::size_t n);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -251,4 +295,4 @@ public:
|
|||||||
|
|
||||||
#include <boost/beast/core/impl/flat_static_buffer.ipp>
|
#include <boost/beast/core/impl/flat_static_buffer.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,9 +18,11 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/* Memory is laid out thusly:
|
/* Layout:
|
||||||
|
|
||||||
begin_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
|
begin_ in_ out_ last_ end_
|
||||||
|
|<------->|<---------->|<---------->|<------->|
|
||||||
|
| readable | writable |
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@ -40,7 +42,8 @@ basic_flat_buffer()
|
|||||||
, out_(nullptr)
|
, out_(nullptr)
|
||||||
, last_(nullptr)
|
, last_(nullptr)
|
||||||
, end_(nullptr)
|
, end_(nullptr)
|
||||||
, max_((std::numeric_limits<std::size_t>::max)())
|
, max_((std::numeric_limits<
|
||||||
|
std::size_t>::max)())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,20 +62,24 @@ basic_flat_buffer(std::size_t limit)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
basic_flat_buffer(Allocator const& alloc)
|
basic_flat_buffer(Allocator const& alloc)
|
||||||
: boost::empty_value<base_alloc_type>(boost::empty_init_t(), alloc)
|
: boost::empty_value<base_alloc_type>(
|
||||||
|
boost::empty_init_t(), alloc)
|
||||||
, begin_(nullptr)
|
, begin_(nullptr)
|
||||||
, in_(nullptr)
|
, in_(nullptr)
|
||||||
, out_(nullptr)
|
, out_(nullptr)
|
||||||
, last_(nullptr)
|
, last_(nullptr)
|
||||||
, end_(nullptr)
|
, end_(nullptr)
|
||||||
, max_((std::numeric_limits<std::size_t>::max)())
|
, max_((std::numeric_limits<
|
||||||
|
std::size_t>::max)())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
basic_flat_buffer(std::size_t limit, Allocator const& alloc)
|
basic_flat_buffer(
|
||||||
: boost::empty_value<base_alloc_type>(boost::empty_init_t(), alloc)
|
std::size_t limit, Allocator const& alloc)
|
||||||
|
: boost::empty_value<base_alloc_type>(
|
||||||
|
boost::empty_init_t(), alloc)
|
||||||
, begin_(nullptr)
|
, begin_(nullptr)
|
||||||
, in_(nullptr)
|
, in_(nullptr)
|
||||||
, out_(nullptr)
|
, out_(nullptr)
|
||||||
@ -85,23 +92,23 @@ basic_flat_buffer(std::size_t limit, Allocator const& alloc)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
basic_flat_buffer(basic_flat_buffer&& other)
|
basic_flat_buffer(basic_flat_buffer&& other)
|
||||||
: boost::empty_value<base_alloc_type>(boost::empty_init_t(),
|
: boost::empty_value<base_alloc_type>(
|
||||||
std::move(other.get()))
|
boost::empty_init_t(), std::move(other.get()))
|
||||||
, begin_(boost::exchange(other.begin_, nullptr))
|
, begin_(boost::exchange(other.begin_, nullptr))
|
||||||
, in_(boost::exchange(other.in_, nullptr))
|
, in_(boost::exchange(other.in_, nullptr))
|
||||||
, out_(boost::exchange(other.out_, nullptr))
|
, out_(boost::exchange(other.out_, nullptr))
|
||||||
, last_(out_)
|
, last_(boost::exchange(other.last_, nullptr))
|
||||||
, end_(boost::exchange(other.end_, nullptr))
|
, end_(boost::exchange(other.end_, nullptr))
|
||||||
, max_(other.max_)
|
, max_(other.max_)
|
||||||
{
|
{
|
||||||
other.last_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
basic_flat_buffer(basic_flat_buffer&& other,
|
basic_flat_buffer(
|
||||||
Allocator const& alloc)
|
basic_flat_buffer&& other, Allocator const& alloc)
|
||||||
: boost::empty_value<base_alloc_type>(boost::empty_init_t(), alloc)
|
: boost::empty_value<base_alloc_type>(
|
||||||
|
boost::empty_init_t(), alloc)
|
||||||
{
|
{
|
||||||
if(this->get() != other.get())
|
if(this->get() != other.get())
|
||||||
{
|
{
|
||||||
@ -119,7 +126,7 @@ basic_flat_buffer(basic_flat_buffer&& other,
|
|||||||
begin_ = other.begin_;
|
begin_ = other.begin_;
|
||||||
in_ = other.in_;
|
in_ = other.in_;
|
||||||
out_ = other.out_;
|
out_ = other.out_;
|
||||||
last_ = out_;
|
last_ = other.out_; // invalidate
|
||||||
end_ = other.end_;
|
end_ = other.end_;
|
||||||
max_ = other.max_;
|
max_ = other.max_;
|
||||||
other.begin_ = nullptr;
|
other.begin_ = nullptr;
|
||||||
@ -229,6 +236,36 @@ operator=(basic_flat_buffer<OtherAlloc> const& other) ->
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
void
|
||||||
|
basic_flat_buffer<Allocator>::
|
||||||
|
shrink_to_fit()
|
||||||
|
{
|
||||||
|
auto const len = size();
|
||||||
|
if(len == capacity())
|
||||||
|
return;
|
||||||
|
char* p;
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(begin_);
|
||||||
|
BOOST_ASSERT(in_);
|
||||||
|
p = alloc_traits::allocate(
|
||||||
|
this->get(), len);
|
||||||
|
std::memcpy(p, in_, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = nullptr;
|
||||||
|
}
|
||||||
|
alloc_traits::deallocate(
|
||||||
|
this->get(), begin_, this->dist(begin_, end_));
|
||||||
|
begin_ = p;
|
||||||
|
in_ = begin_;
|
||||||
|
out_ = begin_ + len;
|
||||||
|
last_ = out_;
|
||||||
|
end_ = out_;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@ -284,7 +321,7 @@ prepare(std::size_t n) ->
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
consume(std::size_t n)
|
consume(std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
if(n >= dist(in_, out_))
|
if(n >= dist(in_, out_))
|
||||||
{
|
{
|
||||||
@ -295,40 +332,9 @@ consume(std::size_t n)
|
|||||||
in_ += n;
|
in_ += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
void
|
|
||||||
basic_flat_buffer<Allocator>::
|
|
||||||
shrink_to_fit()
|
|
||||||
{
|
|
||||||
auto const len = size();
|
|
||||||
if(len == capacity())
|
|
||||||
return;
|
|
||||||
char* p;
|
|
||||||
if(len > 0)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(begin_);
|
|
||||||
BOOST_ASSERT(in_);
|
|
||||||
p = alloc_traits::allocate(
|
|
||||||
this->get(), len);
|
|
||||||
std::memcpy(p, in_, len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p = nullptr;
|
|
||||||
}
|
|
||||||
alloc_traits::deallocate(
|
|
||||||
this->get(), begin_, dist(begin_, end_));
|
|
||||||
begin_ = p;
|
|
||||||
in_ = begin_;
|
|
||||||
out_ = begin_ + len;
|
|
||||||
last_ = out_;
|
|
||||||
end_ = out_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
reset()
|
reset()
|
||||||
@ -339,20 +345,17 @@ reset()
|
|||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
copy_from(DynamicBuffer const& buffer)
|
copy_from(DynamicBuffer const& buffer)
|
||||||
{
|
{
|
||||||
if(buffer.size() == 0)
|
if(buffer.size() == 0)
|
||||||
return;
|
return;
|
||||||
using boost::asio::buffer_copy;
|
commit(boost::asio::buffer_copy(
|
||||||
commit(buffer_copy(
|
|
||||||
prepare(buffer.size()), buffer.data()));
|
prepare(buffer.size()), buffer.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
move_assign(basic_flat_buffer& other, std::true_type)
|
move_assign(basic_flat_buffer& other, std::true_type)
|
||||||
@ -373,7 +376,6 @@ move_assign(basic_flat_buffer& other, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
move_assign(basic_flat_buffer& other, std::false_type)
|
move_assign(basic_flat_buffer& other, std::false_type)
|
||||||
@ -391,7 +393,6 @@ move_assign(basic_flat_buffer& other, std::false_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
copy_assign(basic_flat_buffer const& other, std::true_type)
|
copy_assign(basic_flat_buffer const& other, std::true_type)
|
||||||
@ -403,7 +404,6 @@ copy_assign(basic_flat_buffer const& other, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
copy_assign(basic_flat_buffer const& other, std::false_type)
|
copy_assign(basic_flat_buffer const& other, std::false_type)
|
||||||
@ -414,7 +414,6 @@ copy_assign(basic_flat_buffer const& other, std::false_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
swap(basic_flat_buffer& other)
|
swap(basic_flat_buffer& other)
|
||||||
@ -424,7 +423,6 @@ swap(basic_flat_buffer& other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
swap(basic_flat_buffer& other, std::true_type)
|
swap(basic_flat_buffer& other, std::true_type)
|
||||||
@ -441,7 +439,6 @@ swap(basic_flat_buffer& other, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_flat_buffer<Allocator>::
|
basic_flat_buffer<Allocator>::
|
||||||
swap(basic_flat_buffer& other, std::false_type)
|
swap(basic_flat_buffer& other, std::false_type)
|
||||||
|
@ -21,72 +21,26 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/* Memory is laid out thusly:
|
/* Layout:
|
||||||
|
|
||||||
begin_ ..|.. in_ ..|.. out_ ..|.. last_ ..|.. end_
|
begin_ in_ out_ last_ end_
|
||||||
|
|<------->|<---------->|<---------->|<------->|
|
||||||
|
| readable | writable |
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline
|
|
||||||
auto
|
|
||||||
flat_static_buffer_base::
|
|
||||||
data() const ->
|
|
||||||
const_buffers_type
|
|
||||||
{
|
|
||||||
return {in_, dist(in_, out_)};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
flat_static_buffer_base::
|
flat_static_buffer_base::
|
||||||
reset()
|
clear() noexcept
|
||||||
{
|
{
|
||||||
reset_impl();
|
in_ = begin_;
|
||||||
|
out_ = begin_;
|
||||||
|
last_ = begin_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
|
||||||
auto
|
auto
|
||||||
flat_static_buffer_base::
|
flat_static_buffer_base::
|
||||||
prepare(std::size_t n) ->
|
prepare(std::size_t n) ->
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
{
|
|
||||||
return prepare_impl(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
flat_static_buffer_base::
|
|
||||||
reset(void* p, std::size_t n)
|
|
||||||
{
|
|
||||||
reset_impl(p, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class>
|
|
||||||
void
|
|
||||||
flat_static_buffer_base::
|
|
||||||
reset_impl()
|
|
||||||
{
|
|
||||||
in_ = begin_;
|
|
||||||
out_ = begin_;
|
|
||||||
last_ = begin_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class>
|
|
||||||
void
|
|
||||||
flat_static_buffer_base::
|
|
||||||
reset_impl(void* p, std::size_t n)
|
|
||||||
{
|
|
||||||
begin_ = static_cast<char*>(p);
|
|
||||||
in_ = begin_;
|
|
||||||
out_ = begin_;
|
|
||||||
last_ = begin_;
|
|
||||||
end_ = begin_ + n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class>
|
|
||||||
auto
|
|
||||||
flat_static_buffer_base::
|
|
||||||
prepare_impl(std::size_t n) ->
|
|
||||||
mutable_buffers_type
|
|
||||||
{
|
{
|
||||||
if(n <= dist(out_, end_))
|
if(n <= dist(out_, end_))
|
||||||
{
|
{
|
||||||
@ -105,10 +59,9 @@ prepare_impl(std::size_t n) ->
|
|||||||
return {out_, n};
|
return {out_, n};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class>
|
|
||||||
void
|
void
|
||||||
flat_static_buffer_base::
|
flat_static_buffer_base::
|
||||||
consume_impl(std::size_t n)
|
consume(std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
if(n >= size())
|
if(n >= size())
|
||||||
{
|
{
|
||||||
@ -119,6 +72,17 @@ consume_impl(std::size_t n)
|
|||||||
in_ += n;
|
in_ += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flat_static_buffer_base::
|
||||||
|
reset(void* p, std::size_t n) noexcept
|
||||||
|
{
|
||||||
|
begin_ = static_cast<char*>(p);
|
||||||
|
in_ = begin_;
|
||||||
|
out_ = begin_;
|
||||||
|
last_ = begin_;
|
||||||
|
end_ = begin_ + n;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
@ -147,4 +111,4 @@ operator=(flat_static_buffer const& other) ->
|
|||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,6 +18,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -86,6 +87,7 @@ namespace beast {
|
|||||||
in_pos_ out_pos_ == 0
|
in_pos_ out_pos_ == 0
|
||||||
out_end_ == 0
|
out_end_ == 0
|
||||||
*/
|
*/
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class basic_multi_buffer<Allocator>::element
|
class basic_multi_buffer<Allocator>::element
|
||||||
@ -93,105 +95,99 @@ class basic_multi_buffer<Allocator>::element
|
|||||||
boost::intrusive::link_mode<
|
boost::intrusive::link_mode<
|
||||||
boost::intrusive::normal_link>>
|
boost::intrusive::normal_link>>
|
||||||
{
|
{
|
||||||
using size_type =
|
using size_type = typename
|
||||||
typename detail::allocator_traits<Allocator>::size_type;
|
detail::allocator_traits<Allocator>::size_type;
|
||||||
|
|
||||||
size_type const size_;
|
size_type const size_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
element(element const&) = delete;
|
element(element const&) = delete;
|
||||||
element& operator=(element const&) = delete;
|
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
element(size_type n)
|
element(size_type n) noexcept
|
||||||
: size_(n)
|
: size_(n)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type
|
size_type
|
||||||
size() const
|
size() const noexcept
|
||||||
{
|
{
|
||||||
return size_;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
data() const
|
data() const noexcept
|
||||||
{
|
{
|
||||||
return const_cast<char*>(
|
return const_cast<char*>(
|
||||||
reinterpret_cast<char const*>(this + 1));
|
reinterpret_cast<char const*>(this + 1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class basic_multi_buffer<Allocator>::const_buffers_type
|
template<bool IsMutable>
|
||||||
|
class basic_multi_buffer<Allocator>::readable_bytes
|
||||||
{
|
{
|
||||||
basic_multi_buffer const* b_;
|
basic_multi_buffer const* b_;
|
||||||
|
|
||||||
friend class basic_multi_buffer;
|
friend class basic_multi_buffer;
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
const_buffers_type(basic_multi_buffer const& b);
|
readable_bytes(
|
||||||
|
basic_multi_buffer const& b) noexcept
|
||||||
|
: b_(&b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = boost::asio::const_buffer;
|
using value_type = typename std::conditional<
|
||||||
|
IsMutable,
|
||||||
|
boost::asio::mutable_buffer,
|
||||||
|
boost::asio::const_buffer>::type;
|
||||||
|
|
||||||
class const_iterator;
|
class const_iterator;
|
||||||
|
|
||||||
const_buffers_type() = delete;
|
readable_bytes() = delete;
|
||||||
const_buffers_type(const_buffers_type const&) = default;
|
readable_bytes& operator=(readable_bytes const&) = default;
|
||||||
const_buffers_type& operator=(const_buffers_type const&) = default;
|
|
||||||
|
|
||||||
const_iterator
|
template<
|
||||||
begin() const;
|
bool OtherIsMutable,
|
||||||
|
bool ThisIsMutable = IsMutable>
|
||||||
|
readable_bytes(
|
||||||
|
readable_bytes<OtherIsMutable> const& other,
|
||||||
|
typename std::enable_if<
|
||||||
|
! ThisIsMutable || OtherIsMutable>::type* = 0)
|
||||||
|
: b_(other.b_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator begin() const noexcept;
|
||||||
end() const;
|
const_iterator end() const noexcept;
|
||||||
|
|
||||||
friend
|
friend
|
||||||
std::size_t
|
std::size_t
|
||||||
buffer_size(const_buffers_type const& buffers)
|
buffer_size(readable_bytes const& buffers) noexcept
|
||||||
{
|
{
|
||||||
return buffers.b_->size();
|
return buffers.b_->size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
class basic_multi_buffer<Allocator>::mutable_buffers_type
|
|
||||||
{
|
|
||||||
basic_multi_buffer const* b_;
|
|
||||||
|
|
||||||
friend class basic_multi_buffer;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
mutable_buffers_type(basic_multi_buffer const& b);
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = mutable_buffer;
|
|
||||||
|
|
||||||
class const_iterator;
|
|
||||||
|
|
||||||
mutable_buffers_type() = delete;
|
|
||||||
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>
|
template<class Allocator>
|
||||||
class basic_multi_buffer<Allocator>::const_buffers_type::const_iterator
|
template<bool IsMutable>
|
||||||
|
class
|
||||||
|
basic_multi_buffer<Allocator>::
|
||||||
|
readable_bytes<IsMutable>::
|
||||||
|
const_iterator
|
||||||
{
|
{
|
||||||
basic_multi_buffer const* b_ = nullptr;
|
basic_multi_buffer const* b_ = nullptr;
|
||||||
typename list_type::const_iterator it_;
|
typename list_type::const_iterator it_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type =
|
using value_type =
|
||||||
typename const_buffers_type::value_type;
|
typename readable_bytes::value_type;
|
||||||
using pointer = value_type const*;
|
using pointer = value_type const*;
|
||||||
using reference = value_type;
|
using reference = value_type;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
@ -204,27 +200,28 @@ public:
|
|||||||
const_iterator& operator=(const_iterator&& other) = default;
|
const_iterator& operator=(const_iterator&& other) = default;
|
||||||
const_iterator& operator=(const_iterator const& other) = default;
|
const_iterator& operator=(const_iterator const& other) = default;
|
||||||
|
|
||||||
const_iterator(basic_multi_buffer const& b,
|
const_iterator(
|
||||||
typename list_type::const_iterator const& it)
|
basic_multi_buffer const& b,
|
||||||
|
typename list_type::const_iterator const& it) noexcept
|
||||||
: b_(&b)
|
: b_(&b)
|
||||||
, it_(it)
|
, it_(it)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator==(const_iterator const& other) const
|
operator==(const_iterator const& other) const noexcept
|
||||||
{
|
{
|
||||||
return b_ == other.b_ && it_ == other.it_;
|
return b_ == other.b_ && it_ == other.it_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator!=(const_iterator const& other) const
|
operator!=(const_iterator const& other) const noexcept
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
reference
|
reference
|
||||||
operator*() const
|
operator*() const noexcept
|
||||||
{
|
{
|
||||||
auto const& e = *it_;
|
auto const& e = *it_;
|
||||||
return value_type{e.data(),
|
return value_type{e.data(),
|
||||||
@ -237,14 +234,14 @@ public:
|
|||||||
operator->() const = delete;
|
operator->() const = delete;
|
||||||
|
|
||||||
const_iterator&
|
const_iterator&
|
||||||
operator++()
|
operator++() noexcept
|
||||||
{
|
{
|
||||||
++it_;
|
++it_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator
|
||||||
operator++(int)
|
operator++(int) noexcept
|
||||||
{
|
{
|
||||||
auto temp = *this;
|
auto temp = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -252,14 +249,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const_iterator&
|
const_iterator&
|
||||||
operator--()
|
operator--() noexcept
|
||||||
{
|
{
|
||||||
--it_;
|
--it_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator
|
||||||
operator--(int)
|
operator--(int) noexcept
|
||||||
{
|
{
|
||||||
auto temp = *this;
|
auto temp = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -267,36 +264,34 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Allocator>
|
//------------------------------------------------------------------------------
|
||||||
basic_multi_buffer<Allocator>::
|
|
||||||
const_buffers_type::
|
|
||||||
const_buffers_type(
|
|
||||||
basic_multi_buffer const& b)
|
|
||||||
: b_(&b)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
auto
|
class basic_multi_buffer<Allocator>::mutable_buffers_type
|
||||||
basic_multi_buffer<Allocator>::
|
|
||||||
const_buffers_type::
|
|
||||||
begin() const ->
|
|
||||||
const_iterator
|
|
||||||
{
|
{
|
||||||
return const_iterator{*b_, b_->list_.begin()};
|
basic_multi_buffer const* b_;
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
friend class basic_multi_buffer;
|
||||||
auto
|
|
||||||
basic_multi_buffer<Allocator>::
|
explicit
|
||||||
const_buffers_type::
|
mutable_buffers_type(
|
||||||
end() const ->
|
basic_multi_buffer const& b) noexcept
|
||||||
const_iterator
|
: b_(&b)
|
||||||
{
|
{
|
||||||
return const_iterator{*b_, b_->out_ ==
|
}
|
||||||
b_->list_.end() ? b_->list_.end() :
|
|
||||||
std::next(b_->out_)};
|
public:
|
||||||
}
|
using value_type = mutable_buffer;
|
||||||
|
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
mutable_buffers_type() = delete;
|
||||||
|
mutable_buffers_type(mutable_buffers_type const&) = default;
|
||||||
|
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept;
|
||||||
|
const_iterator end() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -321,27 +316,28 @@ public:
|
|||||||
const_iterator& operator=(const_iterator&& other) = default;
|
const_iterator& operator=(const_iterator&& other) = default;
|
||||||
const_iterator& operator=(const_iterator const& other) = default;
|
const_iterator& operator=(const_iterator const& other) = default;
|
||||||
|
|
||||||
const_iterator(basic_multi_buffer const& b,
|
const_iterator(
|
||||||
typename list_type::const_iterator const& it)
|
basic_multi_buffer const& b,
|
||||||
|
typename list_type::const_iterator const& it) noexcept
|
||||||
: b_(&b)
|
: b_(&b)
|
||||||
, it_(it)
|
, it_(it)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator==(const_iterator const& other) const
|
operator==(const_iterator const& other) const noexcept
|
||||||
{
|
{
|
||||||
return b_ == other.b_ && it_ == other.it_;
|
return b_ == other.b_ && it_ == other.it_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator!=(const_iterator const& other) const
|
operator!=(const_iterator const& other) const noexcept
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
reference
|
reference
|
||||||
operator*() const
|
operator*() const noexcept
|
||||||
{
|
{
|
||||||
auto const& e = *it_;
|
auto const& e = *it_;
|
||||||
return value_type{e.data(),
|
return value_type{e.data(),
|
||||||
@ -354,14 +350,14 @@ public:
|
|||||||
operator->() const = delete;
|
operator->() const = delete;
|
||||||
|
|
||||||
const_iterator&
|
const_iterator&
|
||||||
operator++()
|
operator++() noexcept
|
||||||
{
|
{
|
||||||
++it_;
|
++it_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator
|
||||||
operator++(int)
|
operator++(int) noexcept
|
||||||
{
|
{
|
||||||
auto temp = *this;
|
auto temp = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -369,14 +365,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const_iterator&
|
const_iterator&
|
||||||
operator--()
|
operator--() noexcept
|
||||||
{
|
{
|
||||||
--it_;
|
--it_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator
|
const_iterator
|
||||||
operator--(int)
|
operator--(int) noexcept
|
||||||
{
|
{
|
||||||
auto temp = *this;
|
auto temp = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -384,20 +380,37 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
|
template<bool IsMutable>
|
||||||
|
auto
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
mutable_buffers_type::
|
readable_bytes<IsMutable>::
|
||||||
mutable_buffers_type(
|
begin() const noexcept ->
|
||||||
basic_multi_buffer const& b)
|
const_iterator
|
||||||
: b_(&b)
|
|
||||||
{
|
{
|
||||||
|
return const_iterator{*b_, b_->list_.begin()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
template<bool IsMutable>
|
||||||
|
auto
|
||||||
|
basic_multi_buffer<Allocator>::
|
||||||
|
readable_bytes<IsMutable>::
|
||||||
|
end() const noexcept ->
|
||||||
|
const_iterator
|
||||||
|
{
|
||||||
|
return const_iterator{*b_, b_->out_ ==
|
||||||
|
b_->list_.end() ? b_->list_.end() :
|
||||||
|
std::next(b_->out_)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
auto
|
auto
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
mutable_buffers_type::
|
mutable_buffers_type::
|
||||||
begin() const ->
|
begin() const noexcept ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*b_, b_->out_};
|
return const_iterator{*b_, b_->out_};
|
||||||
@ -407,7 +420,7 @@ template<class Allocator>
|
|||||||
auto
|
auto
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
mutable_buffers_type::
|
mutable_buffers_type::
|
||||||
end() const ->
|
end() const noexcept ->
|
||||||
const_iterator
|
const_iterator
|
||||||
{
|
{
|
||||||
return const_iterator{*b_, b_->list_.end()};
|
return const_iterator{*b_, b_->list_.end()};
|
||||||
@ -424,22 +437,7 @@ basic_multi_buffer<Allocator>::
|
|||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
basic_multi_buffer()
|
basic_multi_buffer(Allocator const& alloc) noexcept
|
||||||
: out_(list_.end())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
basic_multi_buffer<Allocator>::
|
|
||||||
basic_multi_buffer(std::size_t limit)
|
|
||||||
: max_(limit)
|
|
||||||
, out_(list_.end())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
basic_multi_buffer<Allocator>::
|
|
||||||
basic_multi_buffer(Allocator const& alloc)
|
|
||||||
: boost::empty_value<
|
: boost::empty_value<
|
||||||
base_alloc_type>(boost::empty_init_t(), alloc)
|
base_alloc_type>(boost::empty_init_t(), alloc)
|
||||||
, out_(list_.end())
|
, out_(list_.end())
|
||||||
@ -449,7 +447,7 @@ basic_multi_buffer(Allocator const& alloc)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
basic_multi_buffer(std::size_t limit,
|
basic_multi_buffer(std::size_t limit,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc) noexcept
|
||||||
: boost::empty_value<
|
: boost::empty_value<
|
||||||
base_alloc_type>(boost::empty_init_t(), alloc)
|
base_alloc_type>(boost::empty_init_t(), alloc)
|
||||||
, max_(limit)
|
, max_(limit)
|
||||||
@ -459,7 +457,7 @@ basic_multi_buffer(std::size_t limit,
|
|||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
basic_multi_buffer(basic_multi_buffer&& other)
|
basic_multi_buffer(basic_multi_buffer&& other) noexcept
|
||||||
: boost::empty_value<
|
: boost::empty_value<
|
||||||
base_alloc_type>(boost::empty_init_t(), std::move(other.get()))
|
base_alloc_type>(boost::empty_init_t(), std::move(other.get()))
|
||||||
, max_(other.max_)
|
, max_(other.max_)
|
||||||
@ -598,10 +596,12 @@ operator=(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
std::size_t
|
std::size_t
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
capacity() const
|
capacity() const noexcept
|
||||||
{
|
{
|
||||||
auto pos = out_;
|
auto pos = out_;
|
||||||
if(pos == list_.end())
|
if(pos == list_.end())
|
||||||
@ -615,12 +615,21 @@ capacity() const
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
auto
|
auto
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
data() const ->
|
data() const noexcept ->
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
{
|
{
|
||||||
return const_buffers_type(*this);
|
return const_buffers_type(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
auto
|
||||||
|
basic_multi_buffer<Allocator>::
|
||||||
|
data() noexcept ->
|
||||||
|
mutable_data_type
|
||||||
|
{
|
||||||
|
return mutable_data_type(*this);
|
||||||
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
auto
|
auto
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
@ -723,7 +732,7 @@ prepare(size_type n) ->
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
commit(size_type n)
|
commit(size_type n) noexcept
|
||||||
{
|
{
|
||||||
if(list_.empty())
|
if(list_.empty())
|
||||||
return;
|
return;
|
||||||
@ -770,7 +779,7 @@ commit(size_type n)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
consume(size_type n)
|
consume(size_type n) noexcept
|
||||||
{
|
{
|
||||||
if(list_.empty())
|
if(list_.empty())
|
||||||
return;
|
return;
|
||||||
@ -836,10 +845,23 @@ consume(size_type n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
delete_list()
|
reset() noexcept
|
||||||
|
{
|
||||||
|
delete_list();
|
||||||
|
list_.clear();
|
||||||
|
out_ = list_.end();
|
||||||
|
in_size_ = 0;
|
||||||
|
in_pos_ = 0;
|
||||||
|
out_pos_ = 0;
|
||||||
|
out_end_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
void
|
||||||
|
basic_multi_buffer<Allocator>::
|
||||||
|
delete_list() noexcept
|
||||||
{
|
{
|
||||||
for(auto iter = list_.begin(); iter != list_.end();)
|
for(auto iter = list_.begin(); iter != list_.end();)
|
||||||
{
|
{
|
||||||
@ -851,24 +873,8 @@ delete_list()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
basic_multi_buffer<Allocator>::
|
|
||||||
reset()
|
|
||||||
{
|
|
||||||
delete_list();
|
|
||||||
list_.clear();
|
|
||||||
out_ = list_.end();
|
|
||||||
in_size_ = 0;
|
|
||||||
in_pos_ = 0;
|
|
||||||
out_pos_ = 0;
|
|
||||||
out_end_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
copy_from(DynamicBuffer const& buffer)
|
copy_from(DynamicBuffer const& buffer)
|
||||||
@ -881,7 +887,6 @@ copy_from(DynamicBuffer const& buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
move_assign(basic_multi_buffer& other, std::false_type)
|
move_assign(basic_multi_buffer& other, std::false_type)
|
||||||
@ -898,10 +903,9 @@ move_assign(basic_multi_buffer& other, std::false_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
move_assign(basic_multi_buffer& other, std::true_type)
|
move_assign(basic_multi_buffer& other, std::true_type) noexcept
|
||||||
{
|
{
|
||||||
this->get() = std::move(other.get());
|
this->get() = std::move(other.get());
|
||||||
auto const at_end =
|
auto const at_end =
|
||||||
@ -922,7 +926,6 @@ move_assign(basic_multi_buffer& other, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
copy_assign(
|
copy_assign(
|
||||||
@ -934,7 +937,6 @@ copy_assign(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
copy_assign(
|
copy_assign(
|
||||||
@ -947,20 +949,18 @@ copy_assign(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
swap(basic_multi_buffer& other)
|
swap(basic_multi_buffer& other) noexcept
|
||||||
{
|
{
|
||||||
swap(other, typename
|
swap(other, typename
|
||||||
alloc_traits::propagate_on_container_swap{});
|
alloc_traits::propagate_on_container_swap{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
swap(basic_multi_buffer& other, std::true_type)
|
swap(basic_multi_buffer& other, std::true_type) noexcept
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
auto const at_end0 =
|
auto const at_end0 =
|
||||||
@ -981,10 +981,9 @@ swap(basic_multi_buffer& other, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
basic_multi_buffer<Allocator>::
|
basic_multi_buffer<Allocator>::
|
||||||
swap(basic_multi_buffer& other, std::false_type)
|
swap(basic_multi_buffer& other, std::false_type) noexcept
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(this->get() == other.get());
|
BOOST_ASSERT(this->get() == other.get());
|
||||||
using std::swap;
|
using std::swap;
|
||||||
@ -1008,7 +1007,7 @@ template<class Allocator>
|
|||||||
void
|
void
|
||||||
swap(
|
swap(
|
||||||
basic_multi_buffer<Allocator>& lhs,
|
basic_multi_buffer<Allocator>& lhs,
|
||||||
basic_multi_buffer<Allocator>& rhs)
|
basic_multi_buffer<Allocator>& rhs) noexcept
|
||||||
{
|
{
|
||||||
lhs.swap(rhs);
|
lhs.swap(rhs);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace beast {
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
static_buffer_base(void* p, std::size_t size)
|
static_buffer_base(void* p, std::size_t size) noexcept
|
||||||
: begin_(static_cast<char*>(p))
|
: begin_(static_cast<char*>(p))
|
||||||
, capacity_(size)
|
, capacity_(size)
|
||||||
{
|
{
|
||||||
@ -32,7 +32,7 @@ static_buffer_base(void* p, std::size_t size)
|
|||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
data() const ->
|
data() const noexcept ->
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
{
|
{
|
||||||
using boost::asio::const_buffer;
|
using boost::asio::const_buffer;
|
||||||
@ -53,11 +53,11 @@ data() const ->
|
|||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
mutable_data() ->
|
data() noexcept ->
|
||||||
mutable_buffers_type
|
mutable_data_type
|
||||||
{
|
{
|
||||||
using boost::asio::mutable_buffer;
|
using boost::asio::mutable_buffer;
|
||||||
mutable_buffers_type result;
|
mutable_data_type result;
|
||||||
if(in_off_ + in_size_ <= capacity_)
|
if(in_off_ + in_size_ <= capacity_)
|
||||||
{
|
{
|
||||||
result[0] = mutable_buffer{begin_ + in_off_, in_size_};
|
result[0] = mutable_buffer{begin_ + in_off_, in_size_};
|
||||||
@ -74,14 +74,14 @@ mutable_data() ->
|
|||||||
inline
|
inline
|
||||||
auto
|
auto
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
prepare(std::size_t size) ->
|
prepare(std::size_t n) ->
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
{
|
{
|
||||||
using boost::asio::mutable_buffer;
|
using boost::asio::mutable_buffer;
|
||||||
if(size > capacity_ - in_size_)
|
if(n > capacity_ - in_size_)
|
||||||
BOOST_THROW_EXCEPTION(std::length_error{
|
BOOST_THROW_EXCEPTION(std::length_error{
|
||||||
"buffer overflow"});
|
"buffer overflow"});
|
||||||
out_size_ = size;
|
out_size_ = n;
|
||||||
auto const out_off = (in_off_ + in_size_) % capacity_;
|
auto const out_off = (in_off_ + in_size_) % capacity_;
|
||||||
mutable_buffers_type result;
|
mutable_buffers_type result;
|
||||||
if(out_off + out_size_ <= capacity_ )
|
if(out_off + out_size_ <= capacity_ )
|
||||||
@ -100,27 +100,27 @@ prepare(std::size_t size) ->
|
|||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
commit(std::size_t size)
|
commit(std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
in_size_ += (std::min)(size, out_size_);
|
in_size_ += (std::min)(n, out_size_);
|
||||||
out_size_ = 0;
|
out_size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
consume(std::size_t size)
|
consume(std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
if(size < in_size_)
|
if(n < in_size_)
|
||||||
{
|
{
|
||||||
in_off_ = (in_off_ + size) % capacity_;
|
in_off_ = (in_off_ + n) % capacity_;
|
||||||
in_size_ -= size;
|
in_size_ -= n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// rewind the offset, so the next call to prepare
|
// rewind the offset, so the next call to prepare
|
||||||
// can have a longer contiguous segment. this helps
|
// can have a longer contiguous segment. this helps
|
||||||
// algorithms optimized for larger buffesr.
|
// algorithms optimized for larger buffers.
|
||||||
in_off_ = 0;
|
in_off_ = 0;
|
||||||
in_size_ = 0;
|
in_size_ = 0;
|
||||||
}
|
}
|
||||||
@ -129,10 +129,10 @@ consume(std::size_t size)
|
|||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
reset(void* p, std::size_t size)
|
reset(void* p, std::size_t n) noexcept
|
||||||
{
|
{
|
||||||
begin_ = static_cast<char*>(p);
|
begin_ = static_cast<char*>(p);
|
||||||
capacity_ = size;
|
capacity_ = n;
|
||||||
in_off_ = 0;
|
in_off_ = 0;
|
||||||
in_size_ = 0;
|
in_size_ = 0;
|
||||||
out_size_ = 0;
|
out_size_ = 0;
|
||||||
|
@ -23,14 +23,39 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A @b DynamicBuffer that uses multiple buffers internally.
|
/** A dynamic buffer providing sequences of variable length.
|
||||||
|
|
||||||
The implementation uses a sequence of one or more character arrays
|
A dynamic buffer encapsulates memory storage that may be
|
||||||
of varying sizes. Additional character array objects are appended to
|
automatically resized as required, where the memory is
|
||||||
the sequence to accommodate changes in the size of the character
|
divided into two regions: readable bytes followed by
|
||||||
sequence.
|
writable bytes. These memory regions are internal to
|
||||||
|
the dynamic buffer, but direct access to the elements
|
||||||
|
is provided to permit them to be efficiently used with
|
||||||
|
I/O operations.
|
||||||
|
|
||||||
@note Meets the requirements of @b DynamicBuffer.
|
The implementation uses a sequence of one or more byte
|
||||||
|
arrays of varying sizes to represent the readable and
|
||||||
|
writable bytes. Additional byte array objects are
|
||||||
|
appended to the sequence to accommodate changes in the
|
||||||
|
desired size. The behavior and implementation of this
|
||||||
|
container is most similar to `std::deque`.
|
||||||
|
|
||||||
|
Objects of this type meet the requirements of @b DynamicBuffer
|
||||||
|
and have the following additional properties:
|
||||||
|
|
||||||
|
@li The buffer sequence representing the readable bytes
|
||||||
|
returned by @ref data is mutable.
|
||||||
|
|
||||||
|
@li Buffer sequences representing the readable and writable
|
||||||
|
bytes, returned by @ref data and @ref prepare, may have
|
||||||
|
length greater than one.
|
||||||
|
|
||||||
|
@li A configurable maximum buffer size may be set upon
|
||||||
|
construction. Attempts to exceed the buffer size will throw
|
||||||
|
`std::length_error`.
|
||||||
|
|
||||||
|
@li Sequences previously obtained using @ref data remain
|
||||||
|
valid after calls to @ref prepare or @ref commit.
|
||||||
|
|
||||||
@tparam Allocator The allocator to use for managing memory.
|
@tparam Allocator The allocator to use for managing memory.
|
||||||
*/
|
*/
|
||||||
@ -51,6 +76,9 @@ class basic_multi_buffer
|
|||||||
// contains `element` followed by raw storage bytes.
|
// contains `element` followed by raw storage bytes.
|
||||||
class element;
|
class element;
|
||||||
|
|
||||||
|
template<bool IsMutable>
|
||||||
|
class readable_bytes;
|
||||||
|
|
||||||
using alloc_traits = detail::allocator_traits<base_alloc_type>;
|
using alloc_traits = detail::allocator_traits<base_alloc_type>;
|
||||||
using list_type = typename boost::intrusive::make_list<element,
|
using list_type = typename boost::intrusive::make_list<element,
|
||||||
boost::intrusive::constant_time_size<true>>::type;
|
boost::intrusive::constant_time_size<true>>::type;
|
||||||
@ -82,82 +110,103 @@ public:
|
|||||||
/// The type of allocator used.
|
/// The type of allocator used.
|
||||||
using allocator_type = Allocator;
|
using allocator_type = Allocator;
|
||||||
|
|
||||||
#if BOOST_BEAST_DOXYGEN
|
|
||||||
/// 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
|
/// Destructor
|
||||||
~basic_multi_buffer();
|
~basic_multi_buffer();
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
Upon construction, capacity will be zero.
|
Upon construction, @ref capacity will return zero.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer();
|
basic_multi_buffer() noexcept(
|
||||||
|
std::is_nothrow_default_constructible<Allocator>::value)
|
||||||
|
:
|
||||||
|
out_(list_.end())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructor.
|
/** Constructor
|
||||||
|
|
||||||
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param limit The setting for @ref max_size.
|
@param limit The setting for @ref max_size.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
basic_multi_buffer(std::size_t limit);
|
basic_multi_buffer(std::size_t limit) noexcept(
|
||||||
|
std::is_nothrow_default_constructible<Allocator>::value)
|
||||||
|
: max_(limit)
|
||||||
|
, out_(list_.end())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructor.
|
/** Constructor
|
||||||
|
|
||||||
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param alloc The allocator to use.
|
@param alloc The allocator to use.
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
basic_multi_buffer(Allocator const& alloc);
|
basic_multi_buffer(Allocator const& alloc) noexcept;
|
||||||
|
|
||||||
/** Constructor.
|
/** Constructor
|
||||||
|
|
||||||
|
Upon construction, @ref capacity will return zero.
|
||||||
|
|
||||||
@param limit The setting for @ref max_size.
|
@param limit The setting for @ref max_size.
|
||||||
|
|
||||||
@param alloc The allocator to use.
|
@param alloc The allocator to use.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer(
|
basic_multi_buffer(
|
||||||
std::size_t limit, Allocator const& alloc);
|
std::size_t limit, Allocator const& alloc) noexcept;
|
||||||
|
|
||||||
/** Move constructor
|
/** Move Constructor
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Constructs the container with the contents of other
|
||||||
|
using move semantics. After the move, other is
|
||||||
|
guaranteed to be empty.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data
|
||||||
|
or @ref prepare are not invalidated after the move.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
The object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer(basic_multi_buffer&& other);
|
basic_multi_buffer(basic_multi_buffer&& other) noexcept;
|
||||||
|
|
||||||
/** Move constructor
|
/** Move Constructor
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Using alloc as the allocator for the new container, the
|
||||||
|
contents of other are moved. If `alloc != other.get_allocator()`,
|
||||||
|
this results in a copy. After the move, other is
|
||||||
|
guaranteed to be empty.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
The object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
|
|
||||||
@param alloc The allocator to use.
|
@param alloc The allocator to use for the newly
|
||||||
|
constructed object.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer(basic_multi_buffer&& other,
|
basic_multi_buffer(basic_multi_buffer&& other,
|
||||||
Allocator const& alloc);
|
Allocator const& alloc);
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
allocator and contents of other, and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer(basic_multi_buffer const& other);
|
basic_multi_buffer(basic_multi_buffer const& other);
|
||||||
|
|
||||||
/** Copy constructor
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
specified allocator, a copy of the contents of other,
|
||||||
|
and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
|
|
||||||
@ -166,7 +215,10 @@ public:
|
|||||||
basic_multi_buffer(basic_multi_buffer const& other,
|
basic_multi_buffer(basic_multi_buffer const& other,
|
||||||
Allocator const& alloc);
|
Allocator const& alloc);
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
contents of other, and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -174,7 +226,11 @@ public:
|
|||||||
basic_multi_buffer(basic_multi_buffer<
|
basic_multi_buffer(basic_multi_buffer<
|
||||||
OtherAlloc> const& other);
|
OtherAlloc> const& other);
|
||||||
|
|
||||||
/** Copy constructor.
|
/** Copy Constructor
|
||||||
|
|
||||||
|
The newly constructed object will have a copy of the
|
||||||
|
specified allocator, a copy of the contents of other,
|
||||||
|
and zero writable bytes.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
|
|
||||||
@ -184,20 +240,28 @@ public:
|
|||||||
basic_multi_buffer(basic_multi_buffer<
|
basic_multi_buffer(basic_multi_buffer<
|
||||||
OtherAlloc> const& other, allocator_type const& alloc);
|
OtherAlloc> const& other, allocator_type const& alloc);
|
||||||
|
|
||||||
/** Move assignment
|
/** Move Assignment
|
||||||
|
|
||||||
After the move, `*this` will have an empty output sequence.
|
Assigns the container with the contents of other
|
||||||
|
using move semantics. After the move, other is
|
||||||
|
guaranteed to be empty. The previous contents of
|
||||||
|
this container are deleted.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data
|
||||||
|
or @ref prepare are not invalidated after the move.
|
||||||
|
|
||||||
@param other The object to move from. After the move,
|
@param other The object to move from. After the move,
|
||||||
The object's state will be as if constructed using
|
the moved-from object's state will be as if default
|
||||||
its current allocator and limit.
|
constructed using its current allocator and limit.
|
||||||
*/
|
*/
|
||||||
basic_multi_buffer&
|
basic_multi_buffer&
|
||||||
operator=(basic_multi_buffer&& other);
|
operator=(basic_multi_buffer&& other);
|
||||||
|
|
||||||
/** Copy assignment
|
/** Copy Assignment
|
||||||
|
|
||||||
After the copy, `*this` will have an empty output sequence.
|
The assigned object will have a copy of the allocator
|
||||||
|
and contents of other, and zero writable bytes. The
|
||||||
|
previous contents of this container are deleted.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -205,7 +269,9 @@ public:
|
|||||||
|
|
||||||
/** Copy assignment
|
/** Copy assignment
|
||||||
|
|
||||||
After the copy, `*this` will have an empty output sequence.
|
The assigned object will have a copy of the contents
|
||||||
|
of other, and zero writable bytes. The previous contents
|
||||||
|
of this container are deleted.
|
||||||
|
|
||||||
@param other The object to copy from.
|
@param other The object to copy from.
|
||||||
*/
|
*/
|
||||||
@ -213,102 +279,142 @@ public:
|
|||||||
basic_multi_buffer& operator=(
|
basic_multi_buffer& operator=(
|
||||||
basic_multi_buffer<OtherAlloc> const& other);
|
basic_multi_buffer<OtherAlloc> const& other);
|
||||||
|
|
||||||
/// Returns a copy of the associated allocator.
|
/// Returns a copy of the allocator used.
|
||||||
allocator_type
|
allocator_type
|
||||||
get_allocator() const
|
get_allocator() const
|
||||||
{
|
{
|
||||||
return this->get();
|
return this->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size of the input sequence.
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
/// The ConstBufferSequence used to represent the readable bytes.
|
||||||
|
using const_buffers_type = __implementation_defined__;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the readable bytes.
|
||||||
|
using mutable_data_type = __implementation_defined__;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the writable bytes.
|
||||||
|
using mutable_buffers_type = __implementation_defined__;
|
||||||
|
#else
|
||||||
|
using const_buffers_type = readable_bytes<false>;
|
||||||
|
using mutable_data_type = readable_bytes<true>;
|
||||||
|
class mutable_buffers_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Returns the number of readable bytes.
|
||||||
size_type
|
size_type
|
||||||
size() const
|
size() const noexcept
|
||||||
{
|
{
|
||||||
return in_size_;
|
return in_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the permitted maximum sum of the sizes of the input and output sequence.
|
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||||
size_type
|
size_type
|
||||||
max_size() const
|
max_size() const noexcept
|
||||||
{
|
{
|
||||||
return max_;
|
return max_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum sum of the sizes of the input sequence and output sequence the buffer can hold without requiring reallocation.
|
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||||
std::size_t
|
std::size_t
|
||||||
capacity() const;
|
capacity() const noexcept;
|
||||||
|
|
||||||
/** Get a list of buffers that represents the input sequence.
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
|
||||||
@note These buffers remain valid across subsequent calls to `prepare`.
|
|
||||||
*/
|
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const noexcept;
|
||||||
|
|
||||||
/** Get a list of buffers that represents the output sequence, with the given size.
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
const_buffers_type
|
||||||
|
cdata() const noexcept
|
||||||
|
{
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
@note Buffers representing the input sequence acquired prior to
|
/** Returns a mutable buffer sequence representing the readable bytes.
|
||||||
this call remain valid.
|
|
||||||
|
@note The sequence may contain zero or more contiguous memory
|
||||||
|
regions.
|
||||||
|
*/
|
||||||
|
mutable_data_type
|
||||||
|
data() noexcept;
|
||||||
|
|
||||||
|
/** Returns a mutable buffer sequence representing writable bytes.
|
||||||
|
|
||||||
|
Returns a mutable buffer sequence representing the writable
|
||||||
|
bytes containing exactly `n` bytes of storage. Memory may be
|
||||||
|
reallocated as needed.
|
||||||
|
|
||||||
|
All buffer sequences previously obtained using @ref prepare are
|
||||||
|
invalidated. Buffer sequences previously obtained using @ref data
|
||||||
|
remain valid.
|
||||||
|
|
||||||
|
@param n The desired number of bytes in the returned buffer
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||||
*/
|
*/
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(size_type n);
|
prepare(size_type n);
|
||||||
|
|
||||||
/** Move bytes from the output sequence to the input sequence.
|
/** Append writable bytes to the readable bytes.
|
||||||
|
|
||||||
@note Buffers representing the input sequence acquired prior to
|
Appends n bytes from the start of the writable bytes to the
|
||||||
this call remain valid.
|
end of the readable bytes. The remainder of the writable bytes
|
||||||
|
are discarded. If n is greater than the number of writable
|
||||||
|
bytes, all writable bytes are appended to the readable bytes.
|
||||||
|
|
||||||
|
All buffer sequences previously obtained using @ref prepare are
|
||||||
|
invalidated. Buffer sequences previously obtained using @ref data
|
||||||
|
remain valid.
|
||||||
|
|
||||||
|
@param n The number of bytes to append. If this number
|
||||||
|
is greater than the number of writable bytes, all
|
||||||
|
writable bytes are appended.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
commit(size_type n);
|
commit(size_type n) noexcept;
|
||||||
|
|
||||||
/// Remove bytes from the input sequence.
|
/** Remove bytes from beginning of the readable bytes.
|
||||||
|
|
||||||
|
Removes n bytes from the beginning of the readable bytes.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to remove. If this number
|
||||||
|
is greater than the number of readable bytes, all
|
||||||
|
readable bytes are removed.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
consume(size_type n);
|
consume(size_type n) noexcept;
|
||||||
|
|
||||||
|
/// Exchange two dynamic buffers
|
||||||
template<class Alloc>
|
template<class Alloc>
|
||||||
friend
|
friend
|
||||||
void
|
void
|
||||||
swap(
|
swap(
|
||||||
basic_multi_buffer<Alloc>& lhs,
|
basic_multi_buffer<Alloc>& lhs,
|
||||||
basic_multi_buffer<Alloc>& rhs);
|
basic_multi_buffer<Alloc>& rhs) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class OtherAlloc>
|
template<class OtherAlloc>
|
||||||
friend class basic_multi_buffer;
|
friend class basic_multi_buffer;
|
||||||
|
|
||||||
void
|
void reset() noexcept;
|
||||||
delete_list();
|
void delete_list() noexcept;
|
||||||
|
|
||||||
void
|
|
||||||
reset();
|
|
||||||
|
|
||||||
template<class DynamicBuffer>
|
template<class DynamicBuffer>
|
||||||
void
|
void copy_from(DynamicBuffer const& other);
|
||||||
copy_from(DynamicBuffer const& other);
|
void move_assign(basic_multi_buffer& other, std::false_type);
|
||||||
|
void move_assign(basic_multi_buffer& other, std::true_type) noexcept;
|
||||||
void
|
void copy_assign(basic_multi_buffer const& other, std::false_type);
|
||||||
move_assign(basic_multi_buffer& other, std::false_type);
|
void copy_assign(basic_multi_buffer const& other, std::true_type);
|
||||||
|
void swap(basic_multi_buffer&) noexcept;
|
||||||
void
|
void swap(basic_multi_buffer&, std::true_type) noexcept;
|
||||||
move_assign(basic_multi_buffer& other, std::true_type);
|
void swap(basic_multi_buffer&, std::false_type) noexcept;
|
||||||
|
void debug_check() const;
|
||||||
void
|
|
||||||
copy_assign(basic_multi_buffer const& other, std::false_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
copy_assign(basic_multi_buffer const& other, std::true_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_multi_buffer&);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_multi_buffer&, std::true_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
swap(basic_multi_buffer&, std::false_type);
|
|
||||||
|
|
||||||
void
|
|
||||||
debug_check() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A typical multi buffer
|
/// A typical multi buffer
|
||||||
@ -319,4 +425,4 @@ using multi_buffer = basic_multi_buffer<std::allocator<char>>;
|
|||||||
|
|
||||||
#include <boost/beast/core/impl/multi_buffer.ipp>
|
#include <boost/beast/core/impl/multi_buffer.ipp>
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -20,21 +21,34 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A circular @b DynamicBuffer with a fixed size internal buffer.
|
/** A dynamic buffer providing a fixed, circular buffer.
|
||||||
|
|
||||||
This implements a circular dynamic buffer. Calls to @ref prepare
|
A dynamic buffer encapsulates memory storage that may be
|
||||||
never require moving memory. The buffer sequences returned may
|
automatically resized as required, where the memory is
|
||||||
be up to length two.
|
divided into two regions: readable bytes followed by
|
||||||
Ownership of the underlying storage belongs to the derived class.
|
writable bytes. These memory regions are internal to
|
||||||
|
the dynamic buffer, but direct access to the elements
|
||||||
|
is provided to permit them to be efficiently used with
|
||||||
|
I/O operations.
|
||||||
|
|
||||||
|
Objects of this type meet the requirements of @b DynamicBuffer
|
||||||
|
and have the following additional properties:
|
||||||
|
|
||||||
|
@li A mutable buffer sequence representing the readable
|
||||||
|
bytes is returned by @ref data when `this` is non-const.
|
||||||
|
|
||||||
|
@li Buffer sequences representing the readable and writable
|
||||||
|
bytes, returned by @ref data and @ref prepare, will have
|
||||||
|
length at most one.
|
||||||
|
|
||||||
|
@li All operations execute in constant time.
|
||||||
|
|
||||||
|
@li Ownership of the underlying storage belongs to the
|
||||||
|
derived class.
|
||||||
|
|
||||||
@note Variables are usually declared using the template class
|
@note Variables are usually declared using the template class
|
||||||
@ref static_buffer; however, to reduce the number of instantiations
|
@ref static_buffer; however, to reduce the number of template
|
||||||
of template functions receiving static stream buffer arguments in a
|
instantiations, objects should be passed `static_buffer_base&`.
|
||||||
deduced context, the signature of the receiving function should use
|
|
||||||
@ref static_buffer_base.
|
|
||||||
|
|
||||||
When used with @ref static_buffer this implements a dynamic
|
|
||||||
buffer using no memory allocations.
|
|
||||||
|
|
||||||
@see @ref static_buffer
|
@see @ref static_buffer
|
||||||
*/
|
*/
|
||||||
@ -46,18 +60,98 @@ class static_buffer_base
|
|||||||
std::size_t out_size_ = 0;
|
std::size_t out_size_ = 0;
|
||||||
std::size_t capacity_;
|
std::size_t capacity_;
|
||||||
|
|
||||||
|
class const_buffer_pair;
|
||||||
|
|
||||||
|
class mutable_buffer_pair
|
||||||
|
{
|
||||||
|
boost::asio::mutable_buffer b_[2];
|
||||||
|
|
||||||
|
friend class const_buffer_pair;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using const_iterator =
|
||||||
|
boost::asio::mutable_buffer const*;
|
||||||
|
|
||||||
|
// workaround for buffers_iterator bug
|
||||||
|
using value_type =
|
||||||
|
boost::asio::mutable_buffer;
|
||||||
|
|
||||||
|
mutable_buffer_pair() = default;
|
||||||
|
mutable_buffer_pair(
|
||||||
|
mutable_buffer_pair const&) = default;
|
||||||
|
|
||||||
|
boost::asio::mutable_buffer&
|
||||||
|
operator[](int i) noexcept
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(i >= 0 && i < 2);
|
||||||
|
return b_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
begin() const noexcept
|
||||||
|
{
|
||||||
|
return &b_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
end() const noexcept
|
||||||
|
{
|
||||||
|
if(b_[1].size() > 0)
|
||||||
|
return &b_[2];
|
||||||
|
else
|
||||||
|
return &b_[1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_buffer_pair
|
||||||
|
{
|
||||||
|
boost::asio::const_buffer b_[2];
|
||||||
|
|
||||||
|
public:
|
||||||
|
using const_iterator =
|
||||||
|
boost::asio::const_buffer const*;
|
||||||
|
|
||||||
|
// workaround for buffers_iterator bug
|
||||||
|
using value_type =
|
||||||
|
boost::asio::const_buffer;
|
||||||
|
|
||||||
|
const_buffer_pair() = default;
|
||||||
|
const_buffer_pair(
|
||||||
|
const_buffer_pair const&) = default;
|
||||||
|
|
||||||
|
const_buffer_pair(
|
||||||
|
mutable_buffer_pair const& other)
|
||||||
|
: b_{other.b_[0], other.b_[1]}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::asio::const_buffer&
|
||||||
|
operator[](int i) noexcept
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(i >= 0 && i < 2);
|
||||||
|
return b_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
begin() const noexcept
|
||||||
|
{
|
||||||
|
return &b_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator
|
||||||
|
end() const noexcept
|
||||||
|
{
|
||||||
|
if(b_[1].size() > 0)
|
||||||
|
return &b_[2];
|
||||||
|
else
|
||||||
|
return &b_[1];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static_buffer_base(static_buffer_base const& other) = delete;
|
static_buffer_base(static_buffer_base const& other) = delete;
|
||||||
static_buffer_base& operator=(static_buffer_base const&) = delete;
|
static_buffer_base& operator=(static_buffer_base const&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The type used to represent the input sequence as a list of buffers.
|
|
||||||
using const_buffers_type =
|
|
||||||
std::array<boost::asio::const_buffer, 2>;
|
|
||||||
|
|
||||||
/// The type used to represent the output sequence as a list of buffers.
|
|
||||||
using mutable_buffers_type =
|
|
||||||
std::array<boost::asio::mutable_buffer, 2>;
|
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
This creates a dynamic buffer using the provided storage area.
|
This creates a dynamic buffer using the provided storage area.
|
||||||
@ -66,65 +160,108 @@ public:
|
|||||||
|
|
||||||
@param size The number of valid bytes pointed to by `p`.
|
@param size The number of valid bytes pointed to by `p`.
|
||||||
*/
|
*/
|
||||||
static_buffer_base(void* p, std::size_t size);
|
static_buffer_base(void* p, std::size_t size) noexcept;
|
||||||
|
|
||||||
/// Return the size of the input sequence.
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
/// The ConstBufferSequence used to represent the readable bytes.
|
||||||
|
using const_buffers_type = __implementation_defined__;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the readable bytes.
|
||||||
|
using mutable_data_type = __implementation_defined__;
|
||||||
|
|
||||||
|
/// The MutableBufferSequence used to represent the writable bytes.
|
||||||
|
using mutable_buffers_type = __implementation_defined__;
|
||||||
|
#else
|
||||||
|
using const_buffers_type = const_buffer_pair;
|
||||||
|
using mutable_data_type = mutable_buffer_pair;
|
||||||
|
using mutable_buffers_type = mutable_buffer_pair;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Returns the number of readable bytes.
|
||||||
std::size_t
|
std::size_t
|
||||||
size() const
|
size() const noexcept
|
||||||
{
|
{
|
||||||
return in_size_;
|
return in_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the maximum sum of the input and output sequence sizes.
|
/// Return the maximum number of bytes, both readable and writable, that can ever be held.
|
||||||
std::size_t
|
std::size_t
|
||||||
max_size() const
|
max_size() const noexcept
|
||||||
{
|
{
|
||||||
return capacity_;
|
return capacity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the maximum sum of input and output sizes that can be held without an allocation.
|
/// Return the maximum number of bytes, both readable and writable, that can be held without requiring an allocation.
|
||||||
std::size_t
|
std::size_t
|
||||||
capacity() const
|
capacity() const noexcept
|
||||||
{
|
{
|
||||||
return capacity_;
|
return capacity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get a list of buffers that represent the input sequence.
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
*/
|
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const;
|
data() const noexcept;
|
||||||
|
|
||||||
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
|
const_buffers_type
|
||||||
|
cdata() const noexcept
|
||||||
|
{
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a mutable list of buffers that represent the input sequence.
|
/// Returns a mutable buffer sequence representing the readable bytes
|
||||||
|
mutable_data_type
|
||||||
|
data() noexcept;
|
||||||
|
|
||||||
|
/** Returns a mutable buffer sequence representing writable bytes.
|
||||||
|
|
||||||
|
Returns a mutable buffer sequence representing the writable
|
||||||
|
bytes containing exactly `n` bytes of storage. Memory may be
|
||||||
|
reallocated as needed.
|
||||||
|
|
||||||
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The desired number of bytes in the returned buffer
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@throws std::length_error if `size() + n` exceeds `max_size()`.
|
||||||
*/
|
*/
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
mutable_data();
|
prepare(std::size_t n);
|
||||||
|
|
||||||
/** Get a list of buffers that represent the output sequence, with the given size.
|
/** Append writable bytes to the readable bytes.
|
||||||
|
|
||||||
@param size The number of bytes to request.
|
Appends n bytes from the start of the writable bytes to the
|
||||||
|
end of the readable bytes. The remainder of the writable bytes
|
||||||
|
are discarded. If n is greater than the number of writable
|
||||||
|
bytes, all writable bytes are appended to the readable bytes.
|
||||||
|
|
||||||
@throws std::length_error if the size would exceed the capacity.
|
All buffers sequences previously obtained using
|
||||||
*/
|
@ref data or @ref prepare are invalidated.
|
||||||
mutable_buffers_type
|
|
||||||
prepare(std::size_t size);
|
|
||||||
|
|
||||||
/** Move bytes from the output sequence to the input sequence.
|
@param n The number of bytes to append. If this number
|
||||||
|
is greater than the number of writable bytes, all
|
||||||
@param size The number of bytes to commit. If this is greater
|
writable bytes are appended.
|
||||||
than the size of the output sequence, the entire output
|
|
||||||
sequence is committed.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
commit(std::size_t size);
|
commit(std::size_t n) noexcept;
|
||||||
|
|
||||||
/** Remove bytes from the input sequence.
|
/** Remove bytes from beginning of the readable bytes.
|
||||||
|
|
||||||
@param size The number of bytes to consume. If this is greater
|
Removes n bytes from the beginning of the readable bytes.
|
||||||
than the size of the input sequence, the entire input sequence
|
|
||||||
is consumed.
|
All buffers sequences previously obtained using
|
||||||
|
@ref data or @ref prepare are invalidated.
|
||||||
|
|
||||||
|
@param n The number of bytes to remove. If this number
|
||||||
|
is greater than the number of readable bytes, all
|
||||||
|
readable bytes are removed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
consume(std::size_t size);
|
consume(std::size_t n) noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Constructor
|
/** Constructor
|
||||||
@ -147,7 +284,7 @@ protected:
|
|||||||
@param size The number of valid bytes pointed to by `p`.
|
@param size The number of valid bytes pointed to by `p`.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
reset(void* p, std::size_t size);
|
reset(void* p, std::size_t size) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -236,7 +236,7 @@ operator()(
|
|||||||
d.ws.rd_close_ = true;
|
d.ws.rd_close_ = true;
|
||||||
auto const mb = buffers_prefix(
|
auto const mb = buffers_prefix(
|
||||||
clamp(d.ws.rd_fh_.len),
|
clamp(d.ws.rd_fh_.len),
|
||||||
d.ws.rd_buf_.mutable_data());
|
d.ws.rd_buf_.data());
|
||||||
if(d.ws.rd_fh_.len > 0 && d.ws.rd_fh_.mask)
|
if(d.ws.rd_fh_.len > 0 && d.ws.rd_fh_.mask)
|
||||||
detail::mask_inplace(mb, d.ws.rd_key_);
|
detail::mask_inplace(mb, d.ws.rd_key_);
|
||||||
detail::read_close(d.ws.cr_, mb, d.ev);
|
detail::read_close(d.ws.cr_, mb, d.ev);
|
||||||
@ -381,7 +381,7 @@ close(close_reason const& cr, error_code& ec)
|
|||||||
rd_close_ = true;
|
rd_close_ = true;
|
||||||
auto const mb = buffers_prefix(
|
auto const mb = buffers_prefix(
|
||||||
clamp(rd_fh_.len),
|
clamp(rd_fh_.len),
|
||||||
rd_buf_.mutable_data());
|
rd_buf_.data());
|
||||||
if(rd_fh_.len > 0 && rd_fh_.mask)
|
if(rd_fh_.len > 0 && rd_fh_.mask)
|
||||||
detail::mask_inplace(mb, rd_key_);
|
detail::mask_inplace(mb, rd_key_);
|
||||||
detail::read_close(cr_, mb, result);
|
detail::read_close(cr_, mb, result);
|
||||||
|
@ -267,7 +267,7 @@ operator()(
|
|||||||
if(ws_.rd_fh_.len > 0 && ws_.rd_fh_.mask)
|
if(ws_.rd_fh_.len > 0 && ws_.rd_fh_.mask)
|
||||||
detail::mask_inplace(buffers_prefix(
|
detail::mask_inplace(buffers_prefix(
|
||||||
clamp(ws_.rd_fh_.len),
|
clamp(ws_.rd_fh_.len),
|
||||||
ws_.rd_buf_.mutable_data()),
|
ws_.rd_buf_.data()),
|
||||||
ws_.rd_key_);
|
ws_.rd_key_);
|
||||||
if(detail::is_control(ws_.rd_fh_.op))
|
if(detail::is_control(ws_.rd_fh_.op))
|
||||||
{
|
{
|
||||||
@ -454,14 +454,14 @@ operator()(
|
|||||||
ws_.rd_buf_.commit(bytes_transferred);
|
ws_.rd_buf_.commit(bytes_transferred);
|
||||||
if(ws_.rd_fh_.mask)
|
if(ws_.rd_fh_.mask)
|
||||||
detail::mask_inplace(buffers_prefix(clamp(
|
detail::mask_inplace(buffers_prefix(clamp(
|
||||||
ws_.rd_remain_), ws_.rd_buf_.mutable_data()),
|
ws_.rd_remain_), ws_.rd_buf_.data()),
|
||||||
ws_.rd_key_);
|
ws_.rd_key_);
|
||||||
}
|
}
|
||||||
if(ws_.rd_buf_.size() > 0)
|
if(ws_.rd_buf_.size() > 0)
|
||||||
{
|
{
|
||||||
// Copy from the read buffer.
|
// Copy from the read buffer.
|
||||||
// The mask was already applied.
|
// The mask was already applied.
|
||||||
bytes_transferred = buffer_copy(cb_,
|
bytes_transferred = boost::asio::buffer_copy(cb_,
|
||||||
ws_.rd_buf_.data(), clamp(ws_.rd_remain_));
|
ws_.rd_buf_.data(), clamp(ws_.rd_remain_));
|
||||||
auto const mb = buffers_prefix(
|
auto const mb = buffers_prefix(
|
||||||
bytes_transferred, cb_);
|
bytes_transferred, cb_);
|
||||||
@ -542,7 +542,7 @@ operator()(
|
|||||||
if(ws_.rd_fh_.mask)
|
if(ws_.rd_fh_.mask)
|
||||||
detail::mask_inplace(
|
detail::mask_inplace(
|
||||||
buffers_prefix(clamp(ws_.rd_remain_),
|
buffers_prefix(clamp(ws_.rd_remain_),
|
||||||
ws_.rd_buf_.mutable_data()), ws_.rd_key_);
|
ws_.rd_buf_.data()), ws_.rd_key_);
|
||||||
did_read_ = true;
|
did_read_ = true;
|
||||||
}
|
}
|
||||||
zlib::z_params zs;
|
zlib::z_params zs;
|
||||||
@ -1058,7 +1058,7 @@ loop:
|
|||||||
// of the buffer holding payload data.
|
// of the buffer holding payload data.
|
||||||
if(rd_fh_.len > 0 && rd_fh_.mask)
|
if(rd_fh_.len > 0 && rd_fh_.mask)
|
||||||
detail::mask_inplace(buffers_prefix(
|
detail::mask_inplace(buffers_prefix(
|
||||||
clamp(rd_fh_.len), rd_buf_.mutable_data()),
|
clamp(rd_fh_.len), rd_buf_.data()),
|
||||||
rd_key_);
|
rd_key_);
|
||||||
if(detail::is_control(rd_fh_.op))
|
if(detail::is_control(rd_fh_.op))
|
||||||
{
|
{
|
||||||
@ -1160,15 +1160,15 @@ loop:
|
|||||||
if(rd_fh_.mask)
|
if(rd_fh_.mask)
|
||||||
detail::mask_inplace(
|
detail::mask_inplace(
|
||||||
buffers_prefix(clamp(rd_remain_),
|
buffers_prefix(clamp(rd_remain_),
|
||||||
rd_buf_.mutable_data()), rd_key_);
|
rd_buf_.data()), rd_key_);
|
||||||
}
|
}
|
||||||
if(rd_buf_.size() > 0)
|
if(rd_buf_.size() > 0)
|
||||||
{
|
{
|
||||||
// Copy from the read buffer.
|
// Copy from the read buffer.
|
||||||
// The mask was already applied.
|
// The mask was already applied.
|
||||||
auto const bytes_transferred =
|
auto const bytes_transferred =
|
||||||
buffer_copy(buffers, rd_buf_.data(),
|
boost::asio::buffer_copy(buffers,
|
||||||
clamp(rd_remain_));
|
rd_buf_.data(), clamp(rd_remain_));
|
||||||
auto const mb = buffers_prefix(
|
auto const mb = buffers_prefix(
|
||||||
bytes_transferred, buffers);
|
bytes_transferred, buffers);
|
||||||
rd_remain_ -= bytes_transferred;
|
rd_remain_ -= bytes_transferred;
|
||||||
@ -1267,7 +1267,7 @@ loop:
|
|||||||
if(rd_fh_.mask)
|
if(rd_fh_.mask)
|
||||||
detail::mask_inplace(
|
detail::mask_inplace(
|
||||||
buffers_prefix(clamp(rd_remain_),
|
buffers_prefix(clamp(rd_remain_),
|
||||||
rd_buf_.mutable_data()), rd_key_);
|
rd_buf_.data()), rd_key_);
|
||||||
auto const in = buffers_prefix(
|
auto const in = buffers_prefix(
|
||||||
clamp(rd_remain_), buffers_front(
|
clamp(rd_remain_), buffers_front(
|
||||||
rd_buf_.data()));
|
rd_buf_.data()));
|
||||||
|
@ -17,17 +17,63 @@
|
|||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/test/test_allocator.hpp>
|
#include <boost/beast/test/test_allocator.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/buffers_iterator.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
boost::asio::is_dynamic_buffer<flat_buffer>::value);
|
|
||||||
|
|
||||||
class flat_buffer_test : public beast::unit_test::suite
|
class flat_buffer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_dynamic_buffer<
|
||||||
|
flat_buffer>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
flat_buffer::const_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
flat_buffer::mutable_data_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
flat_buffer::mutable_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(std::is_convertible<
|
||||||
|
flat_buffer::mutable_data_type,
|
||||||
|
flat_buffer::const_buffers_type>::value);
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
void
|
||||||
|
testMutableData()
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
DynamicBuffer const& cb = b;
|
||||||
|
ostream(b) << "Hello";
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(b.data())>::value);
|
||||||
|
std::for_each(
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::begin(b.data()),
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::end(b.data()),
|
||||||
|
[](char& c)
|
||||||
|
{
|
||||||
|
c = static_cast<char>(std::toupper(c));
|
||||||
|
});
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.data()) == "HELLO");
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.cdata()) == "HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testBuffer()
|
testBuffer()
|
||||||
{
|
{
|
||||||
@ -338,7 +384,6 @@ public:
|
|||||||
BEAST_EXPECT(b.capacity() >= 125);
|
BEAST_EXPECT(b.capacity() >= 125);
|
||||||
b.shrink_to_fit();
|
b.shrink_to_fit();
|
||||||
BEAST_EXPECT(b.capacity() == b.size());
|
BEAST_EXPECT(b.capacity() == b.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,6 +391,7 @@ public:
|
|||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testBuffer();
|
testBuffer();
|
||||||
|
testMutableData<flat_buffer>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,17 +15,64 @@
|
|||||||
#include <boost/beast/core/ostream.hpp>
|
#include <boost/beast/core/ostream.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/buffers_iterator.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
boost::asio::is_dynamic_buffer<flat_static_buffer_base>::value);
|
|
||||||
|
|
||||||
class flat_static_buffer_test : public beast::unit_test::suite
|
class flat_static_buffer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_dynamic_buffer<
|
||||||
|
flat_static_buffer_base>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
flat_static_buffer_base::const_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
flat_static_buffer_base::mutable_data_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
flat_static_buffer_base::mutable_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(std::is_convertible<
|
||||||
|
flat_static_buffer_base::mutable_data_type,
|
||||||
|
flat_static_buffer_base::const_buffers_type>::value);
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
void
|
||||||
|
testMutableData()
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
DynamicBuffer const& cb = b;
|
||||||
|
ostream(b) << "Hello";
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(b.data())>::value);
|
||||||
|
std::for_each(
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::begin(b.data()),
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::end(b.data()),
|
||||||
|
[](char& c)
|
||||||
|
{
|
||||||
|
c = static_cast<char>(std::toupper(c));
|
||||||
|
});
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.data()) == "HELLO");
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.cdata()) == "HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testStaticBuffer()
|
testStaticBuffer()
|
||||||
{
|
{
|
||||||
@ -226,6 +273,7 @@ public:
|
|||||||
{
|
{
|
||||||
testBuffer();
|
testBuffer();
|
||||||
testStaticBuffer();
|
testStaticBuffer();
|
||||||
|
testMutableData<flat_static_buffer<32>>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,20 +18,35 @@
|
|||||||
#include <boost/beast/test/test_allocator.hpp>
|
#include <boost/beast/test/test_allocator.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/asio/buffers_iterator.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cctype>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
boost::asio::is_dynamic_buffer<multi_buffer>::value);
|
|
||||||
|
|
||||||
class multi_buffer_test : public beast::unit_test::suite
|
class multi_buffer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_dynamic_buffer<
|
||||||
|
multi_buffer>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
multi_buffer::const_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
multi_buffer::mutable_data_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
multi_buffer::mutable_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(std::is_convertible<
|
||||||
|
multi_buffer::mutable_data_type,
|
||||||
|
multi_buffer::const_buffers_type>::value);
|
||||||
|
|
||||||
template<class Alloc1, class Alloc2>
|
template<class Alloc1, class Alloc2>
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
@ -60,6 +75,38 @@ public:
|
|||||||
u = std::forward<V>(v);
|
u = std::forward<V>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
void
|
||||||
|
testMutableData()
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
DynamicBuffer const& cb = b;
|
||||||
|
ostream(b) << "Hello";
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(b.data())>::value);
|
||||||
|
|
||||||
|
std::for_each(
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::begin(b.data()),
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::end(b.data()),
|
||||||
|
[](char& c)
|
||||||
|
{
|
||||||
|
c = static_cast<char>(std::toupper(c));
|
||||||
|
});
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.data()) == "HELLO");
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.cdata()) == "HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testMatrix1()
|
testMatrix1()
|
||||||
{
|
{
|
||||||
@ -588,6 +635,7 @@ public:
|
|||||||
testMatrix2();
|
testMatrix2();
|
||||||
testIterators();
|
testIterators();
|
||||||
testMembers();
|
testMembers();
|
||||||
|
testMutableData<multi_buffer>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
#include <boost/beast/core/ostream.hpp>
|
#include <boost/beast/core/ostream.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/buffers_iterator.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -26,6 +29,53 @@ BOOST_STATIC_ASSERT(
|
|||||||
class static_buffer_test : public beast::unit_test::suite
|
class static_buffer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_dynamic_buffer<
|
||||||
|
static_buffer_base>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
static_buffer_base::const_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
static_buffer_base::mutable_data_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
static_buffer_base::mutable_buffers_type>::value);
|
||||||
|
BOOST_STATIC_ASSERT(std::is_convertible<
|
||||||
|
static_buffer_base::mutable_data_type,
|
||||||
|
static_buffer_base::const_buffers_type>::value);
|
||||||
|
|
||||||
|
template<class DynamicBuffer>
|
||||||
|
void
|
||||||
|
testMutableData()
|
||||||
|
{
|
||||||
|
DynamicBuffer b;
|
||||||
|
DynamicBuffer const& cb = b;
|
||||||
|
ostream(b) << "Hello";
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.data())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_const_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value &&
|
||||||
|
! boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(cb.cdata())>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
boost::asio::is_mutable_buffer_sequence<
|
||||||
|
decltype(b.data())>::value);
|
||||||
|
std::for_each(
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::begin(b.data()),
|
||||||
|
boost::asio::buffers_iterator<decltype(b.data())>::end(b.data()),
|
||||||
|
[](char& c)
|
||||||
|
{
|
||||||
|
c = static_cast<char>(std::toupper(c));
|
||||||
|
});
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.data()) == "HELLO");
|
||||||
|
BEAST_EXPECT(buffers_to_string(b.cdata()) == "HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
testStaticBuffer()
|
testStaticBuffer()
|
||||||
{
|
{
|
||||||
@ -225,7 +275,8 @@ public:
|
|||||||
void run() override
|
void run() override
|
||||||
{
|
{
|
||||||
testBuffer();
|
testBuffer();
|
||||||
//testStaticBuffer();
|
testStaticBuffer();
|
||||||
|
testMutableData<static_buffer<32>>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user