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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,7 +28,7 @@ namespace json {
struct unique_storage : storage
{
void*
allocate(
do_allocate(
std::size_t n,
std::size_t) override
{
@ -37,7 +37,7 @@ struct unique_storage : storage
}
void
deallocate(
do_deallocate(
void* p,
std::size_t n,
std::size_t) noexcept override
@ -48,7 +48,7 @@ struct unique_storage : storage
char>{}.deallocate(cp, n);
}
bool
is_equal(
do_is_equal(
storage const&) const noexcept override
{
return false;
@ -77,7 +77,7 @@ struct fail_storage : storage
}
void*
allocate(
do_allocate(
std::size_t n,
std::size_t) override
{
@ -92,7 +92,7 @@ struct fail_storage : storage
}
void
deallocate(
do_deallocate(
void* p,
std::size_t n,
std::size_t) noexcept override
@ -103,7 +103,7 @@ struct fail_storage : storage
char>{}.deallocate(cp, n);
}
bool
is_equal(
do_is_equal(
storage const&) const noexcept override
{
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 {
#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>
typename std::enable_if<
std::is_same<void,
@ -191,6 +189,8 @@ fail_loop(F&& f)
default_storage(saved);
}
#endif
} // detail
template<class F>