mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
Refactor static_buffer:
* Improve tests and coverage * Add static_buffer_base::clear * Use BOOST_BEAST_DECL
This commit is contained in:
@ -18,6 +18,7 @@ Version 200
|
|||||||
* Add more tests for dynamic buffers
|
* Add more tests for dynamic buffers
|
||||||
* Tidy up multi_buffer
|
* Tidy up multi_buffer
|
||||||
* Refactor ostream
|
* Refactor ostream
|
||||||
|
* Refactor static_buffer
|
||||||
|
|
||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ public:
|
|||||||
{
|
{
|
||||||
b_[0] = *other.begin();
|
b_[0] = *other.begin();
|
||||||
b_[1] = *(other.begin() + 1);
|
b_[1] = *(other.begin() + 1);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers_pair(value_type b0, value_type b1)
|
buffers_pair(value_type b0, value_type b1)
|
||||||
|
@ -76,7 +76,18 @@ public:
|
|||||||
reset(p, n);
|
reset(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the number of readable and writable bytes to zero.
|
/** Clear the readable and writable bytes to zero.
|
||||||
|
|
||||||
|
This function causes the readable and writable bytes
|
||||||
|
to become empty. The capacity is not changed.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data or
|
||||||
|
@ref prepare become invalid.
|
||||||
|
|
||||||
|
@par Exception Safety
|
||||||
|
|
||||||
|
No-throw guarantee.
|
||||||
|
*/
|
||||||
BOOST_BEAST_DECL
|
BOOST_BEAST_DECL
|
||||||
void
|
void
|
||||||
clear() noexcept;
|
clear() noexcept;
|
||||||
|
@ -29,6 +29,15 @@ static_buffer_base(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
static_buffer_base::
|
||||||
|
clear() noexcept
|
||||||
|
{
|
||||||
|
in_off_ = 0;
|
||||||
|
in_size_ = 0;
|
||||||
|
out_size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto
|
auto
|
||||||
static_buffer_base::
|
static_buffer_base::
|
||||||
data() const noexcept ->
|
data() const noexcept ->
|
||||||
@ -73,7 +82,7 @@ prepare(std::size_t n) ->
|
|||||||
using net::mutable_buffer;
|
using net::mutable_buffer;
|
||||||
if(n > capacity_ - in_size_)
|
if(n > capacity_ - in_size_)
|
||||||
BOOST_THROW_EXCEPTION(std::length_error{
|
BOOST_THROW_EXCEPTION(std::length_error{
|
||||||
"buffer overflow"});
|
"static_buffer overflow"});
|
||||||
out_size_ = n;
|
out_size_ = n;
|
||||||
auto const out_off =
|
auto const out_off =
|
||||||
(in_off_ + in_size_) % capacity_;
|
(in_off_ + in_size_) % capacity_;
|
||||||
@ -117,17 +126,6 @@ consume(std::size_t n) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
static_buffer_base::
|
|
||||||
reset(void* p, std::size_t n) noexcept
|
|
||||||
{
|
|
||||||
begin_ = static_cast<char*>(p);
|
|
||||||
capacity_ = n;
|
|
||||||
in_off_ = 0;
|
|
||||||
in_size_ = 0;
|
|
||||||
out_size_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
|
@ -73,9 +73,25 @@ public:
|
|||||||
|
|
||||||
@param size The number of valid bytes pointed to by `p`.
|
@param size The number of valid bytes pointed to by `p`.
|
||||||
*/
|
*/
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
static_buffer_base(void* p, std::size_t size) noexcept;
|
static_buffer_base(void* p, std::size_t size) noexcept;
|
||||||
|
|
||||||
|
/** Clear the readable and writable bytes to zero.
|
||||||
|
|
||||||
|
This function causes the readable and writable bytes
|
||||||
|
to become empty. The capacity is not changed.
|
||||||
|
|
||||||
|
Buffer sequences previously obtained using @ref data or
|
||||||
|
@ref prepare become invalid.
|
||||||
|
|
||||||
|
@par Exception Safety
|
||||||
|
|
||||||
|
No-throw guarantee.
|
||||||
|
*/
|
||||||
|
BOOST_BEAST_DECL
|
||||||
|
void
|
||||||
|
clear() noexcept;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
#if BOOST_BEAST_DOXYGEN
|
#if BOOST_BEAST_DOXYGEN
|
||||||
@ -115,7 +131,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a constant buffer sequence representing the readable bytes
|
/// Returns a constant buffer sequence representing the readable bytes
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
const_buffers_type
|
const_buffers_type
|
||||||
data() const noexcept;
|
data() const noexcept;
|
||||||
|
|
||||||
@ -127,7 +143,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable buffer sequence representing the readable bytes
|
/// Returns a mutable buffer sequence representing the readable bytes
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
mutable_data_type
|
mutable_data_type
|
||||||
data() noexcept;
|
data() noexcept;
|
||||||
|
|
||||||
@ -149,7 +165,7 @@ public:
|
|||||||
|
|
||||||
Strong guarantee.
|
Strong guarantee.
|
||||||
*/
|
*/
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
mutable_buffers_type
|
mutable_buffers_type
|
||||||
prepare(std::size_t n);
|
prepare(std::size_t n);
|
||||||
|
|
||||||
@ -171,7 +187,7 @@ public:
|
|||||||
|
|
||||||
No-throw guarantee.
|
No-throw guarantee.
|
||||||
*/
|
*/
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
void
|
void
|
||||||
commit(std::size_t n) noexcept;
|
commit(std::size_t n) noexcept;
|
||||||
|
|
||||||
@ -190,37 +206,9 @@ public:
|
|||||||
|
|
||||||
No-throw guarantee.
|
No-throw guarantee.
|
||||||
*/
|
*/
|
||||||
inline
|
BOOST_BEAST_DECL
|
||||||
void
|
void
|
||||||
consume(std::size_t n) noexcept;
|
consume(std::size_t n) noexcept;
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Constructor
|
|
||||||
|
|
||||||
The buffer will be in an undefined state. It is necessary
|
|
||||||
for the derived class to call @ref reset in order to
|
|
||||||
initialize the object.
|
|
||||||
*/
|
|
||||||
static_buffer_base() = default;
|
|
||||||
|
|
||||||
/** Reset the pointed-to buffer.
|
|
||||||
|
|
||||||
This function resets the internal state to the buffer provided.
|
|
||||||
All input and output sequences are invalidated. This function
|
|
||||||
allows the derived class to construct its members before
|
|
||||||
initializing the static buffer.
|
|
||||||
|
|
||||||
@param p A pointer to valid storage of at least `n` bytes.
|
|
||||||
|
|
||||||
@param size The number of valid bytes pointed to by `p`.
|
|
||||||
|
|
||||||
@par Exception Safety
|
|
||||||
|
|
||||||
No-throw guarantee.
|
|
||||||
*/
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
reset(void* p, std::size_t size) noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -261,15 +249,15 @@ class static_buffer : public static_buffer_base
|
|||||||
char buf_[N];
|
char buf_[N];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
|
||||||
static_buffer(static_buffer const&) noexcept;
|
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
static_buffer() noexcept
|
static_buffer() noexcept
|
||||||
: static_buffer_base(buf_, N)
|
: static_buffer_base(buf_, N)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
static_buffer(static_buffer const&) noexcept;
|
||||||
|
|
||||||
/// Assignment
|
/// Assignment
|
||||||
static_buffer& operator=(static_buffer const&) noexcept;
|
static_buffer& operator=(static_buffer const&) noexcept;
|
||||||
|
|
||||||
|
@ -24,27 +24,17 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_dynamic_buffer<static_buffer_base>::value);
|
|
||||||
|
|
||||||
class static_buffer_test : public beast::unit_test::suite
|
class static_buffer_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BOOST_STATIC_ASSERT(
|
BOOST_STATIC_ASSERT(
|
||||||
net::is_dynamic_buffer<
|
is_mutable_dynamic_buffer<
|
||||||
|
static_buffer<13>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
is_mutable_dynamic_buffer<
|
||||||
static_buffer_base>::value);
|
static_buffer_base>::value);
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_const_buffer_sequence<
|
|
||||||
static_buffer_base::const_buffers_type>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_mutable_buffer_sequence<
|
|
||||||
static_buffer_base::mutable_data_type>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::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);
|
|
||||||
#if ! defined( BOOST_LIBSTDCXX_VERSION ) || BOOST_LIBSTDCXX_VERSION >= 50000
|
#if ! defined( BOOST_LIBSTDCXX_VERSION ) || BOOST_LIBSTDCXX_VERSION >= 50000
|
||||||
# ifndef BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
|
# ifndef BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
|
||||||
BOOST_STATIC_ASSERT(std::is_trivially_copyable<
|
BOOST_STATIC_ASSERT(std::is_trivially_copyable<
|
||||||
@ -54,147 +44,18 @@ public:
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<class DynamicBuffer>
|
|
||||||
void
|
void
|
||||||
testMutableData()
|
testDynamicBuffer()
|
||||||
{
|
{
|
||||||
DynamicBuffer b;
|
static_buffer<13> b;
|
||||||
DynamicBuffer const& cb = b;
|
test_dynamic_buffer(*this, b);
|
||||||
ostream(b) << "Hello";
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_const_buffer_sequence<
|
|
||||||
decltype(cb.data())>::value &&
|
|
||||||
! net::is_mutable_buffer_sequence<
|
|
||||||
decltype(cb.data())>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_const_buffer_sequence<
|
|
||||||
decltype(cb.cdata())>::value &&
|
|
||||||
! net::is_mutable_buffer_sequence<
|
|
||||||
decltype(cb.cdata())>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
net::is_mutable_buffer_sequence<
|
|
||||||
decltype(b.data())>::value);
|
|
||||||
std::for_each(
|
|
||||||
net::buffers_iterator<decltype(b.data())>::begin(b.data()),
|
|
||||||
net::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()
|
testMembers()
|
||||||
{
|
{
|
||||||
using net::buffer;
|
|
||||||
using net::buffer_size;
|
using net::buffer_size;
|
||||||
char buf[12];
|
|
||||||
std::string const s = "Hello, world";
|
|
||||||
BEAST_EXPECT(s.size() == sizeof(buf));
|
|
||||||
for(std::size_t i = 1; i < 4; ++i) {
|
|
||||||
for(std::size_t j = 1; j < 4; ++j) {
|
|
||||||
for(std::size_t x = 1; x < 4; ++x) {
|
|
||||||
for(std::size_t y = 1; y < 4; ++y) {
|
|
||||||
for(std::size_t t = 1; t < 4; ++ t) {
|
|
||||||
for(std::size_t u = 1; u < 4; ++ u) {
|
|
||||||
std::size_t z = sizeof(buf) - (x + y);
|
|
||||||
std::size_t v = sizeof(buf) - (t + u);
|
|
||||||
{
|
|
||||||
std::memset(buf, 0, sizeof(buf));
|
|
||||||
static_buffer<sizeof(buf)> ba;
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(z);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == z);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(0);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(y);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == y);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(x);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == x);
|
|
||||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
|
||||||
}
|
|
||||||
BEAST_EXPECT(ba.size() == x);
|
|
||||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(x);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == x);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(0);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(z);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == z);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(y);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == y);
|
|
||||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
|
||||||
}
|
|
||||||
ba.commit(1);
|
|
||||||
BEAST_EXPECT(ba.size() == x + y);
|
|
||||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(x);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == x);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(y);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == y);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(0);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(z);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == z);
|
|
||||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
|
||||||
}
|
|
||||||
ba.commit(2);
|
|
||||||
BEAST_EXPECT(ba.size() == x + y + z);
|
|
||||||
BEAST_EXPECT(buffer_size(ba.data()) == ba.size());
|
|
||||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s);
|
|
||||||
ba.consume(t);
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(0);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == 0);
|
|
||||||
}
|
|
||||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t, std::string::npos));
|
|
||||||
ba.consume(u);
|
|
||||||
BEAST_EXPECT(buffers_to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
|
||||||
ba.consume(v);
|
|
||||||
BEAST_EXPECT(buffers_to_string(ba.data()) == "");
|
|
||||||
ba.consume(1);
|
|
||||||
{
|
|
||||||
auto d = ba.prepare(0);
|
|
||||||
BEAST_EXPECT(buffer_size(d) == 0);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ba.prepare(ba.capacity() - ba.size() + 1);
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
pass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}}}}}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
testBuffer()
|
|
||||||
{
|
|
||||||
string_view const s = "Hello, world!";
|
string_view const s = "Hello, world!";
|
||||||
|
|
||||||
// static_buffer_base
|
// static_buffer_base
|
||||||
@ -203,8 +64,9 @@ public:
|
|||||||
static_buffer_base b{buf, sizeof(buf)};
|
static_buffer_base b{buf, sizeof(buf)};
|
||||||
ostream(b) << s;
|
ostream(b) << s;
|
||||||
BEAST_EXPECT(buffers_to_string(b.data()) == s);
|
BEAST_EXPECT(buffers_to_string(b.data()) == s);
|
||||||
b.consume(b.size());
|
b.clear();
|
||||||
BEAST_EXPECT(buffers_to_string(b.data()) == "");
|
BEAST_EXPECT(b.size() == 0);
|
||||||
|
BEAST_EXPECT(buffer_size(b.data()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static_buffer
|
// static_buffer
|
||||||
@ -277,13 +139,53 @@ public:
|
|||||||
}
|
}
|
||||||
(b.base());
|
(b.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This exercises the wrap-around cases
|
||||||
|
// for the circular buffer representation
|
||||||
|
{
|
||||||
|
static_buffer<5> b;
|
||||||
|
{
|
||||||
|
auto const mb = b.prepare(5);
|
||||||
|
BEAST_EXPECT(buffers_length(mb) == 1);
|
||||||
|
}
|
||||||
|
b.commit(4);
|
||||||
|
BEAST_EXPECT(buffers_length(b.data()) == 1);
|
||||||
|
BEAST_EXPECT(buffers_length(b.cdata()) == 1);
|
||||||
|
b.consume(3);
|
||||||
|
{
|
||||||
|
auto const mb = b.prepare(3);
|
||||||
|
BEAST_EXPECT(buffers_length(mb) == 2);
|
||||||
|
auto it1 = mb.begin();
|
||||||
|
auto it2 = std::next(it1);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
net::const_buffer(*it1).data() >
|
||||||
|
net::const_buffer(*it2).data());
|
||||||
|
}
|
||||||
|
b.commit(2);
|
||||||
|
{
|
||||||
|
auto const mb = b.data();
|
||||||
|
auto it1 = mb.begin();
|
||||||
|
auto it2 = std::next(it1);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
net::const_buffer(*it1).data() >
|
||||||
|
net::const_buffer(*it2).data());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto const cb = b.cdata();
|
||||||
|
auto it1 = cb.begin();
|
||||||
|
auto it2 = std::next(it1);
|
||||||
|
BEAST_EXPECT(
|
||||||
|
net::const_buffer(*it1).data() >
|
||||||
|
net::const_buffer(*it2).data());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() override
|
void
|
||||||
|
run() override
|
||||||
{
|
{
|
||||||
testBuffer();
|
testDynamicBuffer();
|
||||||
testStaticBuffer();
|
testMembers();
|
||||||
testMutableData<static_buffer<32>>();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user