As discovered by @felipegb94, there are missing overloads to the
`GenericValue::AddMember<T>` template function, taking an explicit
`GenericValue&` as a name and accepting arbitrary primitive values.
This patch adds the missing overloads. The `StringRefType` overload
is needed to disambiguate the addition of a string literal as
value.
Some tests are added to `TEST(Value, Object)` in `valuetest.cpp`.
The GenericValue "copy" constructor (with Allocator) uses a temporary
GenericDocument object to perform the deep copying with the provided
allocator. This leads to the temporary allocation of the `Stack`
memory, even in case of shallow values (numbers, etc.).
This patch improves the performance of this operation by only resorting
the the SAX Handler implementation in case of Array or Object values.
As mentioned in #181, some environments may require adaptations to
the internal calls to the global `new`/`delete` operators, like
adding explicit `NULL` checks to `delete.
This patch adds two new macros
* RAPIDJSON_NEW(x)
* RAPIDJSON_DELETE(x)
to allow user-defined expressions in these cases.
This fixes#181 in an alternative manner.
In the original disambiguation fix for `GenericValue::operator[]` (#170),
the documentation has been missing, which led to quite badly rendered
Doxygen pages.
During a cleanup, I've realized that a much simpler disambiguation is
possible:
````cpp
GenericValue& operator[](SizeType idx); // array
template <typename T>
GenericValue& operator[](T* name); // object
````
This approach works, as non-template functions are preferred over
template functions.
In order to improve the error messages, the pointer type is restricted
to `(const) Ch`.
Update `tutorial.md` to drop the ambiguity warning.
Some compilers do not export the standard C library functions
to the global namespace, in case the C++ header variants are
included (<cstdlib>, <cstring>).
RapidJSON currently uses:
* malloc, realloc, free
* memcpy, memmove, memset, memcpy
Add an explicit namespace qualification to avoid lookup problems.
For more details see: https://github.com/miloyip/rapidjson/issues/132
This commit tries to minimize the required code changes and forwards the `Handler::Key()` calls to `Handler::String()` wherever possible in order to not break existing code; or at least not code deriving from `BaseReaderHandler` when implementing a custom `Handler`.
The `ShortString` can represent zero-terminated strings up to `MaxSize` chars (excluding the terminating zero) and store a value to determine the length of the contained string in the last character `str[LenPos]` by storing `MaxSize - length` there. If the string to store has the maximal length of `MaxSize` (excluding the terminating zero) then `str[LenPos]` will store `0` and therefore act as the string terminator as well. For getting the string length back from that value just use `MaxSize - str[LenPos]`.
This allows to store `11`-chars strings in 32-bit mode and `15`-chars strings in 64-bit mode inline (for `UTF8`-encoded strings).
Since the payload (the `Data` union) of the current implementation of `GenericValue` is `12 bytes` (32 bit) or `16 bytes` (64 bit) it could store `UTF8`-encoded strings up to `10` or `14` chars plus the `terminating zero` character plus the string length:
``` C++
struct ShortString {
enum { MaxSize = sizeof(GenericValue::String) / sizeof(Ch) - sizeof(unsigned char) };
Ch str[MaxSize];
unsigned char length;
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
```
This is achieved by introducing additional `kInlineStrFlag` and `kShortStringFlag` flags. When setting a new string value in `SetStringRaw(s, alloc)` it is first checked if the string is short enough to fit into the `inline string buffer` and if so the given source string will be copied into the new `ShortString` target instead of allocating additional memory for it.
As mentioned by @kosta-github in http://git.io/0gkYSg, the currently
used growth factor of 2 is suboptimal for memory performance. An
extensive discussion can be found at [1].
This patch reduces the array/object capacity growth factor to 1.5, as
many C++ implementations have chosen to use. In order to avoid
floating-point arithmetics for computing the new capacity, I did not
add any customization parameter for the factor and used a shift+add
instead.
[1] https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md
Some 64-bit integers cannot be represented losslessly as a double.
Due to a typo in the operator==, the comparison has been performed
after a double conversion in too many cases.
Added basic detection of `noexcept` support for some compilers, added
corresponding RAPIDJSON_NOEXCEPT annotations to
* non-allocating constructors
* (move) assignment
* Swap
This commit adds an IsGenericValue meta function to match arbitrary
instantiations of the GenericValue template (or derived classes).
This meta function is used in the SFINAE-checks to avoid matching
the generic APIs (operator=,==,!=; AddMember, PushBack) for instances
of the main template. This avoids ambiguities with the GenericValue
overloads.
Several GenericValue functions take a const-reference to another GenericValue
only. These functions can safely accept values with a different allocator
type.
The following functions are therefore extended by a SourceAllocator template
parameter in this commit:
- operator==/!=/[]
- HasMember, FindMember, RemoveMember
- StringEqual
Before applying the simplifications in ed282b814, the SFINAE check for the
GenericValue(bool) constructor has been broken in MSVC 2005. Add a static
assert as a safe-guard against future reappearance of this problem.
As reported in #113, recent versions of Clang complain about
ambiguous overloads for some comparison operator instantiations,
especially if the deduced template type is a GenericValue.
Add an explicit, non-templated version for now (which is a better
match).
This only solves part of the problem, as comparisons between
* GenericValue & GenericDocument
* GenericValue with different SourceAllocator types
will still cause ambiguities.