Merge pull request #1485 from ylavic/MemberMap
Object members stored in std::multimap
This commit is contained in:
commit
47b837e14a
49
.travis.yml
49
.travis.yml
@ -28,59 +28,65 @@ env:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# gcc
|
# gcc
|
||||||
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF
|
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF
|
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF
|
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF
|
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
|
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
|
||||||
arch: amd64/
|
|
||||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
|
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF
|
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
- env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: arm64
|
arch: arm64
|
||||||
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF
|
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: arm64
|
arch: arm64
|
||||||
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON
|
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=ON
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: arm64
|
arch: arm64
|
||||||
# clang
|
# clang
|
||||||
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
- env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: arm64
|
arch: arm64
|
||||||
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: arm64
|
arch: arm64
|
||||||
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON CCACHE_CPP2=yes
|
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
|
||||||
compiler: clang
|
compiler: clang
|
||||||
arch: arm64
|
arch: arm64
|
||||||
# coverage report
|
# coverage report
|
||||||
@ -93,7 +99,7 @@ matrix:
|
|||||||
after_success:
|
after_success:
|
||||||
- pip install --user cpp-coveralls
|
- pip install --user cpp-coveralls
|
||||||
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
|
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
|
||||||
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF
|
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF MEMBERSMAP=ON
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
arch: amd64
|
arch: amd64
|
||||||
cache:
|
cache:
|
||||||
@ -146,6 +152,7 @@ script:
|
|||||||
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
|
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
|
||||||
(cd build && cmake
|
(cd build && cmake
|
||||||
-DRAPIDJSON_HAS_STDSTRING=ON
|
-DRAPIDJSON_HAS_STDSTRING=ON
|
||||||
|
-DRAPIDJSON_USE_MEMBERSMAP=$MEMBERSMAP
|
||||||
-DRAPIDJSON_BUILD_CXX11=$CXX11
|
-DRAPIDJSON_BUILD_CXX11=$CXX11
|
||||||
-DRAPIDJSON_BUILD_CXX17=$CXX17
|
-DRAPIDJSON_BUILD_CXX17=$CXX17
|
||||||
-DCMAKE_VERBOSE_MAKEFILE=ON
|
-DCMAKE_VERBOSE_MAKEFILE=ON
|
||||||
|
@ -52,6 +52,11 @@ if(RAPIDJSON_HAS_STDSTRING)
|
|||||||
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
|
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(RAPIDJSON_USE_MEMBERSMAP "" OFF)
|
||||||
|
if(RAPIDJSON_USE_MEMBERSMAP)
|
||||||
|
add_definitions(-DRAPIDJSON_USE_MEMBERSMAP=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
find_program(CCACHE_FOUND ccache)
|
||||||
if(CCACHE_FOUND)
|
if(CCACHE_FOUND)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||||
|
15
appveyor.yml
15
appveyor.yml
@ -15,70 +15,83 @@ environment:
|
|||||||
VS_PLATFORM: win32
|
VS_PLATFORM: win32
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
VS_VERSION: 10 2010
|
VS_VERSION: 10 2010
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: ON
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
VS_VERSION: 11 2012
|
VS_VERSION: 11 2012
|
||||||
VS_PLATFORM: win32
|
VS_PLATFORM: win32
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: ON
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
VS_VERSION: 11 2012
|
VS_VERSION: 11 2012
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
VS_VERSION: 12 2013
|
VS_VERSION: 12 2013
|
||||||
VS_PLATFORM: win32
|
VS_PLATFORM: win32
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||||
VS_VERSION: 12 2013
|
VS_VERSION: 12 2013
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: ON
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
VS_VERSION: 14 2015
|
VS_VERSION: 14 2015
|
||||||
VS_PLATFORM: win32
|
VS_PLATFORM: win32
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: ON
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
VS_VERSION: 14 2015
|
VS_VERSION: 14 2015
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
VS_VERSION: 15 2017
|
VS_VERSION: 15 2017
|
||||||
VS_PLATFORM: win32
|
VS_PLATFORM: win32
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
VS_VERSION: 15 2017
|
VS_VERSION: 15 2017
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: ON
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
VS_VERSION: 15 2017
|
VS_VERSION: 15 2017
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: ON
|
CXX11: ON
|
||||||
CXX17: OFF
|
CXX17: OFF
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
VS_VERSION: 15 2017
|
VS_VERSION: 15 2017
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: ON
|
CXX17: ON
|
||||||
|
MEMBERSMAP: OFF
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
VS_VERSION: 16 2019
|
VS_VERSION: 16 2019
|
||||||
VS_PLATFORM: x64
|
VS_PLATFORM: x64
|
||||||
CXX11: OFF
|
CXX11: OFF
|
||||||
CXX17: ON
|
CXX17: ON
|
||||||
|
MEMBERSMAP: ON
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -Wno-dev
|
- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -DRAPIDJSON_USE_MEMBERSMAP=%MEMBERSMAP% -Wno-dev
|
||||||
|
|
||||||
build:
|
build:
|
||||||
project: Build\VS\RapidJSON.sln
|
project: Build\VS\RapidJSON.sln
|
||||||
|
BIN
bin/types/alotofkeys.json
Normal file
BIN
bin/types/alotofkeys.json
Normal file
Binary file not shown.
@ -16,6 +16,7 @@
|
|||||||
#define RAPIDJSON_ALLOCATORS_H_
|
#define RAPIDJSON_ALLOCATORS_H_
|
||||||
|
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
|
#include "internal/meta.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -158,6 +159,7 @@ class MemoryPoolAllocator {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
|
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
|
||||||
|
static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
|
||||||
|
|
||||||
//! Constructor with chunkSize.
|
//! Constructor with chunkSize.
|
||||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||||
@ -417,6 +419,16 @@ private:
|
|||||||
SharedData *shared_; //!< The shared data of the allocator
|
SharedData *shared_; //!< The shared data of the allocator
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template<typename, typename = void>
|
||||||
|
struct IsRefCounted :
|
||||||
|
public FalseType
|
||||||
|
{ };
|
||||||
|
template<typename T>
|
||||||
|
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
|
||||||
|
public TrueType
|
||||||
|
{ };
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename A>
|
template<typename T, typename A>
|
||||||
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
|
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
|
||||||
@ -437,7 +449,6 @@ inline void Free(A& a, T *p, size_t n = 1)
|
|||||||
static_cast<void>(Realloc<T, A>(a, p, n, 0));
|
static_cast<void>(Realloc<T, A>(a, p, n, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
|
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
|
||||||
@ -601,6 +612,7 @@ public:
|
|||||||
|
|
||||||
//! rapidjson Allocator concept
|
//! rapidjson Allocator concept
|
||||||
static const bool kNeedFree = BaseAllocator::kNeedFree;
|
static const bool kNeedFree = BaseAllocator::kNeedFree;
|
||||||
|
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
|
||||||
void* Malloc(size_t size)
|
void* Malloc(size_t size)
|
||||||
{
|
{
|
||||||
return baseAllocator_.Malloc(size);
|
return baseAllocator_.Malloc(size);
|
||||||
|
@ -46,8 +46,8 @@ RAPIDJSON_DIAG_OFF(effc++)
|
|||||||
#include <iterator> // std::random_access_iterator_tag
|
#include <iterator> // std::random_access_iterator_tag
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
#include <utility> // std::move
|
#include <map> // std::multimap
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -732,18 +732,8 @@ public:
|
|||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
|
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
|
||||||
switch (rhs.GetType()) {
|
switch (rhs.GetType()) {
|
||||||
case kObjectType: {
|
case kObjectType:
|
||||||
SizeType count = rhs.data_.o.size;
|
DoCopyMembers(rhs, allocator, copyConstStrings);
|
||||||
Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
|
||||||
const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
|
|
||||||
for (SizeType i = 0; i < count; i++) {
|
|
||||||
new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
|
|
||||||
new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
|
|
||||||
}
|
|
||||||
data_.f.flags = kObjectFlag;
|
|
||||||
data_.o.size = data_.o.capacity = count;
|
|
||||||
SetMembersPointer(lm);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case kArrayType: {
|
case kArrayType: {
|
||||||
SizeType count = rhs.data_.a.size;
|
SizeType count = rhs.data_.a.size;
|
||||||
@ -879,25 +869,30 @@ public:
|
|||||||
/*! Need to destruct elements of array, members of object, or copy-string.
|
/*! Need to destruct elements of array, members of object, or copy-string.
|
||||||
*/
|
*/
|
||||||
~GenericValue() {
|
~GenericValue() {
|
||||||
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
|
// With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release
|
||||||
|
// their Allocator if it's refcounted (e.g. MemoryPoolAllocator).
|
||||||
|
if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 &&
|
||||||
|
internal::IsRefCounted<Allocator>::Value)) {
|
||||||
switch(data_.f.flags) {
|
switch(data_.f.flags) {
|
||||||
case kArrayFlag:
|
case kArrayFlag:
|
||||||
{
|
{
|
||||||
GenericValue* e = GetElementsPointer();
|
GenericValue* e = GetElementsPointer();
|
||||||
for (GenericValue* v = e; v != e + data_.a.size; ++v)
|
for (GenericValue* v = e; v != e + data_.a.size; ++v)
|
||||||
v->~GenericValue();
|
v->~GenericValue();
|
||||||
Allocator::Free(e);
|
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
|
||||||
|
Allocator::Free(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kObjectFlag:
|
case kObjectFlag:
|
||||||
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
|
DoFreeMembers();
|
||||||
m->~Member();
|
|
||||||
Allocator::Free(GetMembersPointer());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kCopyStringFlag:
|
case kCopyStringFlag:
|
||||||
Allocator::Free(const_cast<Ch*>(GetStringPointer()));
|
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
|
||||||
|
Allocator::Free(const_cast<Ch*>(GetStringPointer()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1265,10 +1260,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
|
GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
|
||||||
RAPIDJSON_ASSERT(IsObject());
|
RAPIDJSON_ASSERT(IsObject());
|
||||||
if (newCapacity > data_.o.capacity) {
|
DoReserveMembers(newCapacity, allocator);
|
||||||
SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member))));
|
|
||||||
data_.o.capacity = newCapacity;
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,11 +1334,7 @@ public:
|
|||||||
MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
RAPIDJSON_ASSERT(IsObject());
|
RAPIDJSON_ASSERT(IsObject());
|
||||||
RAPIDJSON_ASSERT(name.IsString());
|
RAPIDJSON_ASSERT(name.IsString());
|
||||||
MemberIterator member = MemberBegin();
|
return DoFindMember(name);
|
||||||
for ( ; member != MemberEnd(); ++member)
|
|
||||||
if (name.StringEqual(member->name))
|
|
||||||
break;
|
|
||||||
return member;
|
|
||||||
}
|
}
|
||||||
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
||||||
|
|
||||||
@ -1375,14 +1363,7 @@ public:
|
|||||||
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
|
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
|
||||||
RAPIDJSON_ASSERT(IsObject());
|
RAPIDJSON_ASSERT(IsObject());
|
||||||
RAPIDJSON_ASSERT(name.IsString());
|
RAPIDJSON_ASSERT(name.IsString());
|
||||||
|
DoAddMember(name, value, allocator);
|
||||||
ObjectData& o = data_.o;
|
|
||||||
if (o.size >= o.capacity)
|
|
||||||
MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator);
|
|
||||||
Member* members = GetMembersPointer();
|
|
||||||
members[o.size].name.RawAssign(name);
|
|
||||||
members[o.size].value.RawAssign(value);
|
|
||||||
o.size++;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1516,9 +1497,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void RemoveAllMembers() {
|
void RemoveAllMembers() {
|
||||||
RAPIDJSON_ASSERT(IsObject());
|
RAPIDJSON_ASSERT(IsObject());
|
||||||
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
|
DoClearMembers();
|
||||||
m->~Member();
|
|
||||||
data_.o.size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Remove a member in object by its name.
|
//! Remove a member in object by its name.
|
||||||
@ -1562,14 +1541,7 @@ public:
|
|||||||
RAPIDJSON_ASSERT(data_.o.size > 0);
|
RAPIDJSON_ASSERT(data_.o.size > 0);
|
||||||
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
|
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
|
||||||
RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
|
RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
|
||||||
|
return DoRemoveMember(m);
|
||||||
MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
|
|
||||||
if (data_.o.size > 1 && m != last)
|
|
||||||
*m = *last; // Move the last one to this place
|
|
||||||
else
|
|
||||||
m->~Member(); // Only one left, just destroy
|
|
||||||
--data_.o.size;
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Remove a member from an object by iterator.
|
//! Remove a member from an object by iterator.
|
||||||
@ -1601,13 +1573,7 @@ public:
|
|||||||
RAPIDJSON_ASSERT(first >= MemberBegin());
|
RAPIDJSON_ASSERT(first >= MemberBegin());
|
||||||
RAPIDJSON_ASSERT(first <= last);
|
RAPIDJSON_ASSERT(first <= last);
|
||||||
RAPIDJSON_ASSERT(last <= MemberEnd());
|
RAPIDJSON_ASSERT(last <= MemberEnd());
|
||||||
|
return DoEraseMembers(first, last);
|
||||||
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
|
||||||
for (MemberIterator itr = pos; itr != last; ++itr)
|
|
||||||
itr->~Member();
|
|
||||||
std::memmove(static_cast<void*>(&*pos), &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
|
||||||
data_.o.size -= static_cast<SizeType>(last - first);
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Erase a member in object by its name.
|
//! Erase a member in object by its name.
|
||||||
@ -1858,12 +1824,12 @@ public:
|
|||||||
//!@name String
|
//!@name String
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
|
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
|
||||||
|
|
||||||
//! Get the length of string.
|
//! Get the length of string.
|
||||||
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
|
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
|
||||||
*/
|
*/
|
||||||
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
|
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
|
||||||
|
|
||||||
//! Set this value as a string without copying source string.
|
//! Set this value as a string without copying source string.
|
||||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||||
@ -2112,6 +2078,13 @@ private:
|
|||||||
Flag f;
|
Flag f;
|
||||||
}; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
}; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) {
|
||||||
|
return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str);
|
||||||
|
}
|
||||||
|
static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) {
|
||||||
|
return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length;
|
||||||
|
}
|
||||||
|
|
||||||
RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
|
RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
|
||||||
RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
|
RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
|
||||||
RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
|
RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
|
||||||
@ -2119,6 +2092,286 @@ private:
|
|||||||
RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
|
RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
|
||||||
RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
|
RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
|
||||||
|
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
|
||||||
|
struct MapTraits {
|
||||||
|
struct Less {
|
||||||
|
bool operator()(const Data& s1, const Data& s2) const {
|
||||||
|
SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2);
|
||||||
|
int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2));
|
||||||
|
return cmp < 0 || (cmp == 0 && n1 < n2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef std::pair<const Data, SizeType> Pair;
|
||||||
|
typedef std::multimap<Data, SizeType, Less, StdAllocator<Pair, Allocator> > Map;
|
||||||
|
typedef typename Map::iterator Iterator;
|
||||||
|
};
|
||||||
|
typedef typename MapTraits::Map Map;
|
||||||
|
typedef typename MapTraits::Less MapLess;
|
||||||
|
typedef typename MapTraits::Pair MapPair;
|
||||||
|
typedef typename MapTraits::Iterator MapIterator;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Layout of the members' map/array, re(al)located according to the needed capacity:
|
||||||
|
//
|
||||||
|
// {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]}
|
||||||
|
//
|
||||||
|
// (where <> stands for the RAPIDJSON_ALIGN-ment, if needed)
|
||||||
|
//
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) {
|
||||||
|
return RAPIDJSON_ALIGN(sizeof(Map*)) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(SizeType)) +
|
||||||
|
RAPIDJSON_ALIGN(capacity * sizeof(Member)) +
|
||||||
|
capacity * sizeof(MapIterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) {
|
||||||
|
return *reinterpret_cast<SizeType*>(reinterpret_cast<uintptr_t>(&map) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(Map*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) {
|
||||||
|
return reinterpret_cast<Member*>(reinterpret_cast<uintptr_t>(&map) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(Map*)) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(SizeType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) {
|
||||||
|
return reinterpret_cast<MapIterator*>(reinterpret_cast<uintptr_t>(&map) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(Map*)) +
|
||||||
|
RAPIDJSON_ALIGN(sizeof(SizeType)) +
|
||||||
|
RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) {
|
||||||
|
RAPIDJSON_ASSERT(members != 0);
|
||||||
|
return *reinterpret_cast<Map**>(reinterpret_cast<uintptr_t>(members) -
|
||||||
|
RAPIDJSON_ALIGN(sizeof(SizeType)) -
|
||||||
|
RAPIDJSON_ALIGN(sizeof(Map*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting..
|
||||||
|
RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) {
|
||||||
|
#if RAPIDJSON_HAS_CXX11
|
||||||
|
MapIterator ret = std::move(rhs);
|
||||||
|
#else
|
||||||
|
MapIterator ret = rhs;
|
||||||
|
#endif
|
||||||
|
rhs.~MapIterator();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) {
|
||||||
|
Map **newMap = static_cast<Map**>(allocator.Malloc(GetMapLayoutSize(newCapacity)));
|
||||||
|
GetMapCapacity(*newMap) = newCapacity;
|
||||||
|
if (!oldMap) {
|
||||||
|
*newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*newMap = *oldMap;
|
||||||
|
size_t count = (*oldMap)->size();
|
||||||
|
std::memcpy(static_cast<void*>(GetMapMembers(*newMap)),
|
||||||
|
static_cast<void*>(GetMapMembers(*oldMap)),
|
||||||
|
count * sizeof(Member));
|
||||||
|
MapIterator *oldIt = GetMapIterators(*oldMap),
|
||||||
|
*newIt = GetMapIterators(*newMap);
|
||||||
|
while (count--) {
|
||||||
|
new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count]));
|
||||||
|
}
|
||||||
|
Allocator::Free(oldMap);
|
||||||
|
}
|
||||||
|
return *newMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
|
||||||
|
return GetMapMembers(DoReallocMap(0, capacity, allocator));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
|
||||||
|
ObjectData& o = data_.o;
|
||||||
|
if (newCapacity > o.capacity) {
|
||||||
|
Member* oldMembers = GetMembersPointer();
|
||||||
|
Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0,
|
||||||
|
*&newMap = DoReallocMap(oldMap, newCapacity, allocator);
|
||||||
|
RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap));
|
||||||
|
o.capacity = newCapacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SourceAllocator>
|
||||||
|
MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
|
if (Member* members = GetMembersPointer()) {
|
||||||
|
Map* &map = GetMap(members);
|
||||||
|
MapIterator mit = map->find(reinterpret_cast<const Data&>(name.data_));
|
||||||
|
if (mit != map->end()) {
|
||||||
|
return MemberIterator(&members[mit->second]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MemberEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoClearMembers() {
|
||||||
|
if (Member* members = GetMembersPointer()) {
|
||||||
|
Map* &map = GetMap(members);
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
for (SizeType i = 0; i < data_.o.size; i++) {
|
||||||
|
map->erase(DropMapIterator(mit[i]));
|
||||||
|
members[i].~Member();
|
||||||
|
}
|
||||||
|
data_.o.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoFreeMembers() {
|
||||||
|
if (Member* members = GetMembersPointer()) {
|
||||||
|
GetMap(members)->~Map();
|
||||||
|
for (SizeType i = 0; i < data_.o.size; i++) {
|
||||||
|
members[i].~Member();
|
||||||
|
}
|
||||||
|
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
|
||||||
|
Map** map = &GetMap(members);
|
||||||
|
Allocator::Free(*map);
|
||||||
|
Allocator::Free(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
|
||||||
|
RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
|
||||||
|
return Malloc<Member>(allocator, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
|
||||||
|
ObjectData& o = data_.o;
|
||||||
|
if (newCapacity > o.capacity) {
|
||||||
|
Member* newMembers = Realloc<Member>(allocator, GetMembersPointer(), o.capacity, newCapacity);
|
||||||
|
RAPIDJSON_SETPOINTER(Member, o.members, newMembers);
|
||||||
|
o.capacity = newCapacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SourceAllocator>
|
||||||
|
MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
|
MemberIterator member = MemberBegin();
|
||||||
|
for ( ; member != MemberEnd(); ++member)
|
||||||
|
if (name.StringEqual(member->name))
|
||||||
|
break;
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoClearMembers() {
|
||||||
|
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
|
||||||
|
m->~Member();
|
||||||
|
data_.o.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoFreeMembers() {
|
||||||
|
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
|
||||||
|
m->~Member();
|
||||||
|
Allocator::Free(GetMembersPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
|
||||||
|
void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
|
||||||
|
ObjectData& o = data_.o;
|
||||||
|
if (o.size >= o.capacity)
|
||||||
|
DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator);
|
||||||
|
Member* members = GetMembersPointer();
|
||||||
|
Member* m = members + o.size;
|
||||||
|
m->name.RawAssign(name);
|
||||||
|
m->value.RawAssign(value);
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
Map* &map = GetMap(members);
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size)));
|
||||||
|
#endif
|
||||||
|
++o.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberIterator DoRemoveMember(MemberIterator m) {
|
||||||
|
ObjectData& o = data_.o;
|
||||||
|
Member* members = GetMembersPointer();
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
Map* &map = GetMap(members);
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
SizeType mpos = static_cast<SizeType>(&*m - members);
|
||||||
|
map->erase(DropMapIterator(mit[mpos]));
|
||||||
|
#endif
|
||||||
|
MemberIterator last(members + (o.size - 1));
|
||||||
|
if (o.size > 1 && m != last) {
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members]));
|
||||||
|
mit[mpos]->second = mpos;
|
||||||
|
#endif
|
||||||
|
*m = *last; // Move the last one to this place
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m->~Member(); // Only one left, just destroy
|
||||||
|
}
|
||||||
|
--o.size;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) {
|
||||||
|
ObjectData& o = data_.o;
|
||||||
|
MemberIterator beg = MemberBegin(),
|
||||||
|
pos = beg + (first - beg),
|
||||||
|
end = MemberEnd();
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
Map* &map = GetMap(GetMembersPointer());
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
#endif
|
||||||
|
for (MemberIterator itr = pos; itr != last; ++itr) {
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
map->erase(DropMapIterator(mit[itr - beg]));
|
||||||
|
#endif
|
||||||
|
itr->~Member();
|
||||||
|
}
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
if (first != last) {
|
||||||
|
// Move remaining members/iterators
|
||||||
|
MemberIterator next = pos + (last - first);
|
||||||
|
for (MemberIterator itr = pos; next != end; ++itr, ++next) {
|
||||||
|
std::memcpy(static_cast<void*>(&*itr), &*next, sizeof(Member));
|
||||||
|
SizeType mpos = static_cast<SizeType>(itr - beg);
|
||||||
|
new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg]));
|
||||||
|
mit[mpos]->second = mpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::memmove(static_cast<void*>(&*pos), &*last,
|
||||||
|
static_cast<size_t>(end - last) * sizeof(Member));
|
||||||
|
#endif
|
||||||
|
o.size -= static_cast<SizeType>(last - first);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SourceAllocator>
|
||||||
|
void DoCopyMembers(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings) {
|
||||||
|
RAPIDJSON_ASSERT(rhs.GetType() == kObjectType);
|
||||||
|
|
||||||
|
data_.f.flags = kObjectFlag;
|
||||||
|
SizeType count = rhs.data_.o.size;
|
||||||
|
Member* lm = DoAllocMembers(count, allocator);
|
||||||
|
const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
Map* &map = GetMap(lm);
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
#endif
|
||||||
|
for (SizeType i = 0; i < count; i++) {
|
||||||
|
new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
|
||||||
|
new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
data_.o.size = data_.o.capacity = count;
|
||||||
|
SetMembersPointer(lm);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize this value as array with initial data, without calling destructor.
|
// Initialize this value as array with initial data, without calling destructor.
|
||||||
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
||||||
data_.f.flags = kArrayFlag;
|
data_.f.flags = kArrayFlag;
|
||||||
@ -2136,9 +2389,16 @@ private:
|
|||||||
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
||||||
data_.f.flags = kObjectFlag;
|
data_.f.flags = kObjectFlag;
|
||||||
if (count) {
|
if (count) {
|
||||||
Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
Member* m = DoAllocMembers(count, allocator);
|
||||||
SetMembersPointer(m);
|
SetMembersPointer(m);
|
||||||
std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
|
std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
|
||||||
|
#if RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
Map* &map = GetMap(m);
|
||||||
|
MapIterator* mit = GetMapIterators(map);
|
||||||
|
for (SizeType i = 0; i < count; i++) {
|
||||||
|
new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetMembersPointer(0);
|
SetMembersPointer(0);
|
||||||
@ -2259,6 +2519,13 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
~GenericDocument() {
|
~GenericDocument() {
|
||||||
|
// Clear the ::ValueType before ownAllocator is destroyed, ~ValueType()
|
||||||
|
// runs last and may access its elements or members which would be freed
|
||||||
|
// with an allocator like MemoryPoolAllocator (CrtAllocator does not
|
||||||
|
// free its data when destroyed, but MemoryPoolAllocator does).
|
||||||
|
if (ownAllocator_) {
|
||||||
|
ValueType::SetNull();
|
||||||
|
}
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +162,24 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#endif // RAPIDJSON_HAS_STDSTRING
|
#endif // RAPIDJSON_HAS_STDSTRING
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
|
||||||
|
/*! \def RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Enable RapidJSON support for object members handling in a \c std::multimap
|
||||||
|
|
||||||
|
By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
|
||||||
|
members are stored in a \c std::multimap for faster lookup and deletion times, a
|
||||||
|
trade off with a slightly slower insertion time and a small object allocat(or)ed
|
||||||
|
memory overhead.
|
||||||
|
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_USE_MEMBERSMAP
|
||||||
|
#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
|
||||||
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_NO_INT64DEFINE
|
// RAPIDJSON_NO_INT64DEFINE
|
||||||
|
|
||||||
@ -578,6 +596,10 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#endif
|
#endif
|
||||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
#include <utility> // std::move
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
|
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||||
#if RAPIDJSON_HAS_CXX11
|
#if RAPIDJSON_HAS_CXX11
|
||||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||||
|
@ -130,7 +130,8 @@ public:
|
|||||||
"integers.json",
|
"integers.json",
|
||||||
"mixed.json",
|
"mixed.json",
|
||||||
"nulls.json",
|
"nulls.json",
|
||||||
"paragraphs.json"
|
"paragraphs.json",
|
||||||
|
"alotofkeys.json"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
|
for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
|
||||||
@ -158,7 +159,7 @@ public:
|
|||||||
free(whitespace_);
|
free(whitespace_);
|
||||||
json_ = 0;
|
json_ = 0;
|
||||||
whitespace_ = 0;
|
whitespace_ = 0;
|
||||||
for (size_t i = 0; i < 7; i++) {
|
for (size_t i = 0; i < 8; i++) {
|
||||||
free(types_[i]);
|
free(types_[i]);
|
||||||
types_[i] = 0;
|
types_[i] = 0;
|
||||||
}
|
}
|
||||||
@ -174,8 +175,8 @@ protected:
|
|||||||
size_t length_;
|
size_t length_;
|
||||||
char *whitespace_;
|
char *whitespace_;
|
||||||
size_t whitespace_length_;
|
size_t whitespace_length_;
|
||||||
char *types_[7];
|
char *types_[8];
|
||||||
size_t typesLength_[7];
|
size_t typesLength_[8];
|
||||||
|
|
||||||
static const size_t kTrialCount = 1000;
|
static const size_t kTrialCount = 1000;
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "rapidjson/memorystream.h"
|
#include "rapidjson/memorystream.h"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef RAPIDJSON_SSE2
|
#ifdef RAPIDJSON_SSE2
|
||||||
#define SIMD_SUFFIX(name) name##_SSE2
|
#define SIMD_SUFFIX(name) name##_SSE2
|
||||||
@ -52,7 +53,7 @@ public:
|
|||||||
// Parse as a document
|
// Parse as a document
|
||||||
EXPECT_FALSE(doc_.Parse(json_).HasParseError());
|
EXPECT_FALSE(doc_.Parse(json_).HasParseError());
|
||||||
|
|
||||||
for (size_t i = 0; i < 7; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
|
EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
char *temp_;
|
char *temp_;
|
||||||
Document doc_;
|
Document doc_;
|
||||||
Document typesDoc_[7];
|
Document typesDoc_[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
|
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
|
||||||
@ -335,6 +336,23 @@ TEST_F(RapidJson, DocumentAccept) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RapidJson, DocumentFind) {
|
||||||
|
typedef Document::ValueType ValueType;
|
||||||
|
typedef ValueType::ConstMemberIterator ConstMemberIterator;
|
||||||
|
const Document &doc = typesDoc_[7]; // alotofkeys.json
|
||||||
|
if (doc.IsObject()) {
|
||||||
|
std::vector<const ValueType*> keys;
|
||||||
|
for (ConstMemberIterator it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) {
|
||||||
|
keys.push_back(&it->name);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < kTrialCount; i++) {
|
||||||
|
for (size_t j = 0; j < keys.size(); j++) {
|
||||||
|
EXPECT_TRUE(doc.FindMember(*keys[j]) != doc.MemberEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct NullStream {
|
struct NullStream {
|
||||||
typedef char Ch;
|
typedef char Ch;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user