mirror of
https://github.com/nlohmann/json.git
synced 2026-11-06 20:49:21 +00:00
Binary readers: append strings straight from contiguous input
get_bytes() read every string into a zero-filled resize() and copied the bytes over it, so each byte was written twice. A string that the input holds in one block (bulk_remaining() at least its length) is now appended from it directly. The claimed length is checked against the input first, so a huge claimed length still allocates nothing it cannot fill; other inputs and binary values keep the chunked loop. from_cbor() and from_msgpack() of twitter.json and citm_catalog.json get 5.5-9.1% faster on an Apple M1 Max and 2.7-8.6% on x86-64 (GCC 15, Clang 21); canada.json, which has few strings, is unchanged. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+68
No files matched your search
@@ -4887,6 +4887,13 @@ class binary_reader
|
||||
const char* context,
|
||||
ContainerType& result)
|
||||
{
|
||||
// a string that is in the block of input as a whole is appended from
|
||||
// it, without the zero-filling resize() below
|
||||
if (append_from_block(len, result, std::integral_constant < bool, bulk_scan && std::is_same<ContainerType, string_t>::value > {}))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// upper bound on the number of bytes read (and allocated) per chunk
|
||||
constexpr std::size_t chunk_size = 4096;
|
||||
|
||||
@@ -4923,6 +4930,33 @@ class binary_reader
|
||||
return true;
|
||||
}
|
||||
|
||||
/// append the @a len bytes at the current position to @a result, if the
|
||||
/// input holds them in one block; false (with nothing read) otherwise
|
||||
template<typename NumberType>
|
||||
bool append_from_block(const NumberType len, string_t& result, std::true_type /*block*/)
|
||||
{
|
||||
if (len <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const std::size_t remaining = ia.bulk_remaining();
|
||||
if (static_cast<std::uintmax_t>(len) > static_cast<std::uintmax_t>(remaining))
|
||||
{
|
||||
return false; // (the loop reports the premature end)
|
||||
}
|
||||
const auto n = static_cast<std::size_t>(len);
|
||||
result.append(reinterpret_cast<const typename string_t::value_type*>(ia.bulk_data()), n);
|
||||
ia.bulk_skip(n);
|
||||
chars_read += n;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename NumberType, typename ContainerType>
|
||||
static bool append_from_block(const NumberType /*len*/, ContainerType& /*result*/, std::false_type /*block*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in] context further context information (for diagnostics)
|
||||
@return whether the last read character is not EOF
|
||||
|
||||
Reference in new issue
Block a user