When using operator[] on a GenericValue type clang-tidy complains,
appropriately, about the alignment of the buffer used for placement-new
of the "dummy" GenericValue.
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)
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.
d87b698d0f made all definitions of GenericMemberIterator consistent as
classes (they were structs with RAPIDJSON_NOMEMBERITERATORCLASS
defined), but it didn't keep the member definitions public.
document.h:586:71: error: 'Iterator' is a private member of
'rapidjson::GenericMemberIterator<false, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >'
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for i...
^
document.h:2124:32: note: in instantiation of template class
'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >' requested here
class GenericDocument : public GenericValue<Encoding, Allocator> {
Recent GCC versions warn about using memcpy/memmove to
write to a class pointer (-Wclass-memaccess).
Avoid the warnings by casting to void* first.
Closes#1086.
Closes#1205.
Closes#1246.
Sometimes, particularly when Microsoft's windows.h is included, min/max
are defined as macros, interfering with use of
std::numeric_limits::min() and the like.
To guard against this, the function name is wrapped in an extra set of
parenthesis, which inhibits function-style macro expansion.
* Safely assert upon passing NULL string without length
(requires usage of RAPIDJSON_ASSERT within an expression)
* Allow using a NULL string together with an explicit length 0
(GenericStringRef, GenericValue::SetString, ...), see #817
* Add GenericValue::SetString(StringRefType, Allocator&) overload
* Add tests for the various cases
As reported by @Llerd in #962, the `copyConstStrings` parameter
has not been forwarded recursively to the constructors of
object members and array elements.
Copying the result of an in-situ parsing into another value/document
currently requires that the original buffer - still holding the strings
from the parsing, outlives the destination object as well.
In order to obtain a "full" copy of a GenericValue, this commit adds
an optional flag `copyConstStrings` to `CopyFrom`, which then forces
to take a copy of all embedded strings in the source value.
This solves the problem discussed in #962.