mirror of
https://github.com/nlohmann/json.git
synced 2026-10-15 10:47:13 +00:00
Make flatten() linear for ordered_json
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
4 files changed
+126
-8
No files matched your search
Generated
+37
-4
@@ -21562,6 +21562,23 @@ class json_pointer
|
||||
}
|
||||
|
||||
private:
|
||||
// Add the entry (key, v) to the object `obj`. Flattened paths are pairwise
|
||||
// distinct, so objects that can append a key known to be absent
|
||||
// (ordered_map) skip the lookup, which is linear and would make flatten
|
||||
// quadratic; all other object types use operator[].
|
||||
template<typename ObjectType, typename ValueType>
|
||||
static auto add_flattened(ObjectType& obj, const string_t& key, ValueType&& v, int /*unused*/)
|
||||
-> decltype(obj.emplace_new_key(key, std::forward<ValueType>(v)), void())
|
||||
{
|
||||
obj.emplace_new_key(key, std::forward<ValueType>(v));
|
||||
}
|
||||
|
||||
template<typename ObjectType, typename ValueType>
|
||||
static void add_flattened(ObjectType& obj, const string_t& key, ValueType&& v, ...)
|
||||
{
|
||||
obj[key] = std::forward<ValueType>(v);
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in] reference_string the reference string to the current value
|
||||
@param[in] value the value to consider
|
||||
@@ -21606,7 +21623,8 @@ class json_pointer
|
||||
|
||||
// flatten `v`, whose path is `path`: primitives and empty containers
|
||||
// are added to the result right away; other containers get a frame
|
||||
const auto enter = [&stack, &path, &result](const BasicJsonType & v)
|
||||
auto& object = *result.m_data.m_value.object;
|
||||
const auto enter = [&stack, &path, &object](const BasicJsonType & v)
|
||||
{
|
||||
switch (v.type())
|
||||
{
|
||||
@@ -21615,7 +21633,7 @@ class json_pointer
|
||||
if (v.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[path] = nullptr;
|
||||
add_flattened(object, path, nullptr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -21629,7 +21647,7 @@ class json_pointer
|
||||
if (v.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[path] = nullptr;
|
||||
add_flattened(object, path, nullptr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -21649,7 +21667,7 @@ class json_pointer
|
||||
default:
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[path] = v;
|
||||
add_flattened(object, path, v, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -21695,6 +21713,10 @@ class json_pointer
|
||||
enter(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// the entries were added without going through basic_json, so the
|
||||
// parent pointers (JSON_DIAGNOSTICS) have to be set now
|
||||
result.set_parents();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -29161,6 +29183,17 @@ public:
|
||||
return {std::prev(this->end()), true};
|
||||
}
|
||||
|
||||
/// @brief add an element at the end without checking whether the key exists
|
||||
/// @note The caller must guarantee that @a key is not yet contained, otherwise
|
||||
/// the container holds duplicate keys. This avoids the linear search of
|
||||
/// emplace() and operator[] when many keys known to be new are added.
|
||||
template<class V, detail::enable_if_t<
|
||||
detail::is_constructible<T, V>::value, int> = 0>
|
||||
void emplace_new_key(const key_type& key, V && t)
|
||||
{
|
||||
append(key, std::forward<V>(t));
|
||||
}
|
||||
|
||||
T& operator[](const key_type& key)
|
||||
{
|
||||
return emplace(key, T{}).first->second;
|
||||
|
||||
Reference in new issue
Block a user