mirror of
https://github.com/boostorg/json.git
synced 2025-05-11 05:33:57 +00:00
Handler specifies structure and string limits
This commit is contained in:
parent
da65b25f4d
commit
f3d0710e37
@ -387,6 +387,11 @@ class boost_null_impl : public any_impl
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
bool on_document_begin(error_code&) { return true; }
|
||||
bool on_document_end(error_code&) { return true; }
|
||||
bool on_object_begin(error_code&) { return true; }
|
||||
|
@ -26,60 +26,64 @@ using namespace boost::json;
|
||||
|
||||
//[example_validate
|
||||
|
||||
// The null parser discards all the data
|
||||
class null_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code& ) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part(string_view, error_code&) { return true; }
|
||||
bool on_comment(string_view, error_code&) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
null_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
~null_parser()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write( false, data, size, ec );
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
validate( string_view s )
|
||||
{
|
||||
// The null parser discards all the data
|
||||
|
||||
class null_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code& ) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part(string_view, error_code&) { return true; }
|
||||
bool on_comment(string_view, error_code&) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
null_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
~null_parser()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write( false, data, size, ec );
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
// Parse with the null parser and return false on error
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
|
@ -17,58 +17,63 @@
|
||||
|
||||
using namespace boost::json;
|
||||
|
||||
class null_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code& ) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part(string_view, error_code&) { return true; }
|
||||
bool on_comment(string_view, error_code&) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
null_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
~null_parser()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write( false, data, size, ec );
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
validate( string_view s )
|
||||
{
|
||||
class null_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code& ) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part(string_view, error_code&) { return true; }
|
||||
bool on_comment(string_view, error_code&) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
null_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
~null_parser()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write( false, data, size, ec );
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
// Parse with the null parser and return false on error
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
|
@ -1022,7 +1022,7 @@ public:
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
return BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
return array_impl::max_size();
|
||||
}
|
||||
|
||||
/** Return the number of elements that can be held in currently allocated memory.
|
||||
|
@ -965,10 +965,22 @@ parse_unescaped(const char* p)
|
||||
cs = detail::count_valid<AllowBadUTF8>(
|
||||
cs.begin(), cs.end());
|
||||
std::size_t size = cs.used(start);
|
||||
if(BOOST_JSON_UNLIKELY(size >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
return fail(cs.begin(), IsKey ?
|
||||
error::key_too_large : error::string_too_large);
|
||||
if(IsKey)
|
||||
{
|
||||
BOOST_ASSERT(total <= Handler::max_key_size);
|
||||
if(BOOST_JSON_UNLIKELY(size >
|
||||
Handler::max_key_size - total))
|
||||
return fail(cs.begin(),
|
||||
error::key_too_large);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(total <= Handler::max_string_size);
|
||||
if(BOOST_JSON_UNLIKELY(size >
|
||||
Handler::max_string_size - total))
|
||||
return fail(cs.begin(),
|
||||
error::string_too_large);
|
||||
}
|
||||
total += size;
|
||||
if(BOOST_JSON_UNLIKELY(! cs))
|
||||
{
|
||||
@ -1049,6 +1061,8 @@ parse_escaped(
|
||||
&Handler::on_key_part : &Handler::on_string_part;
|
||||
constexpr auto ev_too_large = IsKey ?
|
||||
error::key_too_large : error::string_too_large;
|
||||
constexpr auto max_size = IsKey ?
|
||||
Handler::max_key_size : Handler::max_string_size;
|
||||
detail::clipped_const_stream cs(p, end_);
|
||||
detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
|
||||
int digit;
|
||||
@ -1089,8 +1103,9 @@ do_str3:
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(! temp.empty()))
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(temp.size() >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
BOOST_ASSERT(total <= max_size);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
temp.size() > max_size - total))
|
||||
return fail(cs.begin(), ev_too_large);
|
||||
total += temp.size();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
@ -1238,8 +1253,9 @@ do_str3:
|
||||
// flush
|
||||
if(BOOST_JSON_LIKELY(! temp.empty()))
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(temp.size() >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
BOOST_ASSERT(total <= max_size);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
temp.size() > max_size - total))
|
||||
return fail(cs.begin(), ev_too_large);
|
||||
total += temp.size();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
@ -1367,8 +1383,9 @@ do_str2:
|
||||
// flush
|
||||
if(BOOST_JSON_LIKELY(! temp.empty()))
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(temp.size() >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
BOOST_ASSERT(total <= max_size);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
temp.size() > max_size - total))
|
||||
return fail(cs.begin(), ev_too_large);
|
||||
total += temp.size();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
@ -1383,8 +1400,9 @@ do_str2:
|
||||
c = *cs;
|
||||
if(BOOST_JSON_LIKELY(c == '\x22')) // '"'
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(temp.size() >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
BOOST_ASSERT(total <= max_size);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
temp.size() > max_size - total))
|
||||
return fail(cs.begin(), ev_too_large);
|
||||
total += temp.size();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
@ -1400,8 +1418,9 @@ do_str2:
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(! temp.empty()))
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(temp.size() >
|
||||
BOOST_JSON_MAX_STRING_SIZE - total))
|
||||
BOOST_ASSERT(total <= max_size);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
temp.size() > max_size - total))
|
||||
return fail(cs.begin(), ev_too_large);
|
||||
total += temp.size();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
@ -1512,7 +1531,7 @@ do_obj2:
|
||||
}
|
||||
loop:
|
||||
if(BOOST_JSON_UNLIKELY(++size >
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE))
|
||||
Handler::max_object_size))
|
||||
return fail(cs.begin(), error::object_too_large);
|
||||
do_obj3:
|
||||
cs = parse_string<StackEmpty, true,
|
||||
@ -1658,7 +1677,7 @@ do_arr2:
|
||||
}
|
||||
loop:
|
||||
if(BOOST_JSON_UNLIKELY(++size >
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE))
|
||||
Handler::max_array_size))
|
||||
return fail(cs.begin(), error::array_too_large);
|
||||
do_arr3:
|
||||
// array is not empty, value required
|
||||
|
@ -54,10 +54,7 @@ public:
|
||||
static
|
||||
constexpr
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
return BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
max_size() noexcept;
|
||||
|
||||
value*
|
||||
data() const noexcept
|
||||
|
@ -83,6 +83,24 @@ BOOST_JSON_NS_BEGIN
|
||||
the error code to a suitable value. This error
|
||||
code will be returned by the write function to
|
||||
the caller.
|
||||
\n
|
||||
Handlers must also define the following
|
||||
static data members:
|
||||
|
||||
@li `max_object_size`, the maximum number
|
||||
of elements an object can contain,
|
||||
|
||||
@li `max_array_size`, the maximum number
|
||||
of elements an array can contain,
|
||||
|
||||
@li `max_key_size`, the maximum length
|
||||
for object keys, and
|
||||
|
||||
@li `max_string_size`, the maximum
|
||||
length for strings.
|
||||
|
||||
If a value exceeding these limits
|
||||
is encountered, parsing fails.
|
||||
\n
|
||||
The following declaration meets the parser's
|
||||
handler requirements:
|
||||
@ -90,6 +108,12 @@ BOOST_JSON_NS_BEGIN
|
||||
@code
|
||||
struct handler
|
||||
{
|
||||
/// Value size limits
|
||||
constexpr static std::size_t max_object_size = -1;
|
||||
constexpr static std::size_t max_array_size = -1;
|
||||
constexpr static std::size_t max_key_size = -1;
|
||||
constexpr static std::size_t max_string_size = -1;
|
||||
|
||||
/// Called once when the JSON parsing begins.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
|
@ -13,6 +13,18 @@
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
array_impl::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) / sizeof(value)>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
auto
|
||||
array_impl::
|
||||
index_of(value const* pos) const noexcept ->
|
||||
|
@ -21,16 +21,14 @@ array_impl(
|
||||
std::size_t capacity,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
auto constexpr soft_limit =
|
||||
(std::size_t(-1) - sizeof(table)) /
|
||||
sizeof(value);
|
||||
if( capacity > soft_limit ||
|
||||
capacity > max_size())
|
||||
if(capacity > max_size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
"capacity > max_size()",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
if(capacity > 0)
|
||||
{
|
||||
// make sure to update max_size
|
||||
// if this is changed
|
||||
tab_ = ::new(sp->allocate(
|
||||
(sizeof(table) +
|
||||
capacity * sizeof(value) +
|
||||
|
@ -16,6 +16,19 @@
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
object_impl::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) /
|
||||
(sizeof(value_type) + sizeof(index_t))>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
object_impl::
|
||||
remove(
|
||||
@ -41,7 +54,7 @@ bucket_sizes() noexcept ->
|
||||
{
|
||||
// Taken from Boost.Intrusive and Boost.MultiIndex code,
|
||||
// thanks to Ion Gaztanaga and Joaquin M Lopez Munoz.
|
||||
static constexpr std::size_t list[33] =
|
||||
static constexpr std::size_t list[34] =
|
||||
{
|
||||
0,
|
||||
|
||||
@ -61,7 +74,9 @@ bucket_sizes() noexcept ->
|
||||
100663319, 201326611,
|
||||
402653189, 805306457,
|
||||
1610612741,
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE // 3221225473
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE,
|
||||
// catch anything that exceeds max_size
|
||||
std::size_t(-1)
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
@ -37,14 +37,12 @@ object_impl(
|
||||
std::uintptr_t salt,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
// max capacity based on address model
|
||||
auto constexpr soft_limit =
|
||||
(std::size_t(-1) - sizeof(table)) / (
|
||||
sizeof(value_type) + sizeof(index_t));
|
||||
if(capacity > soft_limit)
|
||||
if(capacity > max_size())
|
||||
throw_length_error(
|
||||
"capacity > soft_limit",
|
||||
"capacity > max_size()",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
// make sure to update max_size
|
||||
// if this is changed
|
||||
const auto n =
|
||||
sizeof(table) +
|
||||
capacity *
|
||||
|
@ -31,7 +31,7 @@ class object_impl
|
||||
using index_t = std::uint32_t;
|
||||
static index_t const null_index =
|
||||
std::uint32_t(-1);
|
||||
using bucket_size_array = const std::size_t [33];
|
||||
using bucket_size_array = const std::size_t[34];
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
@ -62,6 +62,11 @@ public:
|
||||
do_destroy(sp);
|
||||
}
|
||||
|
||||
static
|
||||
constexpr
|
||||
std::size_t
|
||||
max_size() noexcept;
|
||||
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
|
@ -97,7 +97,11 @@ public:
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
return BOOST_JSON_MAX_STRING_SIZE;
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
std::size_t(-1) - sizeof(table)>;
|
||||
return min::value < BOOST_JSON_MAX_STRING_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRING_SIZE;
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
|
@ -212,10 +212,6 @@ reserve(std::size_t new_capacity)
|
||||
{
|
||||
if(new_capacity <= capacity())
|
||||
return;
|
||||
if(new_capacity > max_size())
|
||||
detail::throw_length_error(
|
||||
"new_capacity > max_size()",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
rehash(new_capacity);
|
||||
}
|
||||
|
||||
|
@ -509,12 +509,12 @@ rehash(std::size_t new_capacity)
|
||||
BOOST_ASSERT(new_capacity > capacity());
|
||||
std::size_t const* prime =
|
||||
object_impl::bucket_sizes();
|
||||
while(new_capacity > *prime)
|
||||
while(*prime < new_capacity)
|
||||
++prime;
|
||||
new_capacity = *prime;
|
||||
if(new_capacity > max_size())
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
"new_capacity > max_size()",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
object_impl impl(
|
||||
new_capacity,
|
||||
|
@ -860,7 +860,7 @@ public:
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
return BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
return object_impl::max_size();
|
||||
}
|
||||
|
||||
/** Return the number of elements that can be held in currently allocated memory
|
||||
|
@ -104,6 +104,18 @@ class parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t
|
||||
max_object_size = object::max_size();
|
||||
|
||||
constexpr static std::size_t
|
||||
max_array_size = array::max_size();
|
||||
|
||||
constexpr static std::size_t
|
||||
max_key_size = string::max_size();
|
||||
|
||||
constexpr static std::size_t
|
||||
max_string_size = string::max_size();
|
||||
|
||||
value_stack st;
|
||||
|
||||
template<class... Args>
|
||||
|
@ -62,6 +62,8 @@ class string
|
||||
friend struct detail::value_access;
|
||||
#endif
|
||||
|
||||
using string_impl = detail::string_impl;
|
||||
|
||||
inline
|
||||
string(
|
||||
char** key,
|
||||
@ -130,7 +132,7 @@ private:
|
||||
char>::value>::type;
|
||||
|
||||
storage_ptr sp_; // must come first
|
||||
detail::string_impl impl_;
|
||||
string_impl impl_;
|
||||
|
||||
public:
|
||||
/** Destructor.
|
||||
@ -190,7 +192,7 @@ public:
|
||||
: sp_(std::move(other.get().sp_))
|
||||
, impl_(other.get().impl_)
|
||||
{
|
||||
::new(&other.get().impl_) detail::string_impl();
|
||||
::new(&other.get().impl_) string_impl();
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
@ -437,7 +439,7 @@ public:
|
||||
: sp_(other.sp_)
|
||||
, impl_(other.impl_)
|
||||
{
|
||||
::new(&other.impl_) detail::string_impl();
|
||||
::new(&other.impl_) string_impl();
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
@ -1433,7 +1435,7 @@ public:
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
return BOOST_JSON_MAX_STRING_SIZE;
|
||||
return string_impl::max_size();
|
||||
}
|
||||
|
||||
/** Return the number of characters that can be held without a reallocation.
|
||||
|
@ -872,6 +872,72 @@ public:
|
||||
good_one(s);
|
||||
}
|
||||
|
||||
class comment_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
std::string captured = "";
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code&) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view s, error_code& )
|
||||
{
|
||||
captured.append(s.data(), s.size());
|
||||
return true;
|
||||
}
|
||||
bool on_comment( string_view s, error_code& )
|
||||
{
|
||||
captured.append(s.data(), s.size());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
comment_parser()
|
||||
: p_(make_options(true, false, false))
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
false, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured() const noexcept
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testComments()
|
||||
{
|
||||
@ -899,67 +965,6 @@ public:
|
||||
"/*** aaaa***/"
|
||||
};
|
||||
|
||||
class comment_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
std::string captured = "";
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view, error_code&) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view s, error_code& )
|
||||
{
|
||||
captured.append(s.data(), s.size());
|
||||
return true;
|
||||
}
|
||||
bool on_comment( string_view s, error_code& )
|
||||
{
|
||||
captured.append(s.data(), s.size());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
comment_parser()
|
||||
: p_(make_options(true, false, false))
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
false, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured() const noexcept
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
std::string formatted = "";
|
||||
std::string just_comments = "";
|
||||
std::size_t guess = std::count(
|
||||
@ -1064,6 +1069,73 @@ public:
|
||||
good("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{},},},},},},}", enabled);
|
||||
}
|
||||
|
||||
class utf8_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
std::string captured = "";
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view sv, std::size_t, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_string( string_view sv, std::size_t, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_number_part( string_view, error_code&) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view, error_code& ) { return true; }
|
||||
bool on_comment( string_view, error_code& ) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
utf8_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
bool more,
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
more, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured() const noexcept
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testUTF8Validation()
|
||||
{
|
||||
@ -1228,68 +1300,6 @@ public:
|
||||
bad("\"\\n\xf4\x80\x70\x80----------\"");
|
||||
bad("\"\\n\xf4\x80\xbf\x70-\\n\xf4\x80\xbf\x70\"");
|
||||
|
||||
class utf8_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
std::string captured = "";
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view sv, std::size_t, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_string( string_view sv, std::size_t, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_number_part( string_view, error_code&) { return true; }
|
||||
bool on_int64( std::int64_t, string_view, error_code& ) { return true; }
|
||||
bool on_uint64( std::uint64_t, string_view, error_code& ) { return true; }
|
||||
bool on_double( double, string_view, error_code& ) { return true; }
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view, error_code& ) { return true; }
|
||||
bool on_comment( string_view, error_code& ) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
utf8_parser()
|
||||
: p_(parse_options())
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
bool more,
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
more, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured() const noexcept
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
const auto check =
|
||||
[this](string_view expected)
|
||||
{
|
||||
@ -1360,85 +1370,89 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
class literal_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
std::string captured = "";
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view sv, error_code&)
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_int64( std::int64_t, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 's';
|
||||
return true;
|
||||
}
|
||||
bool on_uint64( std::uint64_t, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 'u';
|
||||
return true;
|
||||
}
|
||||
bool on_double( double, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 'd';
|
||||
return true;
|
||||
}
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view, error_code& ) { return true; }
|
||||
bool on_comment( string_view, error_code& ) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
literal_parser()
|
||||
: p_(make_options(true, false, false))
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
bool more,
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
more, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured()
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testNumberLiteral()
|
||||
{
|
||||
class literal_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
std::string captured = "";
|
||||
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
bool on_object_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_array_begin( error_code& ) { return true; }
|
||||
bool on_array_end( std::size_t, error_code& ) { return true; }
|
||||
bool on_key_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_key( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string_part( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_string( string_view, std::size_t, error_code& ) { return true; }
|
||||
bool on_number_part( string_view sv, error_code&)
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
return true;
|
||||
}
|
||||
bool on_int64( std::int64_t, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 's';
|
||||
return true;
|
||||
}
|
||||
bool on_uint64( std::uint64_t, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 'u';
|
||||
return true;
|
||||
}
|
||||
bool on_double( double, string_view sv, error_code& )
|
||||
{
|
||||
captured.append(sv.data(), sv.size());
|
||||
captured += 'd';
|
||||
return true;
|
||||
}
|
||||
bool on_bool( bool, error_code& ) { return true; }
|
||||
bool on_null( error_code& ) { return true; }
|
||||
bool on_comment_part( string_view, error_code& ) { return true; }
|
||||
bool on_comment( string_view, error_code& ) { return true; }
|
||||
};
|
||||
|
||||
basic_parser<handler> p_;
|
||||
|
||||
public:
|
||||
literal_parser()
|
||||
: p_(make_options(true, false, false))
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
write(
|
||||
bool more,
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write(
|
||||
more, data, size, ec);
|
||||
if(! ec && n < size)
|
||||
ec = error::extra_data;
|
||||
return n;
|
||||
}
|
||||
|
||||
string_view
|
||||
captured()
|
||||
{
|
||||
return p_.handler().captured;
|
||||
}
|
||||
};
|
||||
|
||||
const auto check =
|
||||
[](string_view expected)
|
||||
[](string_view expected)
|
||||
{
|
||||
string_view sv = expected;
|
||||
sv.remove_suffix(1);
|
||||
|
@ -286,14 +286,8 @@ public:
|
||||
auto jv = parse(s, ec);
|
||||
BOOST_TEST(! ec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testBasicParser()
|
||||
{
|
||||
// overflow in on_key_part
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
std::string big;
|
||||
big = "\\b";
|
||||
@ -301,13 +295,12 @@ public:
|
||||
string::max_size()*2, '*');
|
||||
auto const js =
|
||||
"{\"" + big + "\":null}";
|
||||
p.write(js.data(), js.size(), ec);
|
||||
auto jv = parse(js, ec);
|
||||
BOOST_TEST(ec == error::key_too_large);
|
||||
}
|
||||
|
||||
// overflow in on_key
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
std::string big;
|
||||
big = "\\b";
|
||||
@ -315,13 +308,12 @@ public:
|
||||
(string::max_size()*3)/2, '*');
|
||||
auto const js =
|
||||
"{\"" + big + "\":null}";
|
||||
p.write(js.data(), js.size(), ec);
|
||||
auto jv = parse(js, ec);
|
||||
BOOST_TEST(ec == error::key_too_large);
|
||||
}
|
||||
|
||||
// overflow in on_string_part
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
std::string big;
|
||||
big = "\\b";
|
||||
@ -329,13 +321,12 @@ public:
|
||||
string::max_size()*2, '*');
|
||||
auto const js =
|
||||
"\"" + big + "\"";
|
||||
p.write(js.data(), js.size(), ec);
|
||||
auto jv = parse(js, ec);
|
||||
BOOST_TEST(ec == error::string_too_large);
|
||||
}
|
||||
|
||||
// overflow in on_string
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
std::string big;
|
||||
big = "\\b";
|
||||
@ -343,14 +334,13 @@ public:
|
||||
(string::max_size()*3)/2, '*');
|
||||
auto const js =
|
||||
"\"" + big + "\"";
|
||||
p.write(js.data(), js.size(), ec);
|
||||
auto jv = parse(js, ec);
|
||||
BOOST_TEST(ec == error::string_too_large);
|
||||
}
|
||||
|
||||
|
||||
// object overflow
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
string_view s = R"({
|
||||
"00":0,"01":0,"02":0,"03":0,"04":0,"05":0,"06":0,"07":0,"08":0,"09":0,
|
||||
@ -358,20 +348,19 @@ public:
|
||||
"20":0
|
||||
})";
|
||||
|
||||
p.write(s.data(), s.size(), ec);
|
||||
auto jv = parse(s, ec);
|
||||
BOOST_TEST(ec == error::object_too_large);
|
||||
}
|
||||
|
||||
// array overflow
|
||||
{
|
||||
null_parser p;
|
||||
error_code ec;
|
||||
string_view s = "["
|
||||
"0,0,0,0,0,0,0,0,0,0,"
|
||||
"0,0,0,0,0,0,0,0,0,0,"
|
||||
"0"
|
||||
"]";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
auto jv = parse(s, ec);
|
||||
BOOST_TEST(ec == error::array_too_large);
|
||||
}
|
||||
}
|
||||
@ -390,7 +379,6 @@ public:
|
||||
testString();
|
||||
testStack();
|
||||
testParser();
|
||||
testBasicParser();
|
||||
|
||||
#else
|
||||
BOOST_TEST_PASS();
|
||||
|
@ -145,6 +145,11 @@ class null_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
bool on_document_begin( error_code& ) { return true; }
|
||||
bool on_document_end( error_code& ) { return true; }
|
||||
bool on_object_begin( error_code& ) { return true; }
|
||||
@ -205,6 +210,11 @@ class fail_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
std::size_t n;
|
||||
|
||||
handler()
|
||||
@ -445,6 +455,11 @@ class throw_parser
|
||||
{
|
||||
struct handler
|
||||
{
|
||||
constexpr static std::size_t max_object_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_array_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_key_size = std::size_t(-1);
|
||||
constexpr static std::size_t max_string_size = std::size_t(-1);
|
||||
|
||||
std::size_t n;
|
||||
|
||||
handler()
|
||||
|
@ -1640,13 +1640,7 @@ public:
|
||||
check_array(value{false,2}, false, 2);
|
||||
check_array(value{false,2,"3",nullptr}, false, 2, "3", nullptr);
|
||||
check_array(value{2,false,"3"}, 2, false, "3");
|
||||
check_array(value{true,2,"3"}, true, 2, "3"); }
|
||||
|
||||
void
|
||||
testMaxSize()
|
||||
{
|
||||
// The implementation requires these equal
|
||||
BOOST_TEST(object::max_size() == array::max_size());
|
||||
check_array(value{true,2,"3"}, true, 2, "3");
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -1667,7 +1661,6 @@ public:
|
||||
testKeyValuePair();
|
||||
testStdConstruction();
|
||||
testInitList();
|
||||
testMaxSize();
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user