When RAPIDJSON_USE_MEMBERSMAP is defined, an object Value will store
its members in an (re)allocated array of Members like before, but also
in an std::multimap<GenericValue::Data,SizeType> where the key and value
reference the corresponding Member by its Data and index in the array,
respectively, and in a relocatable manner.
The layout of the members map/array is now:
{multimap*}<>{capacity}<>{Member[capacity]}<>{multimap::iterator[capacity]}
where <> stands for the RAPIDJSON_ALIGN-ment of each part, if needed.
This layout needs to be reallocated when the current capacity is
exhausted, which requires to take care of the multimap and its iterators
explicitely. The multimap is allocated separately and only its pointer is
saved in this layout, so it can easily be restored in its new position.
As for the old/alive iterators, they must move to their new offset according
to the new capacity.
With this in place, it's immediate to get the multimap::iterator from a
MemberIterator and vice versa, thus the same complexity applies for the
operations with MemberIterator or MapIterator.
For FindMember() and RemoveMember(), the complexity drops from O(n) to
the multimap/rbtree's O(log n).
For EraseMember() it drops from O(n-m) to O((log n)-m), m representing
the move/copy of the trailing members.
For AddMember() though, the complexity grows from O(1) to O(log n) due to
the insertion in the multimap too.
Consequently parsing will be slower, up to ~20% measured in perftests on
my laptop (since it's mainly composed of insertions). But later work on
the Document (usually the goal of parsing...) will be much faster; the
new DocumentFind perftest included in this commit is 8 times faster with
RAPIDJSON_USE_MEMBERSMAP (still on my laptop). Overall the tests are 4%
slower (mainly composed of parsing), and notably 15% slower for schemas
parsing/validation (which supposedly comes from the larger JSON files
parsing, still). As a side note, when RAPIDJSON_USE_MEMBERSMAP is not
defined, this commit does nothing (same results for perftest with regard
to previous versions).
Finally, the multimap is allocated and constructed using StdAllocator,
so they will use the same Allocator than for any other Value allocation,
and thus will benefit from the same performance/safety/security/whatever
provided by the user given Allocator.
When rhs is a sub-Value of *this, destroying *this also destroys/frees
rhs, thus the following RawAssign(rhs) crashes.
Address this by saving/moving rhs to a temporary first, which clears rhs
and avoids its destruction with *this.
The crash can be reproduced in test Value.MergeDuplicateKey by using the
CrtAllocator instead of the default Document's MemoryPoolAllocator.
/data/mwrep/res/osp/RapidJson/20-0-0-0/include/rapidjson/document.h:729:58: error: use of overloaded operator '!=' is ambiguous (with operand types 'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::MemberIterator' (aka 'rapidjson::GenericMemberIterator<false, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >') and 'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::MemberIterator')
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
RAPIDJSON_CLZLL is defined as macro of __builtin_clzll when
using gcc to compile. This introduces two issues:
1. in gcc __builtin_clzll returns int, not uint32_t.
2. __builtin_clzll return is undefined when input x is 0
See: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
This patch removes RAPIDJSON_CLZLL, merges __builtin_clzll to
internal clzll with input check and return value explicit cast.
Change-Id: Iac4b355dc5e5b4ed9b3f35a640b6b5537e76f22c
Signed-off-by: Jun He <jun.he@arm.com>
Co-authored-by: Jun He <jun.he@arm.com>
This change comes up with compile time pre-processor directives to
tune the behavior of rapidjson wrt memory consumption. The idea is to
allow each module using this library to choose the right defaults based
on how it consumes memory and what performance it expects.
1. RAPIDJSON_DEFAULT_ALLOCATOR: If defined allows you to choose
CrtAllocator over MemoryPoolAllocator. If it is not defined, chooses MemoryPoolAllocator by default.
2. RAPIDJSON_DEFAULT_STACK_ALLOCATOR: If defined allows you to choose
MemoryPoolAllocator over CrtAllocator. If it is not defined, chooses CrtAllocator by default.
3. RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY and RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY: If defined and set to a
value, uses that value for default number of objects/array elements to be pre-allocated. If not defined,
uses value of 16: the current default.
Verified that all tests pass.