mirror of
https://github.com/nlohmann/json.git
synced 2026-10-24 14:58:54 +00:00
1.7: use detail::is_primitive in json.hpp switches (#5891)
has_no_children, set_parents, max_size and the two diff walkers. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 file changed
+107
-167
+107
-167
@@ -732,23 +732,15 @@ private:
|
|||||||
// true if v is not an array/object, or is an already-empty one
|
// true if v is not an array/object, or is an already-empty one
|
||||||
static bool has_no_children(const basic_json& v) noexcept
|
static bool has_no_children(const basic_json& v) noexcept
|
||||||
{
|
{
|
||||||
switch (v.m_data.m_type)
|
if (detail::is_primitive(v.m_data.m_type))
|
||||||
{
|
{
|
||||||
case value_t::array:
|
return true;
|
||||||
return v.m_data.m_value.array->empty();
|
|
||||||
case value_t::object:
|
|
||||||
return v.m_data.m_value.object->empty();
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (v.m_data.m_type == value_t::array)
|
||||||
|
{
|
||||||
|
return v.m_data.m_value.array->empty();
|
||||||
|
}
|
||||||
|
return v.m_data.m_value.object->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// true if no child of the non-empty array/object v has children of
|
// true if no child of the non-empty array/object v has children of
|
||||||
@@ -1106,36 +1098,24 @@ public:
|
|||||||
void set_parents()
|
void set_parents()
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
switch (m_data.m_type)
|
if (detail::is_primitive(m_data.m_type))
|
||||||
{
|
{
|
||||||
case value_t::array:
|
return;
|
||||||
{
|
}
|
||||||
for (auto& element : *m_data.m_value.array)
|
|
||||||
{
|
|
||||||
element.m_parent = this;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::object:
|
if (m_data.m_type == value_t::array)
|
||||||
|
{
|
||||||
|
for (auto& element : *m_data.m_value.array)
|
||||||
{
|
{
|
||||||
for (auto& element : *m_data.m_value.object)
|
element.m_parent = this;
|
||||||
{
|
}
|
||||||
element.second.m_parent = this;
|
}
|
||||||
}
|
else
|
||||||
break;
|
{
|
||||||
|
for (auto& element : *m_data.m_value.object)
|
||||||
|
{
|
||||||
|
element.second.m_parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -4602,34 +4582,20 @@ public:
|
|||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
size_type max_size() const noexcept
|
size_type max_size() const noexcept
|
||||||
{
|
{
|
||||||
switch (m_data.m_type)
|
if (detail::is_primitive(m_data.m_type))
|
||||||
{
|
{
|
||||||
case value_t::array:
|
// all other types have max_size() == size()
|
||||||
{
|
return size();
|
||||||
// delegate call to array_t::max_size()
|
|
||||||
return m_data.m_value.array->max_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::object:
|
|
||||||
{
|
|
||||||
// delegate call to object_t::max_size()
|
|
||||||
return m_data.m_value.object->max_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// all other types have max_size() == size()
|
|
||||||
return size();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_data.m_type == value_t::array)
|
||||||
|
{
|
||||||
|
// delegate call to array_t::max_size()
|
||||||
|
return m_data.m_value.array->max_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// delegate call to object_t::max_size()
|
||||||
|
return m_data.m_value.object->max_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -7825,82 +7791,68 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (source.type())
|
if (detail::is_primitive(source.type()))
|
||||||
{
|
{
|
||||||
case value_t::array:
|
// both primitive types: replace value
|
||||||
|
diff_replace(result, path, target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.is_array())
|
||||||
|
{
|
||||||
|
const std::size_t path_length = path.size();
|
||||||
|
|
||||||
|
// first pass: traverse common elements
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < source.size() && i < target.size())
|
||||||
{
|
{
|
||||||
|
// recursive call to compare array values at index i
|
||||||
|
if (!(source[i] == target[i]))
|
||||||
|
{
|
||||||
|
diff_append_index(path, i);
|
||||||
|
diff_unequal(result, source[i], target[i], path, depth + 1);
|
||||||
|
path.resize(path_length);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now reached the end of at least one array
|
||||||
|
// in a second pass, traverse the remaining elements
|
||||||
|
diff_array_tails(result, source, target, path, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff_target_values target_values;
|
||||||
|
std::vector<const_iterator> added;
|
||||||
|
if (diff_object_keys(result, source, target, path, target_values, added))
|
||||||
|
{
|
||||||
|
// fast path: target_values holds, for every member of
|
||||||
|
// source in order, its value in target -- so no further
|
||||||
|
// lookup is needed. Deleted keys are interleaved here
|
||||||
|
// too, in source's original order, to match the
|
||||||
|
// historical (pre-reordering-aware) output order.
|
||||||
const std::size_t path_length = path.size();
|
const std::size_t path_length = path.size();
|
||||||
|
|
||||||
// first pass: traverse common elements
|
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
while (i < source.size() && i < target.size())
|
for (auto it = source.cbegin(); it != source.cend(); ++it, ++i)
|
||||||
{
|
{
|
||||||
// recursive call to compare array values at index i
|
if (target_values[i] != nullptr)
|
||||||
if (!(source[i] == target[i]))
|
|
||||||
{
|
{
|
||||||
diff_append_index(path, i);
|
if (!(it.value() == *target_values[i]))
|
||||||
diff_unequal(result, source[i], target[i], path, depth + 1);
|
|
||||||
path.resize(path_length);
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We now reached the end of at least one array
|
|
||||||
// in a second pass, traverse the remaining elements
|
|
||||||
diff_array_tails(result, source, target, path, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::object:
|
|
||||||
{
|
|
||||||
diff_target_values target_values;
|
|
||||||
std::vector<const_iterator> added;
|
|
||||||
if (diff_object_keys(result, source, target, path, target_values, added))
|
|
||||||
{
|
|
||||||
// fast path: target_values holds, for every member of
|
|
||||||
// source in order, its value in target -- so no further
|
|
||||||
// lookup is needed. Deleted keys are interleaved here
|
|
||||||
// too, in source's original order, to match the
|
|
||||||
// historical (pre-reordering-aware) output order.
|
|
||||||
const std::size_t path_length = path.size();
|
|
||||||
std::size_t i = 0;
|
|
||||||
for (auto it = source.cbegin(); it != source.cend(); ++it, ++i)
|
|
||||||
{
|
|
||||||
if (target_values[i] != nullptr)
|
|
||||||
{
|
{
|
||||||
if (!(it.value() == *target_values[i]))
|
diff_append_key(path, it.key());
|
||||||
{
|
diff_unequal(result, it.value(), *target_values[i], path, depth + 1);
|
||||||
diff_append_key(path, it.key());
|
path.resize(path_length);
|
||||||
diff_unequal(result, it.value(), *target_values[i], path, depth + 1);
|
|
||||||
path.resize(path_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// found a key that is not in target -> remove it
|
|
||||||
diff_remove(result, diff_key_path(path, it.key()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// append the "add" operations for brand-new keys
|
{
|
||||||
diff_added(result, added, path);
|
// found a key that is not in target -> remove it
|
||||||
|
diff_remove(result, diff_key_path(path, it.key()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
// append the "add" operations for brand-new keys
|
||||||
case value_t::string:
|
diff_added(result, added, path);
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// both primitive types: replace value
|
|
||||||
diff_replace(result, path, target);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7946,45 +7898,33 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (s.type())
|
if (detail::is_primitive(s.type()))
|
||||||
{
|
{
|
||||||
case value_t::array:
|
// both primitive types: replace value
|
||||||
|
diff_replace(result, current_path, t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.is_array())
|
||||||
|
{
|
||||||
|
stack.emplace_back(&s, &t, current_path.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<const basic_json*> target_values;
|
||||||
|
std::vector<const_iterator> added;
|
||||||
|
if (diff_object_keys(result, s, t, current_path, target_values, added))
|
||||||
{
|
{
|
||||||
|
// fast path: the frame walks source in lockstep with
|
||||||
|
// common_keys, as diff_recursively does, and appends
|
||||||
|
// added_ops once all members are done
|
||||||
stack.emplace_back(&s, &t, current_path.size());
|
stack.emplace_back(&s, &t, current_path.size());
|
||||||
return;
|
stack.back().member = s.cbegin();
|
||||||
}
|
stack.back().target_values = std::move(target_values);
|
||||||
|
stack.back().added = std::move(added);
|
||||||
case value_t::object:
|
|
||||||
{
|
|
||||||
std::vector<const basic_json*> target_values;
|
|
||||||
std::vector<const_iterator> added;
|
|
||||||
if (diff_object_keys(result, s, t, current_path, target_values, added))
|
|
||||||
{
|
|
||||||
// fast path: the frame walks source in lockstep with
|
|
||||||
// common_keys, as diff_recursively does, and appends
|
|
||||||
// added_ops once all members are done
|
|
||||||
stack.emplace_back(&s, &t, current_path.size());
|
|
||||||
stack.back().member = s.cbegin();
|
|
||||||
stack.back().target_values = std::move(target_values);
|
|
||||||
stack.back().added = std::move(added);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
case value_t::string:
|
|
||||||
case value_t::boolean:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::discarded:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// both primitive types: replace value
|
|
||||||
diff_replace(result, current_path, t);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user