Refactor storage

This commit is contained in:
Vinnie Falco 2019-10-23 14:12:01 -07:00
parent e73d4886ea
commit b82419c1a4
9 changed files with 360 additions and 442 deletions

View File

@ -52,7 +52,7 @@ public:
} }
void* void*
allocate( do_allocate(
std::size_t n, std::size_t n,
std::size_t align) override std::size_t align) override
{ {
@ -60,7 +60,7 @@ public:
} }
void void
deallocate( do_deallocate(
void* p, void* p,
std::size_t n, std::size_t n,
std::size_t align) noexcept override std::size_t align) noexcept override
@ -69,7 +69,7 @@ public:
} }
bool bool
is_equal(storage const& other) const noexcept override do_is_equal(storage const& other) const noexcept override
{ {
return this == dynamic_cast< return this == dynamic_cast<
pool_storage const*>(&other); pool_storage const*>(&other);

View File

@ -19,73 +19,6 @@ namespace json {
//---------------------------------------------------------- //----------------------------------------------------------
namespace detail {
storage_ptr const&
global_storage() noexcept
{
struct builtin : storage
{
void*
allocate(
std::size_t n,
std::size_t) override
{
return std::allocator<
char>().allocate(n);
}
void
deallocate(
void* p,
std::size_t n,
std::size_t) noexcept override
{
std::allocator<
char>().deallocate(
static_cast<char*>(p), n);
}
bool
is_equal(storage const& other)
const noexcept override
{
(void)other;
BOOST_JSON_ASSERT(dynamic_cast<
builtin const*>(&other) == nullptr);
return false;
}
};
static storage_ptr const sp =
make_storage<builtin>();
return sp;
}
inline
storage_ptr&
raw_default_storage() noexcept
{
static storage_ptr sp =
global_storage();
return sp;
}
} // detail
storage_ptr
default_storage() noexcept
{
return detail::raw_default_storage();
}
void
default_storage(storage_ptr sp) noexcept
{
detail::raw_default_storage() = std::move(sp);
}
//----------------------------------------------------------
void void
storage:: storage::
addref() noexcept addref() noexcept
@ -108,6 +41,48 @@ storage() noexcept
{ {
} }
//----------------------------------------------------------
storage_ptr const&
default_storage() noexcept
{
struct builtin : storage
{
void*
do_allocate(
std::size_t n,
std::size_t) override
{
return std::allocator<
char>().allocate(n);
}
void
do_deallocate(
void* p,
std::size_t n,
std::size_t) noexcept override
{
std::allocator<
char>().deallocate(
static_cast<char*>(p), n);
}
bool
do_is_equal(storage const& other)
const noexcept override
{
(void)other;
BOOST_JSON_ASSERT(dynamic_cast<
builtin const*>(&other) == nullptr);
return false;
}
};
static storage_ptr const sp =
make_storage<builtin>();
return sp;
}
} // json } // json
} // boost } // boost

View File

@ -136,11 +136,12 @@ insert(
}; };
impl tmp; impl tmp;
// We use the global storage since
// it is a temporary deallocated here.
tmp.construct(first, last, tmp.construct(first, last,
detail::global_storage(), default_storage(),
iter_cat<InputIt>{}); iter_cat<InputIt>{});
cleanup c{tmp, cleanup c{tmp, default_storage()};
detail::global_storage()};
auto const off = pos - s_.data(); auto const off = pos - s_.data();
traits_type::copy( traits_type::copy(
s_.insert(off, tmp.size, sp_), s_.insert(off, tmp.size, sp_),
@ -219,11 +220,12 @@ append(
}; };
impl tmp; impl tmp;
// We use the global storage since
// it is a temporary deallocated here.
tmp.construct(first, last, tmp.construct(first, last,
detail::global_storage(), default_storage(),
std::input_iterator_tag{}); std::input_iterator_tag{});
cleanup c{tmp, cleanup c{tmp, default_storage()};
detail::global_storage()};
traits_type::copy( traits_type::copy(
s_.append(tmp.size, sp_), s_.append(tmp.size, sp_),
tmp.data(), tmp.size); tmp.data(), tmp.size);

View File

@ -47,25 +47,31 @@ public:
virtual virtual
~storage() = default; ~storage() = default;
virtual
void* void*
allocate( allocate(
std::size_t n, std::size_t n,
std::size_t align = std::size_t align =
max_align) = 0; max_align)
{
return do_allocate(n, align);
}
virtual
void void
deallocate( deallocate(
void* p, void* p,
std::size_t n, std::size_t n,
std::size_t align = std::size_t align =
max_align) noexcept = 0; max_align)
{
return do_deallocate(p, n, align);
}
virtual
bool bool
is_equal( is_equal(
storage const& other) const noexcept = 0; storage const& other) const noexcept
{
return do_is_equal(other);
}
friend friend
bool bool
@ -84,6 +90,26 @@ public:
{ {
return &lhs != &rhs && ! lhs.is_equal(rhs); return &lhs != &rhs && ! lhs.is_equal(rhs);
} }
protected:
virtual
void*
do_allocate(
std::size_t n,
std::size_t align) = 0;
virtual
void
do_deallocate(
void* p,
std::size_t n,
std::size_t align) noexcept = 0;
virtual
bool
do_is_equal(
storage const& other) const noexcept = 0;
}; };
//---------------------------------------------------------- //----------------------------------------------------------
@ -481,12 +507,12 @@ using storage_ptr = basic_storage_ptr<storage>;
//---------------------------------------------------------- //----------------------------------------------------------
/** Return a pointer to the current default storage /** Return a pointer to the default storage
This function returns a pointer to the current default storage. This function returns the default storage, which is
This default storage is used when constructing used when constructing a container without explicitly
any @ref value, @ref object, @ref array, or @ref string specifying the storage. The default storage uses the
and the storage is not explicitly specified. global allocator, equivalent to `std::allocator<char>`.
@par Complexity @par Complexity
@ -498,38 +524,12 @@ using storage_ptr = basic_storage_ptr<storage>;
@par Thread Safety @par Thread Safety
May not be called concurrently with May be called concurrently.
`void default_storage(storage_ptr)`.
*/ */
BOOST_JSON_DECL BOOST_JSON_DECL
storage_ptr storage_ptr const&
default_storage() noexcept; default_storage() noexcept;
/** Set the current default storage
This function changes the current default storage pointer.
This default storage is used when constructing
any @ref value, @ref object, @ref array, or @ref string
and the storage is not explicitly specified.
@par Complexity
Constant.
@par Exception Safety
No-throw guarantee.
@par Thread Safety
May not be called concurrently with
`void default_storage()` or
`void default_storage(storage_ptr)`.
*/
BOOST_JSON_DECL
void
default_storage(storage_ptr sp) noexcept;
} // json } // json
} // boost } // boost

View File

@ -62,7 +62,6 @@ public:
// array() // array()
{ {
scoped_fail_storage fs;
array a; array a;
BEAST_EXPECT(a.empty()); BEAST_EXPECT(a.empty());
BEAST_EXPECT(a.size() == 0); BEAST_EXPECT(a.size() == 0);
@ -70,7 +69,6 @@ public:
// array(storage_ptr) // array(storage_ptr)
{ {
scoped_fail_storage fs;
array a(default_storage()); array a(default_storage());
check_storage(a, default_storage()); check_storage(a, default_storage());
} }
@ -103,19 +101,20 @@ public:
// array(size_type, storage) // array(size_type, storage)
{ {
// default storage // default storage
fail_loop([&]
{ {
array a(3); array a(3);
BEAST_EXPECT(a.size() == 3); BEAST_EXPECT(a.size() == 3);
for(auto const& v : a) for(auto const& v : a)
BEAST_EXPECT(v.is_null()); BEAST_EXPECT(v.is_null());
check_storage(a, default_storage()); check_storage(a, default_storage());
}); }
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
{ {
array a(3, sp); array a(3, sp);
BEAST_EXPECT(a.size() == 3); BEAST_EXPECT(a.size() == 3);
for(auto const& v : a)
BEAST_EXPECT(v.is_null());
check_storage(a, sp); check_storage(a, sp);
}); });
} }
@ -123,7 +122,6 @@ public:
// array(InputIt, InputIt, storage) // array(InputIt, InputIt, storage)
{ {
// default storage // default storage
fail_loop([&]
{ {
init_list init{ 0, 1, str_, 3, 4 }; init_list init{ 0, 1, str_, 3, 4 };
array a(init.begin(), init.end()); array a(init.begin(), init.end());
@ -133,7 +131,7 @@ public:
BEAST_EXPECT(a[2].as_string() == str_); BEAST_EXPECT(a[2].as_string() == str_);
BEAST_EXPECT(a[3].as_number() == 3); BEAST_EXPECT(a[3].as_number() == 3);
BEAST_EXPECT(a[4].as_number() == 4); BEAST_EXPECT(a[4].as_number() == 4);
}); }
// forward iterator // forward iterator
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
@ -169,14 +167,13 @@ public:
a2 = a1; a2 = a1;
} }
fail_loop([&]
{ {
init_list init{ 1, true, str_ }; init_list init{ 1, true, str_ };
array a1(init.begin(), init.end()); array a1(init.begin(), init.end());
array a2(a1); array a2(a1);
check(a2); check(a2);
check_storage(a2, default_storage()); check_storage(a2, default_storage());
}); }
} }
// array(array const&, storage) // array(array const&, storage)
@ -185,7 +182,7 @@ public:
init_list init{ 1, true, str_ }; init_list init{ 1, true, str_ };
array a1(init.begin(), init.end()); array a1(init.begin(), init.end());
array a2(a1, sp); array a2(a1, sp);
BEAST_EXPECT(a2.size() == 3); check(a2);
check_storage(a2, sp); check_storage(a2, sp);
}); });
@ -357,7 +354,6 @@ public:
// at(pos) // at(pos)
{ {
array a({1, true, str_}); array a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.at(0).is_number()); BEAST_EXPECT(a.at(0).is_number());
BEAST_EXPECT(a.at(1).is_bool()); BEAST_EXPECT(a.at(1).is_bool());
BEAST_EXPECT(a.at(2).is_string()); BEAST_EXPECT(a.at(2).is_string());
@ -375,7 +371,6 @@ public:
// at(pos) const // at(pos) const
{ {
array const a({1, true, str_}); array const a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.at(0).is_number()); BEAST_EXPECT(a.at(0).is_number());
BEAST_EXPECT(a.at(1).is_bool()); BEAST_EXPECT(a.at(1).is_bool());
BEAST_EXPECT(a.at(2).is_string()); BEAST_EXPECT(a.at(2).is_string());
@ -393,7 +388,6 @@ public:
// operator[&](size_type) // operator[&](size_type)
{ {
array a({1, true, str_}); array a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a[0].is_number()); BEAST_EXPECT(a[0].is_number());
BEAST_EXPECT(a[1].is_bool()); BEAST_EXPECT(a[1].is_bool());
BEAST_EXPECT(a[2].is_string()); BEAST_EXPECT(a[2].is_string());
@ -402,7 +396,6 @@ public:
// operator[&](size_type) const // operator[&](size_type) const
{ {
array const a({1, true, str_}); array const a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a[0].is_number()); BEAST_EXPECT(a[0].is_number());
BEAST_EXPECT(a[1].is_bool()); BEAST_EXPECT(a[1].is_bool());
BEAST_EXPECT(a[2].is_string()); BEAST_EXPECT(a[2].is_string());
@ -411,28 +404,24 @@ public:
// front() // front()
{ {
array a({1, true, str_}); array a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.front().is_number()); BEAST_EXPECT(a.front().is_number());
} }
// front() const // front() const
{ {
array const a({1, true, str_}); array const a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.front().is_number()); BEAST_EXPECT(a.front().is_number());
} }
// back() // back()
{ {
array a({1, true, str_}); array a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.back().is_string()); BEAST_EXPECT(a.back().is_string());
} }
// back() const // back() const
{ {
array const a({1, true, str_}); array const a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.back().is_string()); BEAST_EXPECT(a.back().is_string());
} }
@ -440,7 +429,6 @@ public:
{ {
{ {
array a({1, true, str_}); array a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.data() == &a[0]); BEAST_EXPECT(a.data() == &a[0]);
} }
{ {
@ -452,7 +440,6 @@ public:
{ {
{ {
array const a({1, true, str_}); array const a({1, true, str_});
scoped_fail_storage fs;
BEAST_EXPECT(a.data() == &a[0]); BEAST_EXPECT(a.data() == &a[0]);
} }
{ {
@ -763,7 +750,6 @@ public:
// input iterator (empty range) // input iterator (empty range)
{ {
scoped_fail_storage fs;
std::initializer_list<value> init; std::initializer_list<value> init;
array a; array a;
a.insert(a.begin(), a.insert(a.begin(),
@ -948,7 +934,6 @@ public:
{ {
array a1({1, true, str_}); array a1({1, true, str_});
array a2 = {1.}; array a2 = {1.};
scoped_fail_storage fs;
a1.swap(a2); a1.swap(a2);
check(a2); check(a2);
BEAST_EXPECT(a1.size() == 1); BEAST_EXPECT(a1.size() == 1);

View File

@ -120,7 +120,6 @@ public:
// object() // object()
{ {
scoped_fail_storage fs;
object o; object o;
BEAST_EXPECT(o.empty()); BEAST_EXPECT(o.empty());
BEAST_EXPECT(o.size() == 0); BEAST_EXPECT(o.size() == 0);
@ -135,13 +134,12 @@ public:
}); });
// object(size_type) // object(size_type)
fail_loop([&]
{ {
object o(50); object o(50);
BEAST_EXPECT(o.empty()); BEAST_EXPECT(o.empty());
BEAST_EXPECT(o.size() == 0); BEAST_EXPECT(o.size() == 0);
BEAST_EXPECT(o.capacity() == 53); BEAST_EXPECT(o.capacity() == 53);
}); }
// object(size_type, storage_ptr) // object(size_type, storage_ptr)
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
@ -155,7 +153,6 @@ public:
// object(InputIt, InputIt, size_type, storage_ptr) // object(InputIt, InputIt, size_type, storage_ptr)
{ {
fail_loop([&]
{ {
std::initializer_list<std::pair< std::initializer_list<std::pair<
string_view, value>> init = { string_view, value>> init = {
@ -164,9 +161,8 @@ public:
{"c", "hello"}}; {"c", "hello"}};
object o(init.begin(), init.end()); object o(init.begin(), init.end());
check(o, 3); check(o, 3);
}); }
fail_loop([&]
{ {
std::initializer_list<std::pair< std::initializer_list<std::pair<
string_view, value>> init = { string_view, value>> init = {
@ -175,7 +171,7 @@ public:
{"c", "hello"}}; {"c", "hello"}};
object o(init.begin(), init.end(), 5); object o(init.begin(), init.end(), 5);
check(o, 7); check(o, 7);
}); }
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
{ {
@ -203,7 +199,6 @@ public:
check(obj1, 3); check(obj1, 3);
auto const sp = auto const sp =
default_storage(); default_storage();
scoped_fail_storage fs;
object obj2(std::move(obj1)); object obj2(std::move(obj1));
BEAST_EXPECT(obj1.empty()); BEAST_EXPECT(obj1.empty());
BEAST_EXPECT(obj1.size() == 0); BEAST_EXPECT(obj1.size() == 0);
@ -219,7 +214,6 @@ public:
{"b", true}, {"b", true},
{"c", "hello"} {"c", "hello"}
}); });
scoped_fail_storage fs;
object obj2(pilfer(obj1)); object obj2(pilfer(obj1));
BEAST_EXPECT( BEAST_EXPECT(
obj1.get_storage() == nullptr); obj1.get_storage() == nullptr);
@ -247,7 +241,6 @@ public:
}); });
// object(object const&) // object(object const&)
fail_loop([&]
{ {
object obj1({ object obj1({
{"a", 1}, {"a", 1},
@ -257,7 +250,7 @@ public:
object obj2(obj1); object obj2(obj1);
BEAST_EXPECT(! obj1.empty()); BEAST_EXPECT(! obj1.empty());
check(obj2, 3); check(obj2, 3);
}); }
// object(object const&, storage_ptr) // object(object const&, storage_ptr)
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
@ -274,7 +267,6 @@ public:
}); });
// object(initializer_list) // object(initializer_list)
fail_loop([&]
{ {
object o({ object o({
{"a", 1}, {"a", 1},
@ -282,10 +274,9 @@ public:
{"c", "hello"} {"c", "hello"}
}); });
check(o, 3); check(o, 3);
}); }
// object(initializer_list, size_type) // object(initializer_list, size_type)
fail_loop([&]
{ {
object o({ object o({
{"a", 1}, {"a", 1},
@ -294,7 +285,7 @@ public:
}, },
5); 5);
check(o, 7); check(o, 7);
}); }
// object(initializer_list, storage_ptr) // object(initializer_list, storage_ptr)
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
@ -310,6 +301,7 @@ public:
}); });
// object(initializer_list, size_type, storage_ptr) // object(initializer_list, size_type, storage_ptr)
fail_loop([&](storage_ptr const& sp)
{ {
object o({ object o({
{"a", 1}, {"a", 1},
@ -320,7 +312,7 @@ public:
BEAST_EXPECT( BEAST_EXPECT(
*o.get_storage() == *sp); *o.get_storage() == *sp);
check(o, 7); check(o, 7);
} });
// operator=(object&&) // operator=(object&&)
{ {
@ -357,7 +349,6 @@ public:
// operator=(object const&) // operator=(object const&)
{ {
fail_loop([&]
{ {
object obj1({ object obj1({
{"a", 1}, {"a", 1},
@ -371,7 +362,7 @@ public:
default_storage()); default_storage());
check_storage(obj2, check_storage(obj2,
default_storage()); default_storage());
}); }
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
{ {
@ -391,7 +382,6 @@ public:
// operator=(initializer_list) // operator=(initializer_list)
{ {
fail_loop([&]
{ {
object o; object o;
o = { o = {
@ -401,7 +391,7 @@ public:
check(o, 3); check(o, 3);
check_storage(o, check_storage(o,
default_storage()); default_storage());
}); }
fail_loop([&](storage_ptr const& sp) fail_loop([&](storage_ptr const& sp)
{ {
@ -515,9 +505,9 @@ public:
} }
// insert(value_type&&) // insert(value_type&&)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
auto v = object::value_type("a", 1); auto v = object::value_type("a", 1);
auto result = o.insert(std::move(v)); auto result = o.insert(std::move(v));
BEAST_EXPECT(result.second); BEAST_EXPECT(result.second);
@ -530,9 +520,9 @@ public:
}); });
// insert(value_type const&) // insert(value_type const&)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
auto v = object::value_type("a", 1); auto v = object::value_type("a", 1);
auto result = o.insert(v); auto result = o.insert(v);
BEAST_EXPECT(! v.second.is_null()); BEAST_EXPECT(! v.second.is_null());
@ -546,9 +536,9 @@ public:
// insert(P&&) // insert(P&&)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
auto result = o.insert( auto result = o.insert(
std::make_pair("x", 1)); std::make_pair("x", 1));
BEAST_EXPECT(result.second); BEAST_EXPECT(result.second);
@ -556,9 +546,9 @@ public:
BEAST_EXPECT(result.first->second.as_number() == 1); BEAST_EXPECT(result.first->second.as_number() == 1);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
auto const p = std::make_pair("x", 1); auto const p = std::make_pair("x", 1);
auto result = o.insert(p); auto result = o.insert(p);
BEAST_EXPECT(result.second); BEAST_EXPECT(result.second);
@ -568,9 +558,9 @@ public:
} }
// insert(before, value_type const&) // insert(before, value_type const&)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("c", "hello"); o.emplace("c", "hello");
object::value_type const p("b", true); object::value_type const p("b", true);
@ -579,9 +569,9 @@ public:
}); });
// insert(before, value_type&&) // insert(before, value_type&&)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("c", "hello"); o.emplace("c", "hello");
o.insert(o.find("c"), { "b", true }); o.insert(o.find("c"), { "b", true });
@ -590,9 +580,9 @@ public:
// insert(before, P&&) // insert(before, P&&)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("c", "hello"); o.emplace("c", "hello");
o.insert(o.find("c"), o.insert(o.find("c"),
@ -600,9 +590,9 @@ public:
check(o, 3); check(o, 3);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("c", "hello"); o.emplace("c", "hello");
auto const p = auto const p =
@ -613,34 +603,34 @@ public:
} }
// insert(InputIt, InputIt) // insert(InputIt, InputIt)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
std::initializer_list<std::pair< std::initializer_list<std::pair<
string_view, value>> init = { string_view, value>> init = {
{"a", 1}, {"a", 1},
{"b", true}, {"b", true},
{"c", "hello"}}; {"c", "hello"}};
object o; object o(sp);
o.insert(init.begin(), init.end()); o.insert(init.begin(), init.end());
check(o, 3); check(o, 3);
}); });
// insert(InputIt, InputIt) // insert(InputIt, InputIt)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
std::initializer_list<std::pair< std::initializer_list<std::pair<
string_view, value>> init = { string_view, value>> init = {
{"b", true}}; {"b", true}};
object o({{"a", 1}, {"c", "hello"}}); object o({{"a", 1}, {"c", "hello"}}, sp);
o.insert(++o.begin(), o.insert(++o.begin(),
init.begin(), init.end()); init.begin(), init.end());
check(o, 3); check(o, 3);
}); });
// insert(initializer_list) // insert(initializer_list)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.insert({ o.insert({
{ "b", true }, { "b", true },
@ -649,9 +639,9 @@ public:
}); });
// insert(before, initializer_list) // insert(before, initializer_list)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("c", "hello"); o.emplace("c", "hello");
o.insert( o.insert(
o.find("c"), o.find("c"),
@ -664,35 +654,35 @@ public:
// insert_or_assign(key, o); // insert_or_assign(key, o);
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({{"a", 1}}); object o({{"a", 1}}, sp);
o.insert_or_assign("a", str_); o.insert_or_assign("a", str_);
BEAST_EXPECT(o["a"].is_string()); BEAST_EXPECT(o["a"].is_string());
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({ object o({
{"a", 1}, {"a", 1},
{"b", 2}, {"b", 2},
{"c", 3}}); {"c", 3}}, sp);
o.insert_or_assign("d", str_); o.insert_or_assign("d", str_);
BEAST_EXPECT(o["d"].is_string()); BEAST_EXPECT(o["d"].is_string());
BEAST_EXPECT(o.size() == 4); BEAST_EXPECT(o.size() == 4);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({{"a", 1}}); object o({{"a", 1}}, sp);
o.insert_or_assign("b", true); o.insert_or_assign("b", true);
o.insert_or_assign("c", "hello"); o.insert_or_assign("c", "hello");
check(o, 3); check(o, 3);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({{"a", 1}}); object o({{"a", 1}}, sp);
BEAST_EXPECT( BEAST_EXPECT(
! o.insert_or_assign("a", 2).second); ! o.insert_or_assign("a", 2).second);
BEAST_EXPECT(o["a"].as_number() == 2); BEAST_EXPECT(o["a"].as_number() == 2);
@ -701,17 +691,17 @@ public:
// insert_or_assign(before, key, o); // insert_or_assign(before, key, o);
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({{"a", 1}}); object o({{"a", 1}}, sp);
o.insert_or_assign("c", "hello"); o.insert_or_assign("c", "hello");
o.insert_or_assign(o.find("c"), "b", true); o.insert_or_assign(o.find("c"), "b", true);
check(o, 3); check(o, 3);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({{"a", 1}}); object o({{"a", 1}}, sp);
o.insert_or_assign("b", true); o.insert_or_assign("b", true);
o.insert_or_assign("c", "hello"); o.insert_or_assign("c", "hello");
BEAST_EXPECT(! o.insert_or_assign( BEAST_EXPECT(! o.insert_or_assign(
@ -721,9 +711,9 @@ public:
} }
// emplace(key, arg) // emplace(key, arg)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("b", true); o.emplace("b", true);
o.emplace("c", "hello"); o.emplace("c", "hello");
@ -731,9 +721,9 @@ public:
}); });
// emplace(before, key, arg) // emplace(before, key, arg)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o; object o(sp);
o.emplace("a", 1); o.emplace("a", 1);
o.emplace("c", "hello"); o.emplace("c", "hello");
o.emplace(o.find("c"), "b", true); o.emplace(o.find("c"), "b", true);
@ -742,13 +732,13 @@ public:
// erase(pos) // erase(pos)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({ object o({
{"d", nullptr }, {"d", nullptr },
{"a", 1}, {"a", 1},
{"b", true}, {"b", true},
{"c", "hello"}}); {"c", "hello"}}, sp);
auto it = o.erase(o.begin()); auto it = o.erase(o.begin());
BEAST_EXPECT(it->first == "a"); BEAST_EXPECT(it->first == "a");
BEAST_EXPECT(it->second.as_number() == 1); BEAST_EXPECT(it->second.as_number() == 1);
@ -757,7 +747,7 @@ public:
} }
// erase(first, last) // erase(first, last)
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
object o({ object o({
{"a", 1}, {"a", 1},
@ -765,7 +755,7 @@ public:
{"b2", 2}, {"b2", 2},
{"b3", 3}, {"b3", 3},
{"b4", 4}, {"b4", 4},
{"c", "hello"}}); {"c", "hello"}}, sp);
auto first = o.find("b2"); auto first = o.find("b2");
auto last = std::next(first, 3); auto last = std::next(first, 3);
auto it = o.erase(first, last); auto it = o.erase(first, last);
@ -782,7 +772,6 @@ public:
{"a", 1}, {"a", 1},
{"b", true}, {"b", true},
{"c", "hello"}}); {"c", "hello"}});
scoped_fail_storage fs;
BEAST_EXPECT(o.erase("b2") == 0); BEAST_EXPECT(o.erase("b2") == 0);
check(o, 3); check(o, 3);
} }
@ -793,7 +782,6 @@ public:
{"b", true}, {"b", true},
{"b2", 2}, {"b2", 2},
{"c", "hello"}}); {"c", "hello"}});
scoped_fail_storage fs;
BEAST_EXPECT(o.erase("b2") == 1); BEAST_EXPECT(o.erase("b2") == 1);
check(o, 7); check(o, 7);
} }
@ -804,7 +792,6 @@ public:
{ {
object o1 = {{"a",1}, {"b",true}, {"c", "hello"}}; object o1 = {{"a",1}, {"b",true}, {"c", "hello"}};
object o2 = {{"d",{1,2,3}}}; object o2 = {{"d",{1,2,3}}};
scoped_fail_storage fs;
swap(o1, o2); swap(o1, o2);
BEAST_EXPECT(o1.size() == 1); BEAST_EXPECT(o1.size() == 1);
BEAST_EXPECT(o2.size() == 3); BEAST_EXPECT(o2.size() == 3);
@ -861,7 +848,6 @@ public:
} }
// operator[&](key) // operator[&](key)
fail_loop([&]
{ {
object o({ object o({
{"a", 1}, {"a", 1},
@ -871,7 +857,7 @@ public:
BEAST_EXPECT(o["a"].is_number()); BEAST_EXPECT(o["a"].is_number());
BEAST_EXPECT(o["d"].is_null()); BEAST_EXPECT(o["d"].is_null());
BEAST_EXPECT(o.count("d") == 1); BEAST_EXPECT(o.count("d") == 1);
}); }
// count(key) // count(key)
{ {

View File

@ -28,7 +28,7 @@ public:
} }
void* void*
allocate( do_allocate(
std::size_t, std::size_t,
std::size_t) override std::size_t) override
{ {
@ -36,7 +36,7 @@ public:
} }
void void
deallocate( do_deallocate(
void*, void*,
std::size_t, std::size_t,
std::size_t) noexcept override std::size_t) noexcept override
@ -44,7 +44,7 @@ public:
} }
bool bool
is_equal( do_is_equal(
storage const&) storage const&)
const noexcept override const noexcept override
{ {
@ -182,7 +182,7 @@ public:
} }
void void
testFree() testDefaultStorage()
{ {
// default_storage() // default_storage()
{ {
@ -190,15 +190,6 @@ public:
auto sp2 = default_storage(); auto sp2 = default_storage();
BEAST_EXPECT(*sp1 == *sp2); BEAST_EXPECT(*sp1 == *sp2);
} }
// default_storage(storage_ptr)
{
auto sp1 = default_storage();
auto sp2 = make_storage<unique_storage>();
default_storage(sp2);
BEAST_EXPECT(*default_storage() == *sp2);
default_storage(sp1);
}
} }
void void
@ -206,7 +197,7 @@ public:
{ {
testMembers(); testMembers();
testRelational(); testRelational();
testFree(); testDefaultStorage();
} }
}; };

View File

@ -63,16 +63,16 @@ public:
// string() // string()
{ {
scoped_fail_storage fs;
string s; string s;
} }
// string(storage_ptr) // string(storage_ptr)
{ {
scoped_fail_storage fs; auto const sp =
string s(fs.get()); make_storage<unique_storage>();
string s(sp);
BEAST_EXPECT(s.empty()); BEAST_EXPECT(s.empty());
BEAST_EXPECT(*s.get_storage() == *fs.get()); BEAST_EXPECT(*s.get_storage() == *sp.get());
} }
// string(size_type, char, storage_ptr) // string(size_type, char, storage_ptr)
@ -83,11 +83,10 @@ public:
BEAST_EXPECT(s == std::string(t.v1.size(), '*')); BEAST_EXPECT(s == std::string(t.v1.size(), '*'));
}); });
fail_loop([&]
{ {
string s(t.v2.size(), '*'); string s(t.v2.size(), '*');
BEAST_EXPECT(s == std::string(t.v2.size(), '*')); BEAST_EXPECT(s == std::string(t.v2.size(), '*'));
}); }
} }
// string(string const&, size_type, size_type, storage_ptr) // string(string const&, size_type, size_type, storage_ptr)
@ -98,17 +97,15 @@ public:
BEAST_EXPECT(s == "bcd"); BEAST_EXPECT(s == "bcd");
}); });
fail_loop([&]
{ {
string s(string(t.v1), 1, 3); string s(string(t.v1), 1, 3);
BEAST_EXPECT(s == "bcd"); BEAST_EXPECT(s == "bcd");
}); }
fail_loop([&]
{ {
string s(string(t.v1), 1); string s(string(t.v1), 1);
BEAST_EXPECT(s == t.v1.substr(1)); BEAST_EXPECT(s == t.v1.substr(1));
}); }
} }
// string(char const*, storage_ptr) // string(char const*, storage_ptr)
@ -125,17 +122,15 @@ public:
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); });
fail_loop([&]
{ {
string s(t.s1.c_str()); string s(t.s1.c_str());
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s(t.s2.c_str()); string s(t.s2.c_str());
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
} }
// string(char const*, size_type, storage_ptr) // string(char const*, size_type, storage_ptr)
@ -152,17 +147,15 @@ public:
BEAST_EXPECT(s == "ABC"); BEAST_EXPECT(s == "ABC");
}); });
fail_loop([&]
{ {
string s(t.s1.c_str(), 3); string s(t.s1.c_str(), 3);
BEAST_EXPECT(s == "abc"); BEAST_EXPECT(s == "abc");
}); }
fail_loop([&]
{ {
string s(t.s2.c_str(), 3); string s(t.s2.c_str(), 3);
BEAST_EXPECT(s == "ABC"); BEAST_EXPECT(s == "ABC");
}); }
} }
// string(InputIt, InputIt, storage_ptr) // string(InputIt, InputIt, storage_ptr)
@ -195,48 +188,42 @@ public:
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); });
fail_loop([&]
{ {
string s(t.v1.begin(), t.v1.end()); string s(t.v1.begin(), t.v1.end());
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s(t.v2.begin(), t.v2.end()); string s(t.v2.begin(), t.v2.end());
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
fail_loop([&]
{ {
string s( string s(
make_input_iterator(t.v1.begin()), make_input_iterator(t.v1.begin()),
make_input_iterator(t.v1.end())); make_input_iterator(t.v1.end()));
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s( string s(
make_input_iterator(t.v2.begin()), make_input_iterator(t.v2.begin()),
make_input_iterator(t.v2.end())); make_input_iterator(t.v2.end()));
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
} }
// string(string) // string(string)
{ {
fail_loop([&]
{ {
string s(string(t.v1)); string s(string(t.v1));
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s(string(t.v2)); string s(string(t.v2));
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
} }
// string(string, storage_ptr) // string(string, storage_ptr)
@ -279,7 +266,6 @@ public:
{ {
{ {
string s1(t.v1); string s1(t.v1);
scoped_fail_storage fs;
string s2(std::move(s1)); string s2(std::move(s1));
BEAST_EXPECT(s2 == t.v1); BEAST_EXPECT(s2 == t.v1);
BEAST_EXPECT(s1.empty()); BEAST_EXPECT(s1.empty());
@ -290,7 +276,6 @@ public:
{ {
string s1(t.v2); string s1(t.v2);
scoped_fail_storage fs;
string s2(std::move(s1)); string s2(std::move(s1));
BEAST_EXPECT(s2 == t.v2); BEAST_EXPECT(s2 == t.v2);
BEAST_EXPECT(s1.empty()); BEAST_EXPECT(s1.empty());
@ -377,17 +362,15 @@ public:
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); });
fail_loop([&]
{ {
string s(init1); string s(init1);
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s(init2); string s(init2);
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
} }
// string(string_view, storage_ptr) // string(string_view, storage_ptr)
@ -404,17 +387,15 @@ public:
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); });
fail_loop([&]
{ {
string s(t.v1); string s(t.v1);
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); }
fail_loop([&]
{ {
string s(t.v2); string s(t.v2);
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
}); }
} }
// string(string_view, size_type, size_type, storage_ptr) // string(string_view, size_type, size_type, storage_ptr)
@ -431,17 +412,15 @@ public:
BEAST_EXPECT(s == "BCD"); BEAST_EXPECT(s == "BCD");
}); });
fail_loop([&]
{ {
string s(t.v1, 1, 3); string s(t.v1, 1, 3);
BEAST_EXPECT(s == "bcd"); BEAST_EXPECT(s == "bcd");
}); }
fail_loop([&]
{ {
string s(t.v2, 1, 3); string s(t.v2, 1, 3);
BEAST_EXPECT(s == "BCD"); BEAST_EXPECT(s == "BCD");
}); }
} }
} }
@ -1443,9 +1422,9 @@ public:
// reserve(size_type) // reserve(size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.append(t.v1); s.append(t.v1);
s.append(t.v2); s.append(t.v2);
@ -1473,9 +1452,9 @@ public:
} }
// shrink_to_fit() // shrink_to_fit()
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
string::size_type cap; string::size_type cap;
cap = s.capacity(); cap = s.capacity();
@ -1532,17 +1511,17 @@ public:
// insert(size_type, size_type, char) // insert(size_type, size_type, char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, 3, '*'); s.insert(1, 3, '*');
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, 3, '*')); t.v1).insert(1, 3, '*'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, 3, '*'); s.insert(1, 3, '*');
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, 3, '*')); t.v2).insert(1, 3, '*'));
@ -1567,17 +1546,17 @@ public:
// insert(size_type, char const*) // insert(size_type, char const*)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, "***"); s.insert(1, "***");
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, "***")); t.v1).insert(1, "***"));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, "***"); s.insert(1, "***");
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, "***")); t.v2).insert(1, "***"));
@ -1594,17 +1573,17 @@ public:
// insert(size_type, char const*, size_type) // insert(size_type, char const*, size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, "*****", 3); s.insert(1, "*****", 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, "*****", 3)); t.v1).insert(1, "*****", 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, "*****", 3); s.insert(1, "*****", 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, "*****", 3)); t.v2).insert(1, "*****", 3));
@ -1613,17 +1592,17 @@ public:
// insert(size_type, string const&) // insert(size_type, string const&)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, string(t.v2)); s.insert(1, string(t.v2));
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, t.s2)); t.v1).insert(1, t.s2));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, string(t.v1)); s.insert(1, string(t.v1));
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, t.s1)); t.v2).insert(1, t.s1));
@ -1632,33 +1611,33 @@ public:
// insert(size_type, string const&, size_type, size_type) // insert(size_type, string const&, size_type, size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, string(t.v2), 1, 3); s.insert(1, string(t.v2), 1, 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, t.s2, 1, 3)); t.v1).insert(1, t.s2, 1, 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, string(t.v1), 1, 3); s.insert(1, string(t.v1), 1, 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, t.s1, 1, 3)); t.v2).insert(1, t.s1, 1, 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(1, string(t.v2), 1); s.insert(1, string(t.v2), 1);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(1, t.s2, 1, std::string::npos)); t.v1).insert(1, t.s2, 1, std::string::npos));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(1, string(t.v1), 1); s.insert(1, string(t.v1), 1);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(1, t.s1, 1, std::string::npos)); t.v2).insert(1, t.s1, 1, std::string::npos));
@ -1667,16 +1646,16 @@ public:
// insert(const_iterator, char) // insert(const_iterator, char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
BEAST_EXPECT( BEAST_EXPECT(
*s.insert(s.begin()+2, '*') == '*'); *s.insert(s.begin()+2, '*') == '*');
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
BEAST_EXPECT( BEAST_EXPECT(
*s.insert(s.begin()+2, '*') == '*'); *s.insert(s.begin()+2, '*') == '*');
}); });
@ -1684,17 +1663,17 @@ public:
// insert(const_iterator, size_type, char) // insert(const_iterator, size_type, char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
BEAST_EXPECT(string_view( BEAST_EXPECT(string_view(
s.insert(s.begin()+2, 3, '*'), 5) == s.insert(s.begin()+2, 3, '*'), 5) ==
"***cd"); "***cd");
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
BEAST_EXPECT(string_view( BEAST_EXPECT(string_view(
s.insert(s.begin()+2, 3, '*'), 5) == s.insert(s.begin()+2, 3, '*'), 5) ==
"***CD"); "***CD");
@ -1715,25 +1694,25 @@ public:
}; };
BEAST_EXPECT(std::string(init2) == t.s2); BEAST_EXPECT(std::string(init2) == t.s2);
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(s.begin()+2, init2.begin(), init2.end()); s.insert(s.begin()+2, init2.begin(), init2.end());
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.s1).insert(2, init2.begin(), init2.size())); t.s1).insert(2, init2.begin(), init2.size()));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(s.begin()+2, init1.begin(), init1.end()); s.insert(s.begin()+2, init1.begin(), init1.end());
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.s2).insert(2, init1.begin(), init1.size())); t.s2).insert(2, init1.begin(), init1.size()));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(s.begin()+2, s.insert(s.begin()+2,
make_input_iterator(init2.begin()), make_input_iterator(init2.begin()),
make_input_iterator(init2.end())); make_input_iterator(init2.end()));
@ -1741,9 +1720,9 @@ public:
t.s1).insert(2, init2.begin(), init2.size())); t.s1).insert(2, init2.begin(), init2.size()));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(s.begin()+2, s.insert(s.begin()+2,
make_input_iterator(init1.begin()), make_input_iterator(init1.begin()),
make_input_iterator(init1.end())); make_input_iterator(init1.end()));
@ -1766,17 +1745,17 @@ public:
}; };
BEAST_EXPECT(std::string(init2) == t.s2); BEAST_EXPECT(std::string(init2) == t.s2);
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(s.begin()+2, init2); s.insert(s.begin()+2, init2);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.s1).insert(2, init2.begin(), init2.size())); t.s1).insert(2, init2.begin(), init2.size()));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(s.begin()+2, init1); s.insert(s.begin()+2, init1);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.s2).insert(2, init1.begin(), init1.size())); t.s2).insert(2, init1.begin(), init1.size()));
@ -1785,17 +1764,17 @@ public:
// insert(const_iterator, string_view) // insert(const_iterator, string_view)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(2, string_view(t.v2)); s.insert(2, string_view(t.v2));
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(2, t.s2)); t.v1).insert(2, t.s2));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(2, string_view(t.v1)); s.insert(2, string_view(t.v1));
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(2, t.s1)); t.v2).insert(2, t.s1));
@ -1804,17 +1783,17 @@ public:
// insert(const_iterator, string_view) // insert(const_iterator, string_view)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.insert(2, string_view(t.v2), 2, 3); s.insert(2, string_view(t.v2), 2, 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v1).insert(2, t.s2, 2, 3)); t.v1).insert(2, t.s2, 2, 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.insert(2, string_view(t.v1), 2, 3); s.insert(2, string_view(t.v1), 2, 3);
BEAST_EXPECT(s == std::string( BEAST_EXPECT(s == std::string(
t.v2).insert(2, t.s1, 2, 3)); t.v2).insert(2, t.s1, 2, 3));
@ -1915,17 +1894,17 @@ public:
// push_back(char) // push_back(char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
for(auto ch : t.v1) for(auto ch : t.v1)
s.push_back(ch); s.push_back(ch);
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
for(auto ch : t.v2) for(auto ch : t.v2)
s.push_back(ch); s.push_back(ch);
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
@ -1959,17 +1938,17 @@ public:
// append(size_type, char) // append(size_type, char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.v2.size(), '*'); s.append(t.v2.size(), '*');
BEAST_EXPECT(s == t.s1 + BEAST_EXPECT(s == t.s1 +
std::string(t.v2.size(), '*')); std::string(t.v2.size(), '*'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.v1.size(), '*'); s.append(t.v1.size(), '*');
BEAST_EXPECT(s == t.s2 + BEAST_EXPECT(s == t.s2 +
std::string(t.v1.size(), '*')); std::string(t.v1.size(), '*'));
@ -1978,16 +1957,16 @@ public:
// append(string) // append(string)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(string(t.v2)); s.append(string(t.v2));
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(string(t.v1)); s.append(string(t.v1));
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -1995,30 +1974,30 @@ public:
// append(string, size_type, size_type) // append(string, size_type, size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(string(t.v2), 3); s.append(string(t.v2), 3);
BEAST_EXPECT(s == t.s1 + t.s2.substr(3)); BEAST_EXPECT(s == t.s1 + t.s2.substr(3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(string(t.v1), 3); s.append(string(t.v1), 3);
BEAST_EXPECT(s == t.s2 + t.s1.substr(3)); BEAST_EXPECT(s == t.s2 + t.s1.substr(3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(string(t.v2), 2, 3); s.append(string(t.v2), 2, 3);
BEAST_EXPECT(s == t.s1 + t.s2.substr(2, 3)); BEAST_EXPECT(s == t.s1 + t.s2.substr(2, 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(string(t.v1), 2, 3); s.append(string(t.v1), 2, 3);
BEAST_EXPECT(s == t.s2 + t.s1.substr(2, 3)); BEAST_EXPECT(s == t.s2 + t.s1.substr(2, 3));
}); });
@ -2026,16 +2005,16 @@ public:
// append(char const*) // append(char const*)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.s2.c_str()); s.append(t.s2.c_str());
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.s1.c_str()); s.append(t.s1.c_str());
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2043,16 +2022,16 @@ public:
// append(char const*, size_type) // append(char const*, size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.s2.c_str(), 5); s.append(t.s2.c_str(), 5);
BEAST_EXPECT(s == t.s1 + t.s2.substr(0, 5)); BEAST_EXPECT(s == t.s1 + t.s2.substr(0, 5));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.s1.c_str(), 5); s.append(t.s1.c_str(), 5);
BEAST_EXPECT(s == t.s2 + t.s1.substr(0, 5)); BEAST_EXPECT(s == t.s2 + t.s1.substr(0, 5));
}); });
@ -2072,16 +2051,16 @@ public:
}; };
BEAST_EXPECT(std::string(init2) == t.s2); BEAST_EXPECT(std::string(init2) == t.s2);
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(init2); s.append(init2);
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(init1); s.append(init1);
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2101,32 +2080,32 @@ public:
}; };
BEAST_EXPECT(std::string(init2) == t.s2); BEAST_EXPECT(std::string(init2) == t.s2);
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(init2.begin(), init2.end()); s.append(init2.begin(), init2.end());
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(init1.begin(), init1.end()); s.append(init1.begin(), init1.end());
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append( s.append(
make_input_iterator(init2.begin()), make_input_iterator(init2.begin()),
make_input_iterator(init2.end())); make_input_iterator(init2.end()));
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append( s.append(
make_input_iterator(init1.begin()), make_input_iterator(init1.begin()),
make_input_iterator(init1.end())); make_input_iterator(init1.end()));
@ -2136,16 +2115,16 @@ public:
// append(string_view) // append(string_view)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.v2); s.append(t.v2);
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.v1); s.append(t.v1);
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2153,30 +2132,30 @@ public:
// append(string_view) // append(string_view)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.v2, 2); s.append(t.v2, 2);
BEAST_EXPECT(s == t.s1 + t.s2.substr(2)); BEAST_EXPECT(s == t.s1 + t.s2.substr(2));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.v1, 2); s.append(t.v1, 2);
BEAST_EXPECT(s == t.s2 + t.s1.substr(2)); BEAST_EXPECT(s == t.s2 + t.s1.substr(2));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s.append(t.v2, 2, 3); s.append(t.v2, 2, 3);
BEAST_EXPECT(s == t.s1 + t.s2.substr(2, 3)); BEAST_EXPECT(s == t.s1 + t.s2.substr(2, 3));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s.append(t.v1, 2, 3); s.append(t.v1, 2, 3);
BEAST_EXPECT(s == t.s2 + t.s1.substr(2, 3)); BEAST_EXPECT(s == t.s2 + t.s1.substr(2, 3));
}); });
@ -2190,16 +2169,16 @@ public:
// operator+=(string) // operator+=(string)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s += string(t.v2); s += string(t.v2);
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s += string(t.v1); s += string(t.v1);
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2207,17 +2186,17 @@ public:
// operator+=(char) // operator+=(char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
for(auto ch : t.v1) for(auto ch : t.v1)
s += ch; s += ch;
BEAST_EXPECT(s == t.v1); BEAST_EXPECT(s == t.v1);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
for(auto ch : t.v2) for(auto ch : t.v2)
s += ch; s += ch;
BEAST_EXPECT(s == t.v2); BEAST_EXPECT(s == t.v2);
@ -2226,16 +2205,16 @@ public:
// operator+=(char const*) // operator+=(char const*)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s += t.s2.c_str(); s += t.s2.c_str();
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s += t.s1.c_str(); s += t.s1.c_str();
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2255,16 +2234,16 @@ public:
}; };
BEAST_EXPECT(std::string(init2) == t.s2); BEAST_EXPECT(std::string(init2) == t.s2);
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s += init2; s += init2;
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s += init1; s += init1;
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2272,16 +2251,16 @@ public:
// operator+=(string_view) // operator+=(string_view)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v1); string s(t.v1, sp);
s += t.v2; s += t.v2;
BEAST_EXPECT(s == t.s1 + t.s2); BEAST_EXPECT(s == t.s1 + t.s2);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s(t.v2); string s(t.v2, sp);
s += t.v1; s += t.v1;
BEAST_EXPECT(s == t.s2 + t.s1); BEAST_EXPECT(s == t.s2 + t.s1);
}); });
@ -2449,25 +2428,25 @@ public:
// resize(size_type) // resize(size_type)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v1.size()); s.resize(t.v1.size());
BEAST_EXPECT(s.size() == t.v1.size()); BEAST_EXPECT(s.size() == t.v1.size());
BEAST_EXPECT(s == string(t.v1.size(), '\0')); BEAST_EXPECT(s == string(t.v1.size(), '\0'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v2.size()); s.resize(t.v2.size());
BEAST_EXPECT(s.size() == t.v2.size()); BEAST_EXPECT(s.size() == t.v2.size());
BEAST_EXPECT(s == string(t.v2.size(), '\0')); BEAST_EXPECT(s == string(t.v2.size(), '\0'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v1.size()); s.resize(t.v1.size());
s.resize(t.v2.size()); s.resize(t.v2.size());
BEAST_EXPECT(s == string(t.v2.size(), '\0')); BEAST_EXPECT(s == string(t.v2.size(), '\0'));
@ -2478,25 +2457,25 @@ public:
// resize(size_type, char) // resize(size_type, char)
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v1.size(), '*'); s.resize(t.v1.size(), '*');
BEAST_EXPECT(s.size() == t.v1.size()); BEAST_EXPECT(s.size() == t.v1.size());
BEAST_EXPECT(s == string(t.v1.size(), '*')); BEAST_EXPECT(s == string(t.v1.size(), '*'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v2.size(), '*'); s.resize(t.v2.size(), '*');
BEAST_EXPECT(s.size() == t.v2.size()); BEAST_EXPECT(s.size() == t.v2.size());
BEAST_EXPECT(s == string(t.v2.size(), '*')); BEAST_EXPECT(s == string(t.v2.size(), '*'));
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s; string s(sp);
s.resize(t.v1.size(), '*'); s.resize(t.v1.size(), '*');
s.resize(t.v2.size(), '*'); s.resize(t.v2.size(), '*');
BEAST_EXPECT(s == string(t.v2.size(), '*')); BEAST_EXPECT(s == string(t.v2.size(), '*'));
@ -2513,19 +2492,19 @@ public:
// swap // swap
{ {
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s1(t.v1); string s1(t.v1, sp);
string s2(t.v2); string s2(t.v2, sp);
s1.swap(s2); s1.swap(s2);
BEAST_EXPECT(s1 == t.v2); BEAST_EXPECT(s1 == t.v2);
BEAST_EXPECT(s2 == t.v1); BEAST_EXPECT(s2 == t.v1);
}); });
fail_loop([&] fail_loop([&](storage_ptr const& sp)
{ {
string s1(t.v1); string s1(t.v1, sp);
string s2(t.v2); string s2(t.v2, sp);
swap(s1, s2); swap(s1, s2);
BEAST_EXPECT(s1 == t.v2); BEAST_EXPECT(s1 == t.v2);
BEAST_EXPECT(s2 == t.v1); BEAST_EXPECT(s2 == t.v1);

View File

@ -28,7 +28,7 @@ namespace json {
struct unique_storage : storage struct unique_storage : storage
{ {
void* void*
allocate( do_allocate(
std::size_t n, std::size_t n,
std::size_t) override std::size_t) override
{ {
@ -37,7 +37,7 @@ struct unique_storage : storage
} }
void void
deallocate( do_deallocate(
void* p, void* p,
std::size_t n, std::size_t n,
std::size_t) noexcept override std::size_t) noexcept override
@ -48,7 +48,7 @@ struct unique_storage : storage
char>{}.deallocate(cp, n); char>{}.deallocate(cp, n);
} }
bool bool
is_equal( do_is_equal(
storage const&) const noexcept override storage const&) const noexcept override
{ {
return false; return false;
@ -77,7 +77,7 @@ struct fail_storage : storage
} }
void* void*
allocate( do_allocate(
std::size_t n, std::size_t n,
std::size_t) override std::size_t) override
{ {
@ -92,7 +92,7 @@ struct fail_storage : storage
} }
void void
deallocate( do_deallocate(
void* p, void* p,
std::size_t n, std::size_t n,
std::size_t) noexcept override std::size_t) noexcept override
@ -103,7 +103,7 @@ struct fail_storage : storage
char>{}.deallocate(cp, n); char>{}.deallocate(cp, n);
} }
bool bool
is_equal( do_is_equal(
storage const&) const noexcept override storage const&) const noexcept override
{ {
return false; return false;
@ -112,34 +112,32 @@ struct fail_storage : storage
//---------------------------------------------------------- //----------------------------------------------------------
class scoped_fail_storage
{
storage_ptr sp_;
public:
scoped_fail_storage()
: sp_(default_storage())
{
default_storage(
make_storage<fail_storage>());
}
~scoped_fail_storage()
{
default_storage(sp_);
}
storage_ptr const&
get() const noexcept
{
return sp_;
}
};
//----------------------------------------------------------
namespace detail { namespace detail {
#if 1
template<class F>
void
fail_loop(F&& f)
{
auto sp = make_storage<fail_storage>();
while(sp->fail < 200)
{
try
{
f(sp);
}
catch(test_failure const&)
{
continue;
}
break;
}
BEAST_EXPECT(sp->fail < 200);
}
#else
template<class F> template<class F>
typename std::enable_if< typename std::enable_if<
std::is_same<void, std::is_same<void,
@ -191,6 +189,8 @@ fail_loop(F&& f)
default_storage(saved); default_storage(saved);
} }
#endif
} // detail } // detail
template<class F> template<class F>