mirror of
https://github.com/nlohmann/json.git
synced 2026-10-10 16:37:14 +00:00
Merge branch 'json-view/21-images' into json-view/22-view-dump-fast
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
25 files changed
+378
-285
No files matched your search
@@ -2939,8 +2939,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
// large objects). An object with document_data::index_min_members members or
|
||||
// more gets an open-addressing table after parsing; its node stores the
|
||||
// number of the table (1-based) in `extra`. A slot holds the offset of a key
|
||||
// node from its object node (0: empty). Of duplicate keys, the last is kept,
|
||||
// as for the linear search, and as basic_json::parse() does.
|
||||
// node from its object node (0: empty). Of duplicate keys, the first is kept,
|
||||
// as for the linear search.
|
||||
//
|
||||
// The hash is not seeded, so keys chosen to collide could make the build
|
||||
// quadratic. A key therefore sits at most index_max_displacement slots away
|
||||
@@ -3009,8 +3009,7 @@ inline void build_object_index(document_data& d, node* obj)
|
||||
const node* const other = obj + slots[i];
|
||||
if (other->len == k->len && (k->len == 0 || std::memcmp(d.str(*other), key, k->len) == 0))
|
||||
{
|
||||
duplicate = true; // keep the last: the key's slot now leads to this member
|
||||
slots[i] = static_cast<std::uint32_t>(k - obj);
|
||||
duplicate = true; // keep the first
|
||||
break;
|
||||
}
|
||||
if (++distance > index_max_displacement)
|
||||
@@ -3047,7 +3046,7 @@ inline void build_object_indexes(document_data& d)
|
||||
}
|
||||
}
|
||||
|
||||
/// the key node of the last member with this key of an indexed object, or
|
||||
/// the key node of the first member with this key of an indexed object, or
|
||||
/// nullptr
|
||||
inline const node* find_indexed(const document_data& d, const node* obj, const char* key, std::size_t n) noexcept
|
||||
{
|
||||
@@ -3141,9 +3140,10 @@ class short_key
|
||||
std::uint64_t m_b = 0;
|
||||
};
|
||||
|
||||
/// the key node of the last member of an object with the given key, or
|
||||
/// nullptr (the last one, as materialize() and parse() keep it); most keys are
|
||||
/// rejected by their length, from the index alone
|
||||
/// the key node of the first member of an object with the given key, or
|
||||
/// nullptr (the search stops at the first match; materialize() and parse()
|
||||
/// keep the last value of a duplicate key instead); most keys are rejected by
|
||||
/// their length, from the index alone
|
||||
template<bool Editable>
|
||||
const node* find_member(const document_data& d, const node* object, const char* key, std::size_t n) noexcept
|
||||
{
|
||||
@@ -3154,7 +3154,6 @@ const node* find_member(const document_data& d, const node* object, const char*
|
||||
}
|
||||
const node* const end = nav::end(d, object);
|
||||
const auto* const k = reinterpret_cast<const unsigned char*>(key); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
const node* last = nullptr;
|
||||
if (NLOHMANN_VIEW_LIKELY(n <= 16))
|
||||
{
|
||||
const short_key probe(k, n);
|
||||
@@ -3162,19 +3161,19 @@ const node* find_member(const document_data& d, const node* object, const char*
|
||||
{
|
||||
if (m->len == n && probe.matches(reinterpret_cast<const unsigned char*>(d.str(*m)))) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
{
|
||||
last = m;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
return nullptr;
|
||||
}
|
||||
for (const node* m = nav::first(d, object); m != end; m = document_data::after(m + 1))
|
||||
{
|
||||
if (m->len == n && std::memcmp(d.str(*m), key, n) == 0)
|
||||
{
|
||||
last = m;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// whether an integer type is accepted as an array index by the view's
|
||||
@@ -3361,23 +3360,25 @@ class editor
|
||||
{
|
||||
become_empty(o, value_t::object);
|
||||
}
|
||||
// an existing member: assign the one that lookups find (the last
|
||||
// one, should the key occur more than once), and drop the others, so
|
||||
// that lookups, iteration, and materialize() agree. The key stays at
|
||||
// the position of its first occurrence, as materialize() puts it.
|
||||
// an existing member: assign it (and drop later duplicates, so that
|
||||
// lookups, iteration, and materialize() agree)
|
||||
node* slot = nullptr;
|
||||
std::size_t matches = 0;
|
||||
bool duplicates = false;
|
||||
for (const node* k = nav::first(m_doc, o), *end = nav::end(m_doc, o); k != end; k = document_data::after(k + 1))
|
||||
{
|
||||
if (key_equals(*k, key))
|
||||
{
|
||||
if (slot != nullptr)
|
||||
{
|
||||
duplicates = true;
|
||||
break;
|
||||
}
|
||||
slot = const_cast<node*>(nav::value(k + 1)); // NOLINT(cppcoreguidelines-pro-type-const-cast): the nodes belong to this document
|
||||
++matches;
|
||||
}
|
||||
}
|
||||
if (slot != nullptr)
|
||||
{
|
||||
if (matches > 1)
|
||||
if (duplicates)
|
||||
{
|
||||
erase_members(o, key, true);
|
||||
}
|
||||
@@ -3523,38 +3524,27 @@ class editor
|
||||
return k.len == key.size() && (key.size() == 0 || std::memcmp(m_doc.str(k), key.data(), key.size()) == 0);
|
||||
}
|
||||
|
||||
/// Remove the members with this key from an object: all of them, or all
|
||||
/// but one. That one stays where the first occurrence is, but holds the
|
||||
/// value of the last (the one that lookups find, which views may refer to).
|
||||
std::size_t erase_members(node* o, string_view_t key, bool keep_one)
|
||||
/// remove the members with this key (all, or all but the first) from an object
|
||||
std::size_t erase_members(node* o, string_view_t key, bool keep_first)
|
||||
{
|
||||
node* const h = block_of(m_doc, o, 0);
|
||||
node last_value{}; // the entry of the value of the last member
|
||||
node* const end = h + h->next;
|
||||
if (keep_one)
|
||||
{
|
||||
for (node* r = h + 1; r != end; r += 2)
|
||||
{
|
||||
if (key_equals(*r, key))
|
||||
{
|
||||
last_value = r[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
node* w = h + 1;
|
||||
std::size_t erased = 0;
|
||||
bool kept = false;
|
||||
for (node* r = h + 1; r != end; r += 2)
|
||||
for (node* r = h + 1, *end = h + h->next; r != end; r += 2)
|
||||
{
|
||||
const bool match = key_equals(*r, key);
|
||||
if (match && (kept || !keep_one))
|
||||
if (match && (kept || !keep_first))
|
||||
{
|
||||
++erased;
|
||||
continue;
|
||||
}
|
||||
w[0] = r[0];
|
||||
w[1] = match ? last_value : r[1];
|
||||
kept = kept || match;
|
||||
if (w != r)
|
||||
{
|
||||
w[0] = r[0];
|
||||
w[1] = r[1];
|
||||
}
|
||||
w += 2;
|
||||
}
|
||||
h->next = static_cast<std::uint32_t>(w - h);
|
||||
@@ -5835,11 +5825,6 @@ class output_buffer
|
||||
{
|
||||
const auto size = static_cast<std::size_t>(m_pos - m_out.data());
|
||||
m_out.resize(size);
|
||||
// do not keep a buffer that was sized for a much larger output
|
||||
if (m_out.capacity() > 1024 && m_out.capacity() / 2 > size)
|
||||
{
|
||||
m_out.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE void reserve(std::size_t n)
|
||||
@@ -7151,7 +7136,7 @@ class basic_json_view
|
||||
// element access //
|
||||
////////////////////
|
||||
|
||||
/// the value of the member with this key (the last one, should the key
|
||||
/// the value of the member with this key (the first one, should the key
|
||||
/// occur more than once); a discarded view if there is none, or if this
|
||||
/// is a discarded view (so that v["a"]["b"] is safe). Throws type_error.305
|
||||
/// if this is any other value but an object.
|
||||
@@ -7215,7 +7200,7 @@ class basic_json_view
|
||||
return detail::view::resolve_pointer(*this, detail::json_pointer_access::reference_tokens(ptr), detail::view::pointer_mode::unchecked);
|
||||
}
|
||||
|
||||
/// the value of the member with this key (the last one, should the key
|
||||
/// the value of the member with this key (the first one, should the key
|
||||
/// occur more than once). Throws type_error.304 if this is not an object,
|
||||
/// and out_of_range.403 if there is no such member.
|
||||
basic_json_view at(string_view_t key) const
|
||||
@@ -7273,7 +7258,7 @@ class basic_json_view
|
||||
}
|
||||
|
||||
/// the member with this key converted to T, or the default value if there
|
||||
/// is no such member (the last one, should the key occur more than
|
||||
/// is no such member (the first one, should the key occur more than
|
||||
/// once). Throws type_error.306 if this is not an object.
|
||||
template < typename T, typename std::enable_if < !std::is_same<typename std::decay<T>::type, const char*>::value, int >::type = 0 >
|
||||
T value(string_view_t key, const T& default_value) const
|
||||
@@ -7338,7 +7323,7 @@ class basic_json_view
|
||||
// lookup //
|
||||
////////////
|
||||
|
||||
/// an iterator to the member with this key (the last one, should the
|
||||
/// an iterator to the member with this key (the first one, should the
|
||||
/// key occur more than once), or end(); end() also for non-objects
|
||||
iterator find(string_view_t key) const
|
||||
{
|
||||
@@ -7673,7 +7658,7 @@ class basic_json_view
|
||||
return (std::min)(m_doc->size - m_node->off, static_cast<std::size_t>(1024) + nodes * 16);
|
||||
}
|
||||
|
||||
/// the value of the last member with this key, or a discarded view
|
||||
/// the value of the first member with this key, or a discarded view
|
||||
/// (object required)
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE basic_json_view lookup(string_view_t key) const noexcept
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user