Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73b0a3aba3 | ||
|
|
7196bc5b22 | ||
|
|
2ac0851157 | ||
|
|
f093573828 |
No files matched your search
@@ -545,12 +545,9 @@ class input_stream_adapter
|
|||||||
std::char_traits<char>::int_type get_character_slow()
|
std::char_traits<char>::int_type get_character_slow()
|
||||||
{
|
{
|
||||||
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
||||||
// sbumpc() refills the get area if it is exhausted
|
// the get area is exhausted (get_character() handles the other case),
|
||||||
const bool refill = streambuf_access::get_ptr(sb) == streambuf_access::get_end(sb);
|
// so sbumpc() refills it
|
||||||
if (JSON_HEDLEY_UNLIKELY(refill))
|
save_token_segment();
|
||||||
{
|
|
||||||
save_token_segment();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto res = sb->sbumpc();
|
auto res = sb->sbumpc();
|
||||||
@@ -563,17 +560,13 @@ class input_stream_adapter
|
|||||||
is->clear(is->rdstate() | std::ios::eofbit);
|
is->clear(is->rdstate() | std::ios::eofbit);
|
||||||
}
|
}
|
||||||
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
||||||
else if (JSON_HEDLEY_UNLIKELY(refill))
|
else
|
||||||
{
|
{
|
||||||
// the consumed character is at gptr() - 1, unless the streambuf
|
// the consumed character is at gptr() - 1, unless the streambuf
|
||||||
// has no get area and returned it from uflow()
|
// has no get area and returned it from uflow()
|
||||||
const char* const next = streambuf_access::get_ptr(sb);
|
const char* const next = streambuf_access::get_ptr(sb);
|
||||||
after_refill(res, next != nullptr && next != streambuf_access::get_begin(sb));
|
after_refill(res, next != nullptr && next != streambuf_access::get_begin(sb));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
current_in_get_area = true; // LCOV_EXCL_LINE (called only when the get area is exhausted)
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1737,7 +1737,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
key_stack.push_back(val);
|
key_stack.push_back(val);
|
||||||
|
|
||||||
// add discarded value at the given key and store the reference for later
|
// add discarded value at the given key and store the reference for later
|
||||||
if (keep && ref_stack.back())
|
if (keep)
|
||||||
{
|
{
|
||||||
auto& obj = *ref_stack.back()->m_data.m_value.object;
|
auto& obj = *ref_stack.back()->m_data.m_value.object;
|
||||||
// a single lookup: insert the placeholder, or find the existing member
|
// a single lookup: insert the placeholder, or find the existing member
|
||||||
@@ -1794,7 +1794,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
|
|
||||||
const string_t object_key = pop_container();
|
const string_t object_key = pop_container();
|
||||||
|
|
||||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
if (!ref_stack.empty() && ref_stack.back())
|
||||||
{
|
{
|
||||||
// remove discarded value
|
// remove discarded value
|
||||||
remove_discarded_value(*ref_stack.back(), object_key);
|
remove_discarded_value(*ref_stack.back(), object_key);
|
||||||
@@ -1960,8 +1960,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
*/
|
*/
|
||||||
string_t current_key() const
|
string_t current_key() const
|
||||||
{
|
{
|
||||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_object()
|
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_object())
|
||||||
&& !key_stack.empty())
|
|
||||||
{
|
{
|
||||||
return key_stack.back();
|
return key_stack.back();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,14 +300,16 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
/// calls would (including the position and token bookkeeping of a
|
/// calls would (including the position and token bookkeeping of a
|
||||||
/// streaming adapter, see bulk_consume) and leaves @a current holding the last of
|
/// streaming adapter, see bulk_consume) and leaves @a current holding the last of
|
||||||
/// the 4 digits, just as the last such get() would; the codepoint is
|
/// the 4 digits, just as the last such get() would; the codepoint is
|
||||||
/// written to @a out. Makes no state change and returns false for a
|
/// written to @a out. Makes no state change and returns false for fewer
|
||||||
/// pending unget, fewer than 4 remaining bytes, or any of the 4 bytes not
|
/// than 4 remaining bytes or any of the 4 bytes not being a hex digit, so
|
||||||
/// being a hex digit, so the caller falls back unchanged to the
|
/// the caller falls back unchanged to the per-character loop, which then
|
||||||
/// per-character loop, which then reports the same diagnostic (stopping
|
/// reports the same diagnostic (stopping at the first invalid digit) as
|
||||||
/// at the first invalid digit) as before this optimization.
|
/// before this optimization.
|
||||||
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
||||||
{
|
{
|
||||||
if (next_unget || ia.bulk_remaining() < 4)
|
// no unget is pending inside a string (see get_after_string_run())
|
||||||
|
JSON_ASSERT(!next_unget);
|
||||||
|
if (ia.bulk_remaining() < 4)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1409,7 +1411,7 @@ scan_number_done:
|
|||||||
return token_type::value_unsigned;
|
return token_type::value_unsigned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (number_type == token_type::value_integer)
|
else // value_integer (the callers handle value_float themselves)
|
||||||
{
|
{
|
||||||
if (parse_integer_signed(first, last, value_integer))
|
if (parse_integer_signed(first, last, value_integer))
|
||||||
{
|
{
|
||||||
@@ -1780,7 +1782,10 @@ scan_number_done:
|
|||||||
/// the error at the right character
|
/// the error at the right character
|
||||||
JSON_HEDLEY_ALWAYS_INLINE bool scan_literal_bulk(const char* rest, const std::size_t length, std::true_type /*bulk*/)
|
JSON_HEDLEY_ALWAYS_INLINE bool scan_literal_bulk(const char* rest, const std::size_t length, std::true_type /*bulk*/)
|
||||||
{
|
{
|
||||||
if (next_unget || ia.bulk_remaining() < length
|
// called right after scan_after_whitespace() read current (see
|
||||||
|
// get_after_string_run()), so no unget is pending
|
||||||
|
JSON_ASSERT(!next_unget);
|
||||||
|
if (ia.bulk_remaining() < length
|
||||||
|| std::memcmp(ia.bulk_data(), rest, length) != 0)
|
|| std::memcmp(ia.bulk_data(), rest, length) != 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -575,10 +575,7 @@ class parser
|
|||||||
{
|
{
|
||||||
std::string error_msg = "syntax error ";
|
std::string error_msg = "syntax error ";
|
||||||
|
|
||||||
if (!context.empty())
|
error_msg += concat("while parsing ", context, ' ');
|
||||||
{
|
|
||||||
error_msg += concat("while parsing ", context, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
error_msg += "- ";
|
error_msg += "- ";
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
|
// m_it is already value-initialized, so this is not needed for
|
||||||
|
// correctness; it is kept because GCC generates faster loops with it
|
||||||
|
// (iterating a parsed document is 0.5-2.7 % slower without it, #6005)
|
||||||
if (m_object->is_object())
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
m_it.object_iterator = typename object_t::iterator();
|
m_it.object_iterator = typename object_t::iterator();
|
||||||
|
|||||||
@@ -1113,21 +1113,14 @@ class serializer
|
|||||||
{
|
{
|
||||||
// the code point is at least 0x60 (smaller ones are handled
|
// the code point is at least 0x60 (smaller ones are handled
|
||||||
// above) and is not printable ASCII (which the scanner
|
// above) and is not printable ASCII (which the scanner
|
||||||
// copies): it is DEL (0x7F) under EnsureAscii or a non-ASCII
|
// copies). Under EnsureAscii it is DEL (0x7F): every
|
||||||
// character
|
// well-formed multi-byte character is escaped by
|
||||||
|
// write_u_escapes() above, so decode() only ever accepts a
|
||||||
|
// single byte here, and nothing of it was buffered
|
||||||
if (EnsureAscii)
|
if (EnsureAscii)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(codepoint == 0x7F);
|
JSON_ASSERT(codepoint == 0x7F);
|
||||||
if (error_handler == error_handler_t::keep)
|
JSON_ASSERT(bytes == bytes_after_last_accept);
|
||||||
{
|
|
||||||
// this character was buffered as raw bytes below
|
|
||||||
// in case it turned out to be part of an
|
|
||||||
// ill-formed sequence (which is kept as is); now
|
|
||||||
// that it decoded to a well-formed code point,
|
|
||||||
// undo that and \u-escape it like any other
|
|
||||||
// character instead
|
|
||||||
bytes = bytes_after_last_accept;
|
|
||||||
}
|
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+15
-10
@@ -1576,7 +1576,7 @@ public:
|
|||||||
auto src_it = src_object.cbegin();
|
auto src_it = src_object.cbegin();
|
||||||
for (auto& element : *dst.m_data.m_value.object)
|
for (auto& element : *dst.m_data.m_value.object)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(src_it != src_object.cend() && copy_keys_equal(src_it->first, element.first)))
|
if (JSON_HEDLEY_LIKELY(copy_keys_equal(src_it->first, element.first)))
|
||||||
{
|
{
|
||||||
copy_shallow(src_it->second, element.second, worklist);
|
copy_shallow(src_it->second, element.second, worklist);
|
||||||
++src_it;
|
++src_it;
|
||||||
@@ -5353,8 +5353,7 @@ public:
|
|||||||
/// @name lexicographical comparison operators
|
/// @name lexicographical comparison operators
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
// the same-type cases for non-owning scalars, shared by JSON_IMPLEMENT_OPERATOR
|
// the same-type cases for non-owning scalars, used by JSON_IMPLEMENT_SCALAR_FAST
|
||||||
// and JSON_IMPLEMENT_SCALAR_FAST
|
|
||||||
#define JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
#define JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
||||||
case value_t::null: \
|
case value_t::null: \
|
||||||
return (null_result); \
|
return (null_result); \
|
||||||
@@ -5376,7 +5375,7 @@ public:
|
|||||||
// because any negative signed value is smaller than any unsigned value.
|
// because any negative signed value is smaller than any unsigned value.
|
||||||
// Otherwise, the non-negative signed value is cast to unsigned before the
|
// Otherwise, the non-negative signed value is cast to unsigned before the
|
||||||
// comparison to avoid wraparound.
|
// comparison to avoid wraparound.
|
||||||
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result, deep_result, may_descend) \
|
#define JSON_IMPLEMENT_OPERATOR(op, unordered_result, default_result, deep_result, may_descend) \
|
||||||
const auto lhs_type = lhs.type(); \
|
const auto lhs_type = lhs.type(); \
|
||||||
const auto rhs_type = rhs.type(); \
|
const auto rhs_type = rhs.type(); \
|
||||||
\
|
\
|
||||||
@@ -5404,8 +5403,15 @@ public:
|
|||||||
return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
|
return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
/* same-type scalars never get here: the inline fast path of the operator handles them */ \
|
||||||
\
|
case value_t::null: \
|
||||||
|
case value_t::boolean: \
|
||||||
|
case value_t::number_integer: \
|
||||||
|
case value_t::number_unsigned: \
|
||||||
|
case value_t::number_float: \
|
||||||
|
JSON_ASSERT(false); /* NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) */ \
|
||||||
|
return (unordered_result); \
|
||||||
|
\
|
||||||
case value_t::string: \
|
case value_t::string: \
|
||||||
return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
|
return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
|
||||||
\
|
\
|
||||||
@@ -5445,7 +5451,7 @@ public:
|
|||||||
? (number_integer_t(-1) op number_integer_t(1)) \
|
? (number_integer_t(-1) op number_integer_t(1)) \
|
||||||
: (static_cast<number_unsigned_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_unsigned); \
|
: (static_cast<number_unsigned_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_unsigned); \
|
||||||
} \
|
} \
|
||||||
else if(compares_unordered(lhs, rhs))\
|
else if(lhs_type == value_t::discarded || rhs_type == value_t::discarded)\
|
||||||
{\
|
{\
|
||||||
return (unordered_result);\
|
return (unordered_result);\
|
||||||
}\
|
}\
|
||||||
@@ -5513,7 +5519,7 @@ public:
|
|||||||
JSON_HEDLEY_DIAGNOSTIC_PUSH
|
JSON_HEDLEY_DIAGNOSTIC_PUSH
|
||||||
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
|
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
|
||||||
#endif
|
#endif
|
||||||
JSON_IMPLEMENT_OPERATOR( ==, true, false, false,
|
JSON_IMPLEMENT_OPERATOR( ==, false, false,
|
||||||
compare_iteratively<false>(lhs, rhs, false) == compare_result::equal, true)
|
compare_iteratively<false>(lhs, rhs, false) == compare_result::equal, true)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
JSON_HEDLEY_DIAGNOSTIC_POP
|
JSON_HEDLEY_DIAGNOSTIC_POP
|
||||||
@@ -5527,7 +5533,6 @@ public:
|
|||||||
// default_result is used if we cannot compare values. In that case,
|
// default_result is used if we cannot compare values. In that case,
|
||||||
// we compare types.
|
// we compare types.
|
||||||
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
|
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
|
||||||
std::partial_ordering::equivalent,
|
|
||||||
std::partial_ordering::unordered,
|
std::partial_ordering::unordered,
|
||||||
lhs_type <=> rhs_type, // *NOPAD*
|
lhs_type <=> rhs_type, // *NOPAD*
|
||||||
to_partial_ordering(compare_iteratively<true>(lhs, rhs, false)), true)
|
to_partial_ordering(compare_iteratively<true>(lhs, rhs, false)), true)
|
||||||
@@ -5539,7 +5544,7 @@ public:
|
|||||||
// default_result is used if we cannot compare values. In that case,
|
// default_result is used if we cannot compare values. In that case,
|
||||||
// we compare types. Note we have to call the operator explicitly,
|
// we compare types. Note we have to call the operator explicitly,
|
||||||
// because MSVC has problems otherwise.
|
// because MSVC has problems otherwise.
|
||||||
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type),
|
JSON_IMPLEMENT_OPERATOR( <, false, operator<(lhs_type, rhs_type),
|
||||||
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
|
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Generated
+44
-49
@@ -9652,12 +9652,9 @@ class input_stream_adapter
|
|||||||
std::char_traits<char>::int_type get_character_slow()
|
std::char_traits<char>::int_type get_character_slow()
|
||||||
{
|
{
|
||||||
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
||||||
// sbumpc() refills the get area if it is exhausted
|
// the get area is exhausted (get_character() handles the other case),
|
||||||
const bool refill = streambuf_access::get_ptr(sb) == streambuf_access::get_end(sb);
|
// so sbumpc() refills it
|
||||||
if (JSON_HEDLEY_UNLIKELY(refill))
|
save_token_segment();
|
||||||
{
|
|
||||||
save_token_segment();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto res = sb->sbumpc();
|
auto res = sb->sbumpc();
|
||||||
@@ -9670,17 +9667,13 @@ class input_stream_adapter
|
|||||||
is->clear(is->rdstate() | std::ios::eofbit);
|
is->clear(is->rdstate() | std::ios::eofbit);
|
||||||
}
|
}
|
||||||
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
#if !JSON_DISABLE_STREAM_BULK_SCAN
|
||||||
else if (JSON_HEDLEY_UNLIKELY(refill))
|
else
|
||||||
{
|
{
|
||||||
// the consumed character is at gptr() - 1, unless the streambuf
|
// the consumed character is at gptr() - 1, unless the streambuf
|
||||||
// has no get area and returned it from uflow()
|
// has no get area and returned it from uflow()
|
||||||
const char* const next = streambuf_access::get_ptr(sb);
|
const char* const next = streambuf_access::get_ptr(sb);
|
||||||
after_refill(res, next != nullptr && next != streambuf_access::get_begin(sb));
|
after_refill(res, next != nullptr && next != streambuf_access::get_begin(sb));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
current_in_get_area = true; // LCOV_EXCL_LINE (called only when the get area is exhausted)
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -13334,14 +13327,16 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
/// calls would (including the position and token bookkeeping of a
|
/// calls would (including the position and token bookkeeping of a
|
||||||
/// streaming adapter, see bulk_consume) and leaves @a current holding the last of
|
/// streaming adapter, see bulk_consume) and leaves @a current holding the last of
|
||||||
/// the 4 digits, just as the last such get() would; the codepoint is
|
/// the 4 digits, just as the last such get() would; the codepoint is
|
||||||
/// written to @a out. Makes no state change and returns false for a
|
/// written to @a out. Makes no state change and returns false for fewer
|
||||||
/// pending unget, fewer than 4 remaining bytes, or any of the 4 bytes not
|
/// than 4 remaining bytes or any of the 4 bytes not being a hex digit, so
|
||||||
/// being a hex digit, so the caller falls back unchanged to the
|
/// the caller falls back unchanged to the per-character loop, which then
|
||||||
/// per-character loop, which then reports the same diagnostic (stopping
|
/// reports the same diagnostic (stopping at the first invalid digit) as
|
||||||
/// at the first invalid digit) as before this optimization.
|
/// before this optimization.
|
||||||
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
||||||
{
|
{
|
||||||
if (next_unget || ia.bulk_remaining() < 4)
|
// no unget is pending inside a string (see get_after_string_run())
|
||||||
|
JSON_ASSERT(!next_unget);
|
||||||
|
if (ia.bulk_remaining() < 4)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -14443,7 +14438,7 @@ scan_number_done:
|
|||||||
return token_type::value_unsigned;
|
return token_type::value_unsigned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (number_type == token_type::value_integer)
|
else // value_integer (the callers handle value_float themselves)
|
||||||
{
|
{
|
||||||
if (parse_integer_signed(first, last, value_integer))
|
if (parse_integer_signed(first, last, value_integer))
|
||||||
{
|
{
|
||||||
@@ -14814,7 +14809,10 @@ scan_number_done:
|
|||||||
/// the error at the right character
|
/// the error at the right character
|
||||||
JSON_HEDLEY_ALWAYS_INLINE bool scan_literal_bulk(const char* rest, const std::size_t length, std::true_type /*bulk*/)
|
JSON_HEDLEY_ALWAYS_INLINE bool scan_literal_bulk(const char* rest, const std::size_t length, std::true_type /*bulk*/)
|
||||||
{
|
{
|
||||||
if (next_unget || ia.bulk_remaining() < length
|
// called right after scan_after_whitespace() read current (see
|
||||||
|
// get_after_string_run()), so no unget is pending
|
||||||
|
JSON_ASSERT(!next_unget);
|
||||||
|
if (ia.bulk_remaining() < length
|
||||||
|| std::memcmp(ia.bulk_data(), rest, length) != 0)
|
|| std::memcmp(ia.bulk_data(), rest, length) != 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -17371,7 +17369,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
key_stack.push_back(val);
|
key_stack.push_back(val);
|
||||||
|
|
||||||
// add discarded value at the given key and store the reference for later
|
// add discarded value at the given key and store the reference for later
|
||||||
if (keep && ref_stack.back())
|
if (keep)
|
||||||
{
|
{
|
||||||
auto& obj = *ref_stack.back()->m_data.m_value.object;
|
auto& obj = *ref_stack.back()->m_data.m_value.object;
|
||||||
// a single lookup: insert the placeholder, or find the existing member
|
// a single lookup: insert the placeholder, or find the existing member
|
||||||
@@ -17428,7 +17426,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
|
|
||||||
const string_t object_key = pop_container();
|
const string_t object_key = pop_container();
|
||||||
|
|
||||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
if (!ref_stack.empty() && ref_stack.back())
|
||||||
{
|
{
|
||||||
// remove discarded value
|
// remove discarded value
|
||||||
remove_discarded_value(*ref_stack.back(), object_key);
|
remove_discarded_value(*ref_stack.back(), object_key);
|
||||||
@@ -17594,8 +17592,7 @@ class json_sax_dom_callback_parser : public json_sax_dom_error_state
|
|||||||
*/
|
*/
|
||||||
string_t current_key() const
|
string_t current_key() const
|
||||||
{
|
{
|
||||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_object()
|
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_object())
|
||||||
&& !key_stack.empty())
|
|
||||||
{
|
{
|
||||||
return key_stack.back();
|
return key_stack.back();
|
||||||
}
|
}
|
||||||
@@ -23739,10 +23736,7 @@ class parser
|
|||||||
{
|
{
|
||||||
std::string error_msg = "syntax error ";
|
std::string error_msg = "syntax error ";
|
||||||
|
|
||||||
if (!context.empty())
|
error_msg += concat("while parsing ", context, ' ');
|
||||||
{
|
|
||||||
error_msg += concat("while parsing ", context, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
error_msg += "- ";
|
error_msg += "- ";
|
||||||
|
|
||||||
@@ -24070,6 +24064,9 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
|
// m_it is already value-initialized, so this is not needed for
|
||||||
|
// correctness; it is kept because GCC generates faster loops with it
|
||||||
|
// (iterating a parsed document is 0.5-2.7 % slower without it, #6005)
|
||||||
if (m_object->is_object())
|
if (m_object->is_object())
|
||||||
{
|
{
|
||||||
m_it.object_iterator = typename object_t::iterator();
|
m_it.object_iterator = typename object_t::iterator();
|
||||||
@@ -36273,21 +36270,14 @@ class serializer
|
|||||||
{
|
{
|
||||||
// the code point is at least 0x60 (smaller ones are handled
|
// the code point is at least 0x60 (smaller ones are handled
|
||||||
// above) and is not printable ASCII (which the scanner
|
// above) and is not printable ASCII (which the scanner
|
||||||
// copies): it is DEL (0x7F) under EnsureAscii or a non-ASCII
|
// copies). Under EnsureAscii it is DEL (0x7F): every
|
||||||
// character
|
// well-formed multi-byte character is escaped by
|
||||||
|
// write_u_escapes() above, so decode() only ever accepts a
|
||||||
|
// single byte here, and nothing of it was buffered
|
||||||
if (EnsureAscii)
|
if (EnsureAscii)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(codepoint == 0x7F);
|
JSON_ASSERT(codepoint == 0x7F);
|
||||||
if (error_handler == error_handler_t::keep)
|
JSON_ASSERT(bytes == bytes_after_last_accept);
|
||||||
{
|
|
||||||
// this character was buffered as raw bytes below
|
|
||||||
// in case it turned out to be part of an
|
|
||||||
// ill-formed sequence (which is kept as is); now
|
|
||||||
// that it decoded to a well-formed code point,
|
|
||||||
// undo that and \u-escape it like any other
|
|
||||||
// character instead
|
|
||||||
bytes = bytes_after_last_accept;
|
|
||||||
}
|
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -39311,7 +39301,7 @@ public:
|
|||||||
auto src_it = src_object.cbegin();
|
auto src_it = src_object.cbegin();
|
||||||
for (auto& element : *dst.m_data.m_value.object)
|
for (auto& element : *dst.m_data.m_value.object)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(src_it != src_object.cend() && copy_keys_equal(src_it->first, element.first)))
|
if (JSON_HEDLEY_LIKELY(copy_keys_equal(src_it->first, element.first)))
|
||||||
{
|
{
|
||||||
copy_shallow(src_it->second, element.second, worklist);
|
copy_shallow(src_it->second, element.second, worklist);
|
||||||
++src_it;
|
++src_it;
|
||||||
@@ -43088,8 +43078,7 @@ public:
|
|||||||
/// @name lexicographical comparison operators
|
/// @name lexicographical comparison operators
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
// the same-type cases for non-owning scalars, shared by JSON_IMPLEMENT_OPERATOR
|
// the same-type cases for non-owning scalars, used by JSON_IMPLEMENT_SCALAR_FAST
|
||||||
// and JSON_IMPLEMENT_SCALAR_FAST
|
|
||||||
#define JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
#define JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
||||||
case value_t::null: \
|
case value_t::null: \
|
||||||
return (null_result); \
|
return (null_result); \
|
||||||
@@ -43111,7 +43100,7 @@ public:
|
|||||||
// because any negative signed value is smaller than any unsigned value.
|
// because any negative signed value is smaller than any unsigned value.
|
||||||
// Otherwise, the non-negative signed value is cast to unsigned before the
|
// Otherwise, the non-negative signed value is cast to unsigned before the
|
||||||
// comparison to avoid wraparound.
|
// comparison to avoid wraparound.
|
||||||
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result, deep_result, may_descend) \
|
#define JSON_IMPLEMENT_OPERATOR(op, unordered_result, default_result, deep_result, may_descend) \
|
||||||
const auto lhs_type = lhs.type(); \
|
const auto lhs_type = lhs.type(); \
|
||||||
const auto rhs_type = rhs.type(); \
|
const auto rhs_type = rhs.type(); \
|
||||||
\
|
\
|
||||||
@@ -43139,8 +43128,15 @@ public:
|
|||||||
return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
|
return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
JSON_IMPLEMENT_SCALAR_CASES(op, null_result) \
|
/* same-type scalars never get here: the inline fast path of the operator handles them */ \
|
||||||
\
|
case value_t::null: \
|
||||||
|
case value_t::boolean: \
|
||||||
|
case value_t::number_integer: \
|
||||||
|
case value_t::number_unsigned: \
|
||||||
|
case value_t::number_float: \
|
||||||
|
JSON_ASSERT(false); /* NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) */ \
|
||||||
|
return (unordered_result); \
|
||||||
|
\
|
||||||
case value_t::string: \
|
case value_t::string: \
|
||||||
return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
|
return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
|
||||||
\
|
\
|
||||||
@@ -43180,7 +43176,7 @@ public:
|
|||||||
? (number_integer_t(-1) op number_integer_t(1)) \
|
? (number_integer_t(-1) op number_integer_t(1)) \
|
||||||
: (static_cast<number_unsigned_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_unsigned); \
|
: (static_cast<number_unsigned_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_unsigned); \
|
||||||
} \
|
} \
|
||||||
else if(compares_unordered(lhs, rhs))\
|
else if(lhs_type == value_t::discarded || rhs_type == value_t::discarded)\
|
||||||
{\
|
{\
|
||||||
return (unordered_result);\
|
return (unordered_result);\
|
||||||
}\
|
}\
|
||||||
@@ -43248,7 +43244,7 @@ public:
|
|||||||
JSON_HEDLEY_DIAGNOSTIC_PUSH
|
JSON_HEDLEY_DIAGNOSTIC_PUSH
|
||||||
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
|
JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal")
|
||||||
#endif
|
#endif
|
||||||
JSON_IMPLEMENT_OPERATOR( ==, true, false, false,
|
JSON_IMPLEMENT_OPERATOR( ==, false, false,
|
||||||
compare_iteratively<false>(lhs, rhs, false) == compare_result::equal, true)
|
compare_iteratively<false>(lhs, rhs, false) == compare_result::equal, true)
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
JSON_HEDLEY_DIAGNOSTIC_POP
|
JSON_HEDLEY_DIAGNOSTIC_POP
|
||||||
@@ -43262,7 +43258,6 @@ public:
|
|||||||
// default_result is used if we cannot compare values. In that case,
|
// default_result is used if we cannot compare values. In that case,
|
||||||
// we compare types.
|
// we compare types.
|
||||||
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
|
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
|
||||||
std::partial_ordering::equivalent,
|
|
||||||
std::partial_ordering::unordered,
|
std::partial_ordering::unordered,
|
||||||
lhs_type <=> rhs_type, // *NOPAD*
|
lhs_type <=> rhs_type, // *NOPAD*
|
||||||
to_partial_ordering(compare_iteratively<true>(lhs, rhs, false)), true)
|
to_partial_ordering(compare_iteratively<true>(lhs, rhs, false)), true)
|
||||||
@@ -43274,7 +43269,7 @@ public:
|
|||||||
// default_result is used if we cannot compare values. In that case,
|
// default_result is used if we cannot compare values. In that case,
|
||||||
// we compare types. Note we have to call the operator explicitly,
|
// we compare types. Note we have to call the operator explicitly,
|
||||||
// because MSVC has problems otherwise.
|
// because MSVC has problems otherwise.
|
||||||
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type),
|
JSON_IMPLEMENT_OPERATOR( <, false, operator<(lhs_type, rhs_type),
|
||||||
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
|
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -534,10 +534,9 @@ TEST_CASE("object_key_index")
|
|||||||
|
|
||||||
// the hashes are not distinct on purpose: elements with the same
|
// the hashes are not distinct on purpose: elements with the same
|
||||||
// hash are told apart by the caller
|
// hash are told apart by the caller
|
||||||
const auto hash_of = [](std::size_t position) -> std::size_t
|
const auto hash_of = [](std::size_t position)
|
||||||
{
|
{
|
||||||
// truncated to 32 bits where std::size_t is that small
|
return (position % 50) * 0x9E3779B97F4A7C15ull;
|
||||||
return static_cast<std::size_t>((position % 50) * 0x9E3779B97F4A7C15ull);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::size_t> hashes;
|
std::vector<std::size_t> hashes;
|
||||||
|
|||||||
@@ -1555,7 +1555,6 @@ TEST_CASE("regression tests 1")
|
|||||||
{
|
{
|
||||||
my_json j = make();
|
my_json j = make();
|
||||||
#ifdef JSON_NO_THREAD_LOCAL
|
#ifdef JSON_NO_THREAD_LOCAL
|
||||||
// (set by the user, or by the library for clang with MinGW)
|
|
||||||
// the objects below the outermost one are not copied by their
|
// the objects below the outermost one are not copied by their
|
||||||
// object_t here, but member by member, which keeps their
|
// object_t here, but member by member, which keeps their
|
||||||
// timestamps correct: "c" is not mistaken for "b" and is inserted
|
// timestamps correct: "c" is not mistaken for "b" and is inserted
|
||||||
|
|||||||
Reference in new issue
Block a user