mirror of
https://github.com/nlohmann/json.git
synced 2026-10-15 18:57:13 +00:00
Fix quadratic parent updates for ordered_json with JSON_DIAGNOSTICS (#5832)
* Fix quadratic parent updates for ordered_json with JSON_DIAGNOSTICS Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Only trust containers known to keep their elements in place Address review: decide whether an insertion may have moved the other members by naming the containers that are known not to, instead of the ones that are known to. - detail::has_stable_elements: std::map, std::multimap, std::unordered_map and std::unordered_multimap; object_capacity() reports 0 for them. - detail::is_nlohmann_ordered_map: only the real nlohmann::ordered_map (which only appends) reports its capacity(). - Any other object type reports unknown_size(), so it gets a full set_parents() on every insertion. Before, an object type without capacity() was treated as never moving, and one with capacity() (a sorted flat map, say) was trusted to move only on reallocation. - set_parents_after_object_erase() re-parents unless the object type is stable; the unused set_parent() is removed. - Comments say "the object type" instead of "ordered_json". - New test with an object type that moves its members without changing its capacity; it fails without this change. Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
ca7740fef2
commit
4530d9681c
4 files changed
+439
-118
No files matched your search
@@ -9,9 +9,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits> // numeric_limits
|
||||
#include <map> // map, multimap
|
||||
#include <string> // char_traits
|
||||
#include <tuple> // tuple
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <unordered_map> // unordered_map, unordered_multimap
|
||||
#include <utility> // declval
|
||||
#include <vector> // vector
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
@@ -897,6 +899,31 @@ struct has_capacity : std::integral_constant<bool, is_detected<detect_capacity,
|
||||
template <typename T>
|
||||
struct is_ordered_map : has_capacity<T> {};
|
||||
|
||||
// whether T is a specialization of nlohmann::ordered_map, which only ever
|
||||
// appends members, so they can only move when its capacity changes
|
||||
template<typename T>
|
||||
struct is_nlohmann_ordered_map : std::false_type {};
|
||||
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct is_nlohmann_ordered_map<ordered_map<Key, T, IgnoredLess, Allocator>> : std::true_type {};
|
||||
|
||||
// whether adding or erasing elements never moves the other elements of the
|
||||
// container T; only node-based standard containers are known to guarantee this
|
||||
template<typename T>
|
||||
struct has_stable_elements : std::false_type {};
|
||||
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
struct has_stable_elements<std::map<Key, T, Compare, Allocator>> : std::true_type {};
|
||||
|
||||
template<class Key, class T, class Compare, class Allocator>
|
||||
struct has_stable_elements<std::multimap<Key, T, Compare, Allocator>> : std::true_type {};
|
||||
|
||||
template<class Key, class T, class Hash, class KeyEqual, class Allocator>
|
||||
struct has_stable_elements<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
|
||||
|
||||
template<class Key, class T, class Hash, class KeyEqual, class Allocator>
|
||||
struct has_stable_elements<std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
|
||||
|
||||
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
|
||||
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
|
||||
T conditional_static_cast(U value)
|
||||
|
||||
Reference in new issue
Block a user