mirror of
https://github.com/nlohmann/json.git
synced 2026-09-14 20:27:58 +00:00
Only reserve array capacity if the array type supports it (#5522)
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/input/lexer.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/string_concat.hpp>
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
@@ -151,6 +152,29 @@ constexpr std::size_t unknown_size()
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reserve capacity for @a len elements in array @a arr
|
||||
|
||||
Reserving upfront avoids repeated reallocations while the elements are added,
|
||||
but the reservation is capped so a bogus/hostile length (which is not bounded
|
||||
by max_size(), unlike e.g. std::vector) cannot trigger an oversized allocation
|
||||
for a small or truncated input.
|
||||
|
||||
The overload below is selected for array types without reserve() (e.g.,
|
||||
std::deque), which are then left untouched.
|
||||
*/
|
||||
template<typename ArrayType>
|
||||
auto reserve_array(ArrayType& arr, std::size_t len, priority_tag<1> /*unused*/)
|
||||
-> decltype(arr.reserve(len), void())
|
||||
{
|
||||
constexpr std::size_t reserve_cap = 16384;
|
||||
arr.reserve((std::min)(len, reserve_cap));
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief SAX implementation to create a JSON value from SAX events
|
||||
|
||||
@@ -308,12 +332,7 @@ class json_sax_dom_parser
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
{
|
||||
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||
// allocation for a small or truncated input
|
||||
constexpr std::size_t reserve_cap = 16384;
|
||||
ref_stack.back()->m_data.m_value.array->reserve((std::min)(len, reserve_cap));
|
||||
reserve_array(*ref_stack.back()->m_data.m_value.array, len, priority_tag<1> {});
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -697,12 +716,7 @@ class json_sax_dom_callback_parser
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
{
|
||||
// reserve upfront to avoid repeated reallocations while adding elements,
|
||||
// but cap the reservation so a bogus/hostile length (which is not bounded
|
||||
// by max_size(), unlike e.g. std::vector) cannot trigger an oversized
|
||||
// allocation for a small or truncated input
|
||||
constexpr std::size_t reserve_cap = 16384;
|
||||
ref_stack.back()->m_data.m_value.array->reserve((std::min)(len, reserve_cap));
|
||||
reserve_array(*ref_stack.back()->m_data.m_value.array, len, priority_tag<1> {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user