diff --git a/.gitignore b/.gitignore
index 1d3073f7e..5932e82c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
!/bin/encodings
!/bin/jsonchecker
!/bin/types
+!/bin/unittestschema
/build
/doc/html
/doc/doxygen_*.db
diff --git a/.travis.yml b/.travis.yml
index 783c0525a..17d8f03d6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,18 @@
sudo: required
-dist: trusty
-group: edge
+dist: xenial
language: cpp
cache:
- ccache
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - cmake
+ - valgrind
+ - clang-8
env:
global:
- USE_CCACHE=1
@@ -14,49 +21,96 @@ env:
- CCACHE_MAXSIZE=100M
- ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit
- ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit
+ - ARCH_FLAGS_aarch64='-march=armv8-a'
- GITHUB_REPO='Tencent/rapidjson'
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
-before_install:
- - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- - sudo apt-get update -qq
- - sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386 --allow-unauthenticated
-
matrix:
include:
# gcc
- - env: CONF=release ARCH=x86 CXX11=ON
+ - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
+ compiler: gcc
+ arch: amd64
+ - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
+ compiler: gcc
+ arch: amd64
+ - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON
+ compiler: gcc
+ arch: amd64
+ - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
+ compiler: gcc
+ arch: amd64
+ - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
compiler: gcc
- - env: CONF=release ARCH=x86_64 CXX11=ON
+ arch: amd64
+ - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
compiler: gcc
- - env: CONF=debug ARCH=x86 CXX11=OFF
+ arch: amd64
+ - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
compiler: gcc
- - env: CONF=debug ARCH=x86_64 CXX11=OFF
+ arch: amd64
+ - env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF
compiler: gcc
+ arch: arm64
+ - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF
+ compiler: gcc
+ arch: arm64
+ - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=ON
+ compiler: gcc
+ arch: arm64
# clang
- - env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes
+ - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
+ compiler: clang
+ arch: amd64
+ - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
+ compiler: clang
+ arch: amd64
+ - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
+ compiler: clang
+ arch: amd64
+ - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- - env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
+ arch: amd64
+ - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- - env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes
+ arch: amd64
+ - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
- - env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes
+ arch: amd64
+ - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
- - env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes
+ arch: amd64
+ - env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- - env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
+ arch: arm64
+ - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
+ arch: arm64
+ - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes
+ compiler: clang
+ arch: arm64
# coverage report
- - env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage'
+ - env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF
+ compiler: gcc
+ arch: amd64
+ cache:
+ - ccache
+ - pip
+ after_success:
+ - 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
+ - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF MEMBERSMAP=ON
compiler: gcc
+ arch: amd64
cache:
- ccache
- pip
after_success:
- 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
- - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage'
+ - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON
compiler: gcc
+ arch: arm64
cache:
- ccache
- pip
@@ -73,13 +127,24 @@ matrix:
packages:
- doxygen
+before_install:
+ - if [ "x86_64" = "$(arch)" ]; then sudo apt-get install -y g++-multilib libc6-dbg:i386 --allow-unauthenticated; fi
+
before_script:
- - ccache -s
- # hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
- # exposed by merging PR#163 (using -march=native)
- # TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
- - sed -i "s/-march=native//" CMakeLists.txt
- - mkdir build
+ # travis provides clang-7 for amd64 and clang-3.8 for arm64
+ # here use clang-8 to all architectures as clang-7 is not available for arm64
+ - if [ -f /usr/bin/clang++-8 ]; then
+ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 1000;
+ sudo update-alternatives --config clang++;
+ export PATH=/usr/bin:$PATH;
+ fi
+ - if [ "$CXX" = "clang++" ]; then export CCACHE_CPP2=yes; fi
+ - ccache -s
+ # hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
+ # exposed by merging PR#163 (using -march=native)
+ # TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
+ - sed -i "s/-march=native//" CMakeLists.txt
+ - mkdir build
script:
- if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi
@@ -87,10 +152,12 @@ script:
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
(cd build && cmake
-DRAPIDJSON_HAS_STDSTRING=ON
+ -DRAPIDJSON_USE_MEMBERSMAP=$MEMBERSMAP
-DRAPIDJSON_BUILD_CXX11=$CXX11
+ -DRAPIDJSON_BUILD_CXX17=$CXX17
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=$CONF
- -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS"
+ -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS $CXX_FLAGS"
-DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS
..)
- cd build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3b9ac512b..bdfdd6779 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,8 @@ option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON)
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
"Use gtest installation in `thirdparty/gtest` by default if available" OFF)
-option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON)
+option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11" ON)
+option(RAPIDJSON_BUILD_CXX17 "Build rapidjson with C++17" OFF)
if(RAPIDJSON_BUILD_CXX11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
@@ -51,6 +52,11 @@ if(RAPIDJSON_HAS_STDSTRING)
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
endif()
+option(RAPIDJSON_USE_MEMBERSMAP "" OFF)
+if(RAPIDJSON_USE_MEMBERSMAP)
+ add_definitions(-DRAPIDJSON_USE_MEMBERSMAP=1)
+endif()
+
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
@@ -77,6 +83,8 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
+ elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
endif()
if (RAPIDJSON_BUILD_ASAN)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0")
@@ -105,6 +113,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough)
if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
endif()
if (RAPIDJSON_BUILD_ASAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@@ -119,6 +129,18 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
+ # CMake >= 3.10 should handle the above CMAKE_CXX_STANDARD fine, otherwise use /std:c++XX with MSVC >= 19.10
+ if (RAPIDJSON_BUILD_CXX11 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.10")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11")
+ elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.14")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
+ endif()
+ # Always compile with /WX
+ if(CMAKE_CXX_FLAGS MATCHES "/WX-")
+ string(REGEX REPLACE "/WX-" "/WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
+ endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qarch=auto")
endif()
@@ -219,8 +241,10 @@ INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAM
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
# Install files
-INSTALL(FILES
- ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
- ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
- DESTINATION "${CMAKE_INSTALL_DIR}"
- COMPONENT dev)
+IF(CMAKE_INSTALL_DIR)
+ INSTALL(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+ DESTINATION "${CMAKE_INSTALL_DIR}"
+ COMPONENT dev)
+ENDIF()
diff --git a/RapidJSONConfig.cmake.in b/RapidJSONConfig.cmake.in
index e3c65a541..c25d31258 100644
--- a/RapidJSONConfig.cmake.in
+++ b/RapidJSONConfig.cmake.in
@@ -1,3 +1,7 @@
+################################################################################
+# CMake minimum version required
+cmake_minimum_required(VERSION 3.0)
+
################################################################################
# RapidJSON source dir
set( RapidJSON_SOURCE_DIR "@CONFIG_SOURCE_DIR@")
@@ -13,3 +17,9 @@ get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set( RapidJSON_INCLUDE_DIR "@RapidJSON_INCLUDE_DIR@" )
set( RapidJSON_INCLUDE_DIRS "@RapidJSON_INCLUDE_DIR@" )
message(STATUS "RapidJSON found. Headers: ${RapidJSON_INCLUDE_DIRS}")
+
+if(NOT TARGET rapidjson)
+ add_library(rapidjson INTERFACE IMPORTED)
+ set_property(TARGET rapidjson PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES ${RapidJSON_INCLUDE_DIRS})
+endif()
diff --git a/appveyor.yml b/appveyor.yml
index 376dc1976..4044ba664 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -13,37 +13,85 @@ environment:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 10 2010
VS_PLATFORM: win32
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 10 2010
VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 11 2012
VS_PLATFORM: win32
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 11 2012
VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 12 2013
VS_PLATFORM: win32
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 12 2013
VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_VERSION: 14 2015
VS_PLATFORM: win32
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_VERSION: 14 2015
VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: win32
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: OFF
+ MEMBERSMAP: ON
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ VS_VERSION: 15 2017
+ VS_PLATFORM: x64
+ CXX11: ON
+ CXX17: OFF
+ MEMBERSMAP: OFF
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ VS_VERSION: 15 2017
+ VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: ON
+ MEMBERSMAP: OFF
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+ VS_VERSION: 16 2019
+ VS_PLATFORM: x64
+ CXX11: OFF
+ CXX17: ON
+ MEMBERSMAP: ON
before_build:
- 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 -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:
project: Build\VS\RapidJSON.sln
diff --git a/bin/types/alotofkeys.json b/bin/types/alotofkeys.json
new file mode 100644
index 000000000..3fc052e34
--- /dev/null
+++ b/bin/types/alotofkeys.json
@@ -0,0 +1,502 @@
+{
+ "4BABQZ5SZJSO3KFKBOG36EIXXTOF34HVFCELHA2DWOMIL44K": null,
+ "RSZNOTRIJFCHRKG4IKNOW4ZEBMVXPDBYBXBGDGNWTSVLMJ2U": null,
+ "AOGQPY32FQ7T7WZWQPON3X6GU74GOYI6HHVNPATDTBXRUQ4G": null,
+ "3PMTZEGLZNHSOWWJ23BE6PWOXD2VZRDN7MMLUMQ4EIRERVCG": null,
+ "PD2FMQGI5HTGK6MT76OYS2ER2LXFBON44WOMELDY5MRKQI6I": null,
+ "6L6QMMVSE4UQLB4OGX3LVDRNGAL6MOJ6S3RBBUSQ3F5PPHYR": null,
+ "LYVVXT7U7WN7PGGUHCLFXVOBJBSSR6ES2P7AY7XGBXEBLTDD": null,
+ "G5RWOLHDDZOXYEFGGSVWG3C2UHYDW6UOFVBQQLQJVZNCF4TB": null,
+ "3QPIK2M3ZPICZQFQTX22A7VDCAFIGAX2PXIXKDOZX7XUM32R": null,
+ "JR75L2BXOA5LVLNKT4EEZO2P45OHWRPMMWMFENTFFIY7A2V3": null,
+ "TESL546MN7IR7AT3C5HRSESIFHZ5NW6TNRWZXZ43OSRYOZKP": null,
+ "62EJKIAFWGFGPUS6YP2X6E26AV2TZCTCAJMZNWBBNFRPCCRN": null,
+ "5ZDD3KPTPGE2CAWR3MTFUSBMGQAS4ZP5WZKXJTXUNFSYABD6": null,
+ "XQ7TMN5YMQLAND54B4VIVWJAHU3TNZKT2S4SVRW6WKHNJBX2": null,
+ "O456GV3HBAWFDQRCECX6HY3PBTP6WNQIDSKVP2MZIPV3TCBL": null,
+ "WXCN25EBQH5WWN2JBHWNFNDUTYSFDLIAOWO5AE6D5HDO7VNE": null,
+ "THO3I3KDRIMTD6DKNIETIOWDY7FXQ5GJ3P2KUQJWYAEL3LXV": null,
+ "7OMI7VIOKFRZATMNLGIWH7ZBDARZ6ARXIAH5S3GPG5KV52IC": null,
+ "ESUPY3ELKCEGFRSYFGPGFBJOAUGXMYZ6XCWXDFOKHBJHNGVR": null,
+ "TNXSJIEFJLUFUDTR2S5LV73PD6ACFYNHOCRZPUSDPXDD3B7M": null,
+ "T6TISG6P4W66F37634QU4BNJY4RZ77QXXNPGTYH5LCCRDSX6": null,
+ "QTVAA56JKNDYTMV7DXAIL4QVLZPW3UHGLTKDI2BED6S3MGDQ": null,
+ "DTJREAQBCS6I2AJ6MOGTPIXK3ADB4BPNDIHI2YSQP6Y2BMH7": null,
+ "XDGH2OYCTAJ75IEMZ32O644YLT73PRYDORFKBLYEMCHOQ7Q6": null,
+ "4KDDQZRBLNS33DRHZHDMENCWGMNFEJGBZJXSGIQW7VBWOTHT": null,
+ "5KSH3GKWFNXV55KI2FPUDSD57O25N52UTZAAYDFVMFUSEE6O": null,
+ "7AGEUBM5FQZ2JCMUSKTEI6COA3Q5CE5WYB7TP2F5OX3ETMTK": null,
+ "HFHZ5ZE5TC45W4WIF6H7ONTHXKAVWRY2LXN2GN2TXZPIP6PQ": null,
+ "S3U2JJBPKZHZNOM3SWVFQ7OMS7F5M2KDJHHHZKXHZXQRNUSE": null,
+ "YHJBGJ6T6A7PMK5AYXDITDV37BJJIM4TP7I2XHSVYN76724O": null,
+ "TH42A7M3645OUKC54JQMDB5BTGS3URFUCYJ2VOEM6IAGZ5QQ": null,
+ "OYBKULFLWL2MER745QTDL2X2HJNR77QGH2M2P6TSCHVGUJLV": null,
+ "JDU37GHQUOCYA5I5LFS3WAEKKR6C55XJCCLJCCCQJEGUJEP6": null,
+ "CB5HEJZNJ2SWZM426TWIWLHTWAPWPT2AVVHBILEVGFD6NPHI": null,
+ "D4A5SJA2VRB4JGJFC7PHT35S7XAMHPZZ2PZC5YYVV7RLKSUQ": null,
+ "BBVT6NRRU55KNRK5G745FNMZVIFHVZJICEMODF4ZBJFQ3EGL": null,
+ "XBV57OEMT4GYPTTH56A6XKF2ZPMXSMHY7L3LUIS5ZZWRP2OB": null,
+ "GTFJ3NP4VJR6HG2DRNTDKVIWTMIALYUQIQTBJMKVM2I3QKGE": null,
+ "77BMBFMRGASXE5XXT6BRH2DRBNJMIAUDDMEXIJT3RMHTUPI4": null,
+ "FWZZMG7I2JWAHX4LBYAK2G4L4TZYLHXMJWIDGT6JC5TEBCPJ": null,
+ "J3324OXU2BG2NGFMSOYMVKXE6OEJNGENI7EESHDSEWSUVDVV": null,
+ "C636AVNC5C5EKILXT2AQPXYLSNH7LCAJKVDHP67MVHULFSQN": null,
+ "OXTDOQG2VIEVYFC23SKOBSSPGE55AVZZADK6PIHP3APVPHND": null,
+ "JLQVKV4Q2BQHK355NQXZVX4WJBPFOWSD7WIJX2P433KYO4SO": null,
+ "E4XHPOPWH3PRCV5MGQHR3BCTKZMOK46OH4Q6STZDPF2FG6SD": null,
+ "J5IP4A3DV3BHGGU3J72JVVTWNIQOLNC6GQES22MVATK5H7BZ": null,
+ "HHCCDMLNGOU2ABP57ION5TC33UF3NUHL2L3WUYCGZDWLDNTL": null,
+ "54Q67RURG4THOANPT3RAVF72TGKJE425GC5GD3EOKPY6MKVW": null,
+ "TG3BH3HBKFEXAUM5O67VVDTXZA6MHWSVNNLXLXIL2SE2ZEDO": null,
+ "Q5KJ25G2A4CWNGPPYXBZM6QVYA466MQX3HCUMUO5Z24D5JX3": null,
+ "QQZET7VFHGJROUQZSWSRDI5ADXVH26KEPDVL6PZ36ISHOKMQ": null,
+ "KWNJME4V365ZIC7SA7BYCVQUAG6URC2T6MHSO3OVDBJAUPFB": null,
+ "XHQYKGYVLE2PFNXQPD4OUWBASZO5OFVZISCVEFTU6K6KDKHS": null,
+ "Z4SPXMJIAMYD2H4U4F23FALBDZP6NRLUBDFU4PRGZ4SXGTI2": null,
+ "HSCK3PEXH3I3XMMEMIHTM7SDJD3GOKXUMCGOL6UXJXLCSCGN": null,
+ "BIUYMIDY4EVGRLZ6OLJK2CE2FS5TTELIWSEA6UHKUDUYX5LM": null,
+ "IJJDLN5ANXTMX54P6GW2J2EJGGWG257YEAOZMXUSWK7D76LH": null,
+ "CLMTO3VSAOBAOBSA5IGOO4W7KEMLOFUOIR564IBKMJA7RWEY": null,
+ "JU5DNSHLUW34DT3IQ36JBV6M7EPILLMBALURDAB2KJXF6HQB": null,
+ "VXZXWLNQZFJPNQVPTOFWUPLORZD2XRAFXRVRNLUYTPBO22U5": null,
+ "HNACM55ZSGJ2FGRMOTXLVVLA32BC333QGC4HFCDSZ335YA4N": null,
+ "6J5GIOVKU4PKHHU35DWL3D7GTJFF75FF4FKSP2HPGJ7SQ2DP": null,
+ "O3NJM537IQSKKWM3K7EOQSNQDTR6XKUA7ZR7CWYHYYLHKH63": null,
+ "B4QMXK2EAR5E7KGHLODCP56DX5HW7IQVXWHFFCZ4SPSSNGJK": null,
+ "A5AUZBXKF67OXO34ZSEGVXI5PAIG6W2VG3U5C2Q72SNWYNEI": null,
+ "ZGDQ2AA2IFBSU3APKAFL5AO4C4DXY2YBEHXE5UPPVCTFZ36K": null,
+ "N3XZ5FYZEO3ZX37OMUJX3PIWEEV7TVEXX64KKEZEJICKXMTB": null,
+ "3EVOEEWTD7OABLQJIJYLOSVHBS4SB6QGX7GPDFGWI2DGAWKR": null,
+ "HNAEL3D7E2S7IYLKLIK4CGI56DRGAXA5S6KG3RX75PMJ6BVI": null,
+ "VGVW32CIRX3M45J2CPCUPPHNRGNG55MKAU7YF3CDNMGONW2T": null,
+ "QV5MW2W6WQSHNC6OYMWJAWEQM7LHXRMGWCJ7RI5WQ3JGHARW": null,
+ "IND2PUTLFWXTEUY4MMEXCFJA7JN7DODE5HVWC5CL5ED5IEUB": null,
+ "W2IA75XHJRBRKXLHGB7LXD7ECYEZI4V5N5I37UFXJMFWQMYR": null,
+ "AWTZO6OG6TCOUVYYJCWVP2JYEXRXZ7S7F7QKUKZS7JLPKN3H": null,
+ "TCARJATK42Y66SPMGOZ2LHLT2ZPZW7MHGXL5IVTS272FJV4U": null,
+ "XVHBOY5WQDOTWXVFZYQKZ6GNRWMITJDDLXSJ2T3UWF6PFOHL": null,
+ "CY5FGDYLB4UFR4AJRGLGPQT3W3OERGCXC4JHYKJ4HKSFTGK6": null,
+ "B3SJGD67GKIEAOZISX7HWENPDBYJHNJ47JCREGXQ6G2RXPUZ": null,
+ "LWVJYH7M5KXMLPFAHTMF6FKT3PSIW2GRC37AHF65PQY7OUE4": null,
+ "UUFKWC2DOV4ZQHPDPQPRCBEYNAX6OFZ7ZVJNYGW5YZCMSQIS": null,
+ "K5EC26CUN365DZ3LE2NHOINGZHXQ752A3VTPN5IMSRYSTOMT": null,
+ "22RV6RSSZIAFXOZIRAWJAIMMVHYWGL2TY42U3TG2SPFN3I6P": null,
+ "Q7VEOUC52OLXL53CR4XQSGGR5QZ2QXZTRCBACHQFP2HKN4SZ": null,
+ "OZ2ZBCTBC32VOHHBDABY2U462OHUEUS724RUS7Z6TW5K5ZFQ": null,
+ "EYXYWTX2UYI6MUK5L65WSTX2FDOJASIMG6ER22NLABNGAEMI": null,
+ "U4FJU7RQMXXDMHG7B5WFLXCZBNE5PMV43CE5X4RJSJUABT3U": null,
+ "K3T56AL7IXTAGTVIWZHYRKVPHLLD7UVHV4UNU76F764VGY75": null,
+ "U2BRKWY2RBYV5S3XVZTUZXT55CXMB45KDMNFMVY6LENW2DH5": null,
+ "YKLPZ7SDAG2O6NSJFLVGFVCYMY4WZKXQGHH7OO2BKGGVLQNP": null,
+ "WSC2BHA7H6Q62HJIIGQFX2OU64QX4AEU2RZQVIC7LSIO2JSJ": null,
+ "QIFNFKPJJCYPITMAYDAOEXBVEDAKBBR3DV5ZB7DAVBIAWI5K": null,
+ "NMBGIDIK3BMS5ZPZS6ATTID5BOAXZAH2VUED52JSC5XGI42P": null,
+ "LTSG7BGZVBLLXM5U2QDW5LNNPM3B5EQZPHES7JXU2EAQG266": null,
+ "5MZMVLLM7YHR4PTQCGDGWFQQLNN532WMTFGX5CFTDURBYEOH": null,
+ "UOMT2ERDBVXC3LRYKCVVUNROBWPGFHFWKFCW65HAPXN2H4FD": null,
+ "RFYZPAIVYHTITTR5AKOBAMYKOA3VSKRTK4P4ZOS7JFSVEY53": null,
+ "QQJGQV6BSW6PL4DZGQDWWVTF7U5MEVPQABOA4IRP7NOD4V4V": null,
+ "EFOSJBHVPSGTB3O374JFJW6MVW47ODOZQNKYSWHR5W6UZECP": null,
+ "YTL42MLIGIUD6Q3AMVMJ6ZMWNSXSUWCKV4ZUQWSGTEOATQC4": null,
+ "F5IL5OV3Y6E4QEE7JMQTKV6ULJ5AQQKQPZ23VXK72AV2P7XG": null,
+ "AZEV37T65EWVWQJSISCHTYHLWRXWCR6XD4LJ4KFLJ6RAOPF5": null,
+ "T5TAAFPNZLVDYHSNNHIJW4KBZWNFT5CMIPIWW3EFKPU4REYG": null,
+ "W326OLSKXRLU6MEIVUTKFFHFGXEH3VM43F353L3NHQP6HE2Q": null,
+ "MIIUZQ4KGTLA66VIE7WPN4T43SR6Q42YUKWEP6467AYWKU62": null,
+ "AXSJHLTL4FXCMLLJTQS4HIBRGUY6ATR3GZPV4MGXLWNFHDYU": null,
+ "MC2CMWSKD2HMTVIWCMSPZWHEGW73RWEZKU3IFZJM33IW3VI6": null,
+ "ZGOZHC22WZN6LSY3KK4HK6RF6F73VWSB7U47KZSLTYOQZAVH": null,
+ "HU26VJYM5YNEXCOCWCVEQNNZ2WAPFEVYK67JZOHMSZIOUWJN": null,
+ "6ZA46O27SWCAX5MQUHZYFV5UNQUDLZG4LDA6VILK6YRQMMZ5": null,
+ "LMGGW3CAN4T6DSVJZB46LOBI6KTZN7CKHNZ6BMWRBL5PVYXX": null,
+ "RZKIP3F5SY2P4NWANAQZJHPH34CU3GMQ4VCN4QXMP7ZBSQ43": null,
+ "CMUAX53FME5Y62VC7T7ZOUZMOPHBDFVLMVVMHYDDBZEHMOOA": null,
+ "ORTA47K5MLIHEUXQTFFTQNW2RMYQSTVDJXUNIF334SAJJYMC": null,
+ "XEGLAWIOOPE25FDXHN65P4FYJVB46M4NGGXFAWZ5VDWBBMU4": null,
+ "WZGXOCCN6GENKYYAYCH6UQD45BIPSYMQOZYAYRU3S2JNJLU3": null,
+ "MXDDSZA6VTTYU56ONDE4QZMB3L2D7A5SCRCIVBYYVIKFDFLU": null,
+ "JJMW475CTRXRR4R3GEZ77STHMKHTQZYFZHFUFXEB77SV2W3H": null,
+ "J3TNJVNF7QSTIJDEEZMLTQECNOES4PXQALSR5ZPYDTIVVKUB": null,
+ "Q5EHPI6GHPPZBATKHYYEXNDSYMW6QVAVKKHC2XO7RU7XXKQ3": null,
+ "B6WGKJEZH7XBZ4VFFRCBFYKC2Z2ZQXMY2HJQUH4LVI3EDMMU": null,
+ "NZ737IT3LUIMH56R66WFETEHFDOZSNVPTHMQTW3JHVTN562C": null,
+ "B52PWLRNPFN73AA63O6JFLEYSPFQEIHQ6AI6YC7KWOYFE5OW": null,
+ "7UTTRFE2I5WB2XZA37L6F7RWCII6S6HLXZRTLSJYFOENAYPI": null,
+ "TJJDGG7R4RNVAOXWRZRZB5K7W2Y6XB7LUYBDOY6H5IDRM3ML": null,
+ "TOG35JU7ULNRY3DE2XYDZ25WZETRSO5WSFFYSZT5IIALO3ZP": null,
+ "2QZKK4CMZNIKUWZZB22ASDR2BYNRAMTNS7MVLBA7Z7RDKZDV": null,
+ "US4C6FXHKR4GCRU6IJQHSAJXLNQGUDCDEPEQDU5C5D76I6XX": null,
+ "QOPUXM3ZKXTPVGMVVDMUZZ75KH2S7DKYXSFCQ3R5RYO5WP2J": null,
+ "GZ2T37SKRE3ZX7FARFWWF3WG443LVP5X6ENDLDHO7GBWYHHM": null,
+ "VSOOUSBMGIPEVAPYAGWZOLDUW5HSTRMTBRTUYLQNHKVUBLJ7": null,
+ "45HJFJQ3YKDBFDZPNDO46YT7DLG754XZWMGJQ7YPJXQ4G4N4": null,
+ "4KY77KV2OWWFEVIBSUZRGZF2V47BEFFHIHNMAQVK65E34ZF3": null,
+ "NB334WI2DNPLWHGXBNHSU4436ZYDQ4D2S3JMLDOM35QINZTR": null,
+ "7K23M4FJGIQFWUMPRDZIK32MF7HZULYYSS5Z7N7QTEJGET3D": null,
+ "ZBMNFKSEG2PXKJZIXIK2MHJQ2ONRJUJVCDBOCHNERPGMN2NQ": null,
+ "YMCOX2NMBDL4J6Z7JBEWHFSCWON4ZSBSBU2WONEYYOYRA75K": null,
+ "GDOVKPAWZFHLAPQ5YHCFWL4NAMC5G2DDXFWUTR27XQ7LEOOQ": null,
+ "CYBYK7ESXTUUHYQVPMDI7VWAZO5TVGLIB3GB7NYRYVDLMYKG": null,
+ "4IYLX3IDNUJ2DWT4RM3QJ3IMVE22X67EW5KWSMZHIU4W2W5B": null,
+ "EBWXJZ3PX7LE4JNB2XWJJNXL5QBVSJQSXAUJMJ34YJKR3JJU": null,
+ "LEKOXMXHU57JTRZUKMCW4WDCAKEOXPHJ34ULXN5P6DIEOYLL": null,
+ "BESPMR4LBE3G4MTWR22CVBYH6NW43HO4ILTSV3P543JZUBD7": null,
+ "5SYIBXIHGJGE4WHL2HYUNK3X4JUGOJOUMKVJMMXSQDKJZHFJ": null,
+ "XN42HP3QOV34GMJA5VINVW3O7KWW2GV7VDKAZDFBCC6SSHNQ": null,
+ "326BDEDWGYW3IMEHP63I6LVGSRMS6DUUNMPY3YVWXCH3YA67": null,
+ "FYNTVFBPC37FYGOXFIXJP57FNX5MYDGUWIMUYMFOJSOXRRDS": null,
+ "7DRCBIQP4EXAVNEMWOZHAEZ2W2EIMKD77PH6JJWP2BDN6NFN": null,
+ "7Z7LWVFB2Z26EVYZPLQAOQ7LXLADTHUA7QGKDRFLXRQ3ZJUX": null,
+ "EOZ2S4T75U62LD4QUZNTOHP7SNVJUNNSE7WWGHCMC75O4XPW": null,
+ "TVG4ZY3YVNQV7WPZ2CEW26QTGWUBVJV7FTRF4TE54446J5SI": null,
+ "MQ62OHPXMGGASRXKOH5MEVGLYHKNWBT3DC7XSXPXFHFXFO5C": null,
+ "MBRTEJLOZ6U43EOO2IS3AHNDCT7WUEK4XN5ZRMTPBKUFXUWU": null,
+ "24WJGDPNT4E7SQT2IBSTHJGYBMEBKS7VPGJYBRRAT5YXNBC4": null,
+ "3KD7I6FOTRB4U2JBT7CIJOPD5XHFWHESYJJQTQVUQ3IGIPVZ": null,
+ "25XHQ7A3DWKVDBX2ZFNIHKOGJCXY73N4Q6PUBEWGH2I55XVP": null,
+ "GE3YTUBPOT5CFJU2LQVMZVC67NFNLXVWNTV4ERN6BHVGCGYL": null,
+ "VXE2WHW6UWRE4WYTAVFAQ75IBYUPNZVMHJC44DGDPIAEOVVE": null,
+ "5JRWFOAEX5TNCAMYGF44C72EWF5NTXIRSVST5J3N6N5SLGFF": null,
+ "TYNIMWTDY2D565BJUNMFXTJHBUMWOTD4YSAFILKXPKX6FKRO": null,
+ "RDUDIY6N4RRUA6YEBBBFPBNYFZQUWRVURNYGJPEU6EHJA64H": null,
+ "MMRLX63PFJLWBJUTXCSLALIGK5YOHTLAY64WFQIYQJCX4QID": null,
+ "P4T7UPQNUAFMAJ3G4KBRHOQP5GCJP46XXYKPTTENUI36YQEP": null,
+ "VNAKVK3A4TN7WEZAJBJVMUVIKIUWCNH7B373DP7WAM7ZXYDD": null,
+ "VAPNA5BJL7OF7VRVSUEFAG6RZWENO5VOGMFVN6AB4A7H4VU3": null,
+ "TLVHDKN7326OHNXMBBJIVQW5FFFGPXSUR2IVTMPLOLPPJQW2": null,
+ "LD4OK3CY7MQGHUMQOMPAJY2NZUASJLSLWVSIIKIYYYAFYHIK": null,
+ "DXHC3XJCJJG2SMU4O2HDPMJHO4PNNYGIMLB5KSCQPNLBAJER": null,
+ "SANGKO55HOXMBC627JYHVBE3FH6KJL74ITOVF5GYODRRMEMP": null,
+ "TOQW7HYYWSFH3NKL7SITPX5H4HLAH7BKL35ECCAILLJ5B4TA": null,
+ "WUKAWAQHSBKAUAYEQ4UA5PKFB4676VQNQFLXUIX6UCDFZ472": null,
+ "BDU5VYNLNHR6HOLMZI4XSDERPTMVJ4LBUX5XP6W2BQWH3NLR": null,
+ "R6BT3RGKODHZN2AEX26XHNSLCHGPGMQ7IS2ONRTZEPJECW7A": null,
+ "E7Z4FLW3UW2ALRLPSMHQWJWBK7VWS63H3AUZZL6LHCIG3Q5B": null,
+ "FUZAITDO5EH4BU3ZAN55R2RQZ75LRAYI4X3MEJKJD44VHOT7": null,
+ "7SZ7VZ5O2OFPJL3K5JJKH3C2ZYAJCWW5GYXSLVFHRRATZDFA": null,
+ "6H7VKVPSP4MHB6P7H5KLQQN3Q6ZSS65OMK6GJ3JIUMHQINMC": null,
+ "QNCN75MNVAVH2OQR3JE53SGCKLXPSB2XBTZ55J3AX37AV5HT": null,
+ "JCSYRKMHDGVUVZO65VQVAV5SGQS5IRS4UGFNFKMYP6CXMHXN": null,
+ "JXX5VCQU2Q73TK5ICSFX3QIGA6E4IFRTGKPZZY32UTB2RY2Z": null,
+ "BMUAPYFGRJO7ZQAMMSSEADU2RC3LPAAXTORXLSIUCXCSSC2P": null,
+ "3SPFCAR2V2PQA3RWOY5ZZXI2V6UEUCZWL6SNCGEAGNR2JQZV": null,
+ "KUW7Z4ZHRUX6DI6Y3ME7A33SXUAQPXFAHRG4IEU32ETMGTLC": null,
+ "64F67UZGQHZUXLN6HCATAAX2FUQNK2WVOEJGBQ27H5DVZFC3": null,
+ "GHMJSW2TE6E3JLFDD7T6FI67HBDHNDVLGEKATAO5G33TID57": null,
+ "6BZEOJR372ZLNXUMEQQUKHHDCAOE5W4YDT3VWGI3YYPYDC5R": null,
+ "62JOKD5O25I7DBDFMM2BRQP4HI2VJTUHMEF3G3C7JFJF2VNL": null,
+ "NEF5ANHSBNEXLOP7FFH7ZVHPDOCHQQ6EYOG64JDZNIHBT44L": null,
+ "ZKLJACJIQT6M7KUY3VWTMQ4WD7RETAWN7LDUB7UQA3NZHZLC": null,
+ "VBZVHDFHE464JTYWCLYNAA65RDMVURJHVZHWRL3IKTNT6AH6": null,
+ "FHBYZO5SUBQ56J72DWYOUZSDKXE3SKDRWBEGLQPHWUGVSW5B": null,
+ "HHWRIAY52UXIOIKQOL3PBERZFDCQXAAUIDT4RTZF2VETEY3Q": null,
+ "JALKMRCQEIXX3JPLOACUZ2DKA5I2RWSSSIYDVSURW475XHR7": null,
+ "IMQUFG6JBGWA7R3D3NRMJNOF5MKE2NU4H2LAI6UPIHUEY2ZD": null,
+ "GWSUUFLKG23Z4BXTLB2HJHYVRWAWHKV5MA5RVOEE77Z65ILK": null,
+ "ILKEEWZSHVZSQ5M5VAZH6MJPBVQVV63SCQSX73YGTOQZBFKB": null,
+ "TBU3SS7AG7QISWIK2KKNE77ISJUEVH3ZV7QZJAEHLMAOUCEZ": null,
+ "EPN2PRVPXZGZ6WRX5ZMG6UPIM2V2NEA4BBC7ZDAIVCEKMHR5": null,
+ "Z7GJAUSWDAH2JUMVX6IZB2PRSIUHYUKXGKJDM7FXVFDJNDUU": null,
+ "APOEQP3DLJGKFU7424CJJBFDTWODGF45H7HSXT3GO2UC3VCI": null,
+ "LCYBWI4HYCSVGBSWWDJYDCWQZGJP2KVSXUUJBO3XFUWOS4SA": null,
+ "KOTWM653HSOQ2JHNAZGZZA5FGBBJCCBYPDVDE7WDXXIHTULF": null,
+ "TIPJO4GHBUJQKWKVHK5RF2NI5Z6FAIEBGFPR5L4SSCLS6IE6": null,
+ "QJZMGE4B6UPJ35KTTNIAHWTFV7DFQZ2QMF6DLHB2AHZQ45CD": null,
+ "SDV2RDMAXCYWHJJRPTEIZVE6SJST7KQJB57AXCWFVO54E2GX": null,
+ "4NW6WJDWXCXG2TS24H4I7WF2IGROPO4UBN2HJ64M3CWBU2M7": null,
+ "GJPMFWNBHZ63VB5XWIM52UO22ANEXDYLHTF24LGBC7XXI4SH": null,
+ "I3TPFLVZ47TOOMM2G35JFQAYHLAIU3OXV4SXZEP67DNGYXN3": null,
+ "QMPKHHYWWSV32R2LHCWFKBFDXUDUXTZ7FRZK3TCF25CSFNWD": null,
+ "J3C6XZSMIXH2SQMBUEVWEI6UZVX2GJZCAYSPD74BBUUK45RS": null,
+ "WHK5HZ42VH6IJ4U4EUKKVLRAID2FH2YISR7IV6FMNHQPPSH7": null,
+ "C62NUQB2FUJTY5VRNI6ND26FXCUVACSUTTR6NZMNQPYK6357": null,
+ "2JXXJE7WN7QWO6X3ESQCSDDBTZXOY43L5AODQUIR5P6Y4PZB": null,
+ "FQVJ4Y4GES3RGRABQCJIDIYEUNTIGETQ5EOXW25SZSYNJENT": null,
+ "IH2YJNGRU5Y3ODZHMWNV3TIU2MGCNLIPV75QL3JL4I7PH5ZI": null,
+ "RYUBMVYE4PL6JJOSBM57NE2RFKCY2EB3EQR3QU45MJHEX5IN": null,
+ "KRVCQJ6VSHM52MLDNS65PKDYHNBJAHCONQCNLXBD76LDCOFY": null,
+ "W7MB2FYKYWXDXNOKVWJW7TSUANZIGE25NABNIAK7VLPLKQQH": null,
+ "QUJNQSAHDXMNHKHHIRBEFONX6NRV4NA7NKFRDI72ZKVZXR32": null,
+ "SRQAJHTEQYVNHCJDTYHA72VSYS4FPTHXGPFYP6CQRTEUIWVN": null,
+ "GYQMORZKT4JGWGOD4KBEMUB3XZNUM7H4G5IRA6SYDZOGAPVF": null,
+ "73P37OKSAJ5SWM5NJ2QWCTKPTFNLORRRGBNJWR7BTCRLKNCO": null,
+ "D7YVGR63MRZ5YS3UTCUZ7REPWGB6EMGNI3LXZUDAYBSZVGHZ": null,
+ "JNUZON5EE4CF5UIPXIAU5HKQSBN6O2C3OXJ5IT6HPZMUBXRK": null,
+ "3UMKRHCWRV2WNUWPF4WKESLI6EOHPFC6FOXF2MGP6E7GPKF7": null,
+ "ZPWCDBHEOCZRBAVIQNGRQ4WNKSE4XCXWH3PQSBJWVTMLP6AD": null,
+ "RCOP6UXD6CG5XYUXFXT7HDAWQA2LRA52R2NVABFBB574N62D": null,
+ "6EHQW3VGWSY5MQKBQ4PWU2YD4KKXPBUFJCBEEY6GKOGGGT4P": null,
+ "V72EUDLMYSS47DCO7XIEYQO4S6KK7ME4C6VN6IWLZALPDIR2": null,
+ "EX6JHHNN4R7BQVBTVXYRD54J6BLOJTRHM64QBK3DHUWW37KF": null,
+ "6GGFMOEZN5PBE67AJM6XJKDL7V6X26X3TH2WVOO4X2MEQJKO": null,
+ "LYM2NDKVFTJ2IJV2G5HTDDXFDAAHVHVMVTNGBAOABW4JLB7V": null,
+ "5GPR3EHGCAFLKH4CTOZK3JBHCJSEEFD2Y5GS5Y3B5FPXAK6H": null,
+ "3TVZ6BP47YPHI4HKRIK43AJPRVM5UO736FF7WEXI6FJMTKY7": null,
+ "XDL7LZWG4CIO574WINYHCXMGRRZV5BMZQH6GPTTVPBWGV4MD": null,
+ "OHDX42IVKOGGQVXFE7Q3DKX2HNXGIZRAZ5TVVKQ34BO7UKPB": null,
+ "QHSOVA5SCRL5AK65IALQZWLHPSMLOOHHS6JN3LHDCN7DEHJ7": null,
+ "EI2J32TUZKPKSWOYH7EPPKHISCJ5SPTUFJXENKZJFAPEFQJL": null,
+ "3FFPGZBSH57RTBR326VUSL4G3DELAIPWCCHB77LFG5CBS2YU": null,
+ "VOLJPHGJOQKGKQ3PQGRLYJBZCIF3T355GXCQQKV34USNOXNX": null,
+ "ZASYP4G3K3DX6MMU2CK2P6GJ2PKRQFQGFVEZGTMIRAZBDMOC": null,
+ "MSLOXTCY6MPU6XRGIJ7ZGFBB5J4RTGTEC2UW2LO5MIKPXFJO": null,
+ "DM3ZAC4JV4IDN7ZZ2OLHAUCUEWYTMLZSQQEARJF4JVBUTE2D": null,
+ "KWIXQOXXGHTUPBDCHXV6ET4YZXIDCYZEQTFIRHD7DTMSGZ3X": null,
+ "SOF4BRIWEU5XLSXVFE6IHVVDYG73RK5HJACKPUNFRNEDHRWS": null,
+ "4FECMJE2AGQGN54LFXTIQFZC6ZVJN3LY62YCS4E65PMW2K5J": null,
+ "VDCWL2B5OEDDB2YGM7Y23WLJPJBFESITFU5AWDPUKDUMFPBO": null,
+ "W6VC6MV4GBWJ7IDAX4DQHWJSBUJHJN7ADFJ53NBVND3TXUCZ": null,
+ "Z3TTBMVW3FCTJPLHXITOVK4LPLUFJJY3CIYKJ4QY2DANJ53R": null,
+ "O6N3PZGXI5B6NBTOFPB5WWIRJ66O4FYLSGHDIJLVPT25YPWK": null,
+ "RXCNDGG7CDEMAOGCALTPXWLUL7A67D3JSKOZSZEQBLDW2F3S": null,
+ "XVKBWW7HRXDBW3YXSBMO7WVEUPVQ7LRZ44RVFI27PYZO3NTS": null,
+ "XUSRB4YQDOYJALL7CK2OYFPL7GKI6XOFYHP7HTW5H3PF333V": null,
+ "PCCHIGPV6SWW2O4YRPMFMNF5YVW6QY5IF7JPYAULF5WPTYKB": null,
+ "MHRU7JFEPHHUAULYL34RAEAGBU2ARZG63TGIIS7MHEQUKWPY": null,
+ "Y6EDYRAB7V6NAP57DRIKQ3SB57XBPN7MAWD7F3DM4DKWIAMA": null,
+ "JQXEFOTP5HPBTKL4VAXYCMJFZVGSAM3JVLFJPQ6KHVLCRXFI": null,
+ "U53PDNGH4IKMP4PW6AJV6K5Q43PYB6VUZ3IJVEKZK32IR5WJ": null,
+ "52CB2E7VQJ3JJ2SXPHQZZMER64TM2JQBSW3JMX7XITCNSWDT": null,
+ "3JLBHZFBPZQTO3MLCW6S5N3RIR42N6RGDHMP4U6IO6STOOVT": null,
+ "YTFVKDUY6LHHBY5JBBTT75RYI73Y2Y2DFT5PBMOLEVBJEN4Y": null,
+ "TAHMINQIUDTCEBCJ4UH2PUXO5TYMIIZTH4BX26S4NRMPFD6Q": null,
+ "4VJIQ6FLWV6ONBHRWDR34KXCTHL7HIXSQAF3FAKOMZ2C7QV7": null,
+ "IQWFFVGP6CPSAQWMKA3SWYOXAUL2YCD3EJYRQ56S3VXWAMUF": null,
+ "J2FABCRQ7HZFV4FKZKY2UOXRUO4FYXANTTWL27ANRYY6XZC2": null,
+ "G3TOY5CIOYIELRC2S35CGAS2E36TDLTO5XYXHFVKZNDFQC6F": null,
+ "SDKQB4B47LL6CAFDDYJWDS4X7COKTZOCQ6ELJBL2YF6RHZJC": null,
+ "L76D3LKKTUAWNPDXKTWE7JCFCRFVI4UX6NKQS3CAA2OWVF4K": null,
+ "QVYYK2GQF7DHSJACSOZPOQUCWWIYTRGEWMBIR5RRCV2EPQ5X": null,
+ "UM3PJVMZNDU2GJ6KVY5VQ2HPGMSJKVAQBDRKZKHBPBRCU5SO": null,
+ "RDIJQSPXHAUB7XSQQPOL3CNUR5AJAJEWAFYFSDO5G4QWZQCV": null,
+ "3CAVVDQOCSMOPC54JWKI5ITUIHAOV6SKAIIAAPAAJLBDTXEM": null,
+ "JHLSLTDSRVKDHWRGT55OZ5NC6YHGD35WHW4GPK77VZWPNVKN": null,
+ "6K266T5MHDGFA2XECSFBMTQDEE2C4S45S53XBODESR4ERZQ2": null,
+ "VJVWAFFKWR2KSTFIWGAKDUG5VQTO3BPTI7YFYZWZSBMMQOIN": null,
+ "LBSXWCQNCHYUG5M255T3W72NBPR5MBEPO7DFBCD277HSH4DU": null,
+ "WHJGXILLMK23VGXI2OY76SYJQOQHQOM6OSLT4BWU2KSD3OAD": null,
+ "DVNEV7ANOMDRQDHTEMD6CXCTO7NOY2MQQOLI47U4DDOJ2A2M": null,
+ "TV752NASHG7FG2JOGS5P6QLJ7E4W5NX7F3OYYRPOEFZ2NREE": null,
+ "S4DHHYVQ4RQ7HBAXW5ZKISZMULMLCFTSBFICXNLI2OD7YNF6": null,
+ "HSRHOS56TX6EEDHUZX7K4K6Y3R2UNHRINXWVK5WBWHDPE5HF": null,
+ "I67YQZJ4PXHFWHNHMK5SKUEFIL4EEP5B4BH3TJNHZPQOUXDM": null,
+ "5AJTMUDFBWW3EGM2TH2YAJYXIR6GKM7RPBYBRV6KEQPDDLM6": null,
+ "6V3SAQQC44I3CSDERRKA2533GYIWWHUZVR67JAWIBPJJBDBI": null,
+ "5I6EFWIWLDNJQAZNZN326TUHCUY5YOD4ITIT6NL7LWIK6RP4": null,
+ "NVT5LE35FIT6LKWBI5XZO2Q7CTQBFJ3IOIAFNXI7PGVHEE5W": null,
+ "E5I534XUV7GRNCMHBVFI7FMTSPYBGXKOFVXXSEQYYLVGCASL": null,
+ "3XDVU325YQTEXC7HFJKKKH7CTCCNNJZMV6VRT5GVED7HFKMZ": null,
+ "3UJYDR6QUVSSCRHJT6WWNEHC5OMYXOPL3EF26PU2A5HESFG5": null,
+ "UPRVTQXNXYCZG4JZIR7GZCCYTXR5VTUR2OKAJXEWGATCSIOH": null,
+ "2QLXXZPU57ZXMLJHEYDS6IHFLQHOKANOE5URI2TRNFNSIFUG": null,
+ "JFL3SN7LZ7M4RUZXRTYFQTUMYWYHO4P3ZKBGFDC2GGWZBPEA": null,
+ "SBLHOHHAOCNEVQI3UPBY5S4UKTTIH3DEJEDJHWMJ6VEWWTCL": null,
+ "TIE3GNWA2BE2WGFA7Y3KEHF4IF77M5XHZB3DIQLOE3GG4VQM": null,
+ "BB7XBWIYV33TZGTKHTBL4PDPH5ZQ6X7ZCMHS3KIQEJOLOXVH": null,
+ "6WO2JPOCRLCUSXS7BHNKFBDGFSEXCWYUFPK5SDZJTFJAEJRV": null,
+ "RCJUMHWKL3IBJ4ZVWHK4RCZ4RCVVTMG5ZO2KWZOIVZLJTSMT": null,
+ "YIXCNMIMZBA7NK2A5QOCLE77QFF6QDS7NGIHKMILIUB37EMH": null,
+ "ZSI25IY4L2U7CRPBLOYY5TCSAVG22XHHZFC7JZCRAVY46BWH": null,
+ "HUSGTJENHNIBJ7VSWZPOWFHHKKYH7H2YSP32LLQ2N7CWKRME": null,
+ "WTIJK6LZPBOCIJFBZEG26BETKTY5PJKQK5D3M5WVPWVSV7LN": null,
+ "ITSWONDXALFBD4WMGSMRKQXCVTL7JRKVFEHOAOODRQEFFSWC": null,
+ "IY3RQGYC2ME2TEUBYAQG5WJ7WOAJV5GTO6P3FKXWOLSJWGCD": null,
+ "MDSHVZ5WHCTCYB34ZABEUJJRXHQDKO5MSC5YVTGPMNJRXQK7": null,
+ "KHNSXQTOSCRSTX63S7OVO2LGMD7OVR6PZIGEKL5ZDYPCEKK6": null,
+ "LECVNJKLFT6P2HWX3H7ZC5DKJSSRZ7PWZVBN735K7I45SOX4": null,
+ "HFEO55KM3XH34UWCRYM5CFNQ6OFRAKM3U6TABNQDP74DT4JQ": null,
+ "QZOWC3TAAU67PVSBRJOOVZCBSRIOZCMLPB3FH4GS37WOSTEZ": null,
+ "TSB72AJ4HHOBEYK4CGFX3W4RW3SIECQYJMYISHTPPCGQNLFD": null,
+ "6AB4YKYVMU2PXRABAUBBBF4BJ3IOFKYWBJ2IMFMRVLCBI4S4": null,
+ "E3TI3V725PEP7U2CYZUUKJEBPAHOEI5SYCR3YZCMGD5EGYHF": null,
+ "APKJUBCO5NHY6QBYNA2ADB5TTPLCNZMHG7HGXXOLRBOZD46Y": null,
+ "QKL26OQG6L54OCKFPLMXI6M3EG2HI4EG34D7BNI5SBZG6OF7": null,
+ "W4KKIH4RPYXL4JZY24JWLHOATFNENBMSEQQ3DI7WW4PQIJQ3": null,
+ "4XJPWCDQXS6MSKI4EMFPENOX5FV7KMKKZ77LV6GJ6S7ZBVB2": null,
+ "LWMCTL5CEAVQDT5PEXFKRK7Q264CNVV6AU657OQ3SSPCDGSQ": null,
+ "CBMCT6STEYDOVXT6OW34OXGZBN2A77OGBPDRN5AZK4RXNEV5": null,
+ "OUGRMVL7PTQ3GJNWQ5WP7XXNYBIMVWKSNQ2QZH5RZRDEGUND": null,
+ "XKVAYVNQL7KW5EHGEWYRPSWDXNUEKP3YC3OXGEHKG7PGNZHL": null,
+ "ZLO6BOTXUEEW7UOENY2NVIFLSG37YPUETQBYYCQBJM5VXNG4": null,
+ "QMZJWAJYYE6WZQX3OKY34BPU7ZZN6ECDNIZOIXREE6AP3WJF": null,
+ "B5FU7VNVUSA3ODDEUDVTKE7GWPU3JQXWHRWYGLT6VFKSFYAA": null,
+ "HLHSAJUSHU5EY26UTR2UDJAM3BIHYYHF46MNLTQZJWDAUCDO": null,
+ "N73SLU2EDTPQ54MY5NWT7KPSVTO3TOGPO3DGX4HQYPZMFYJV": null,
+ "7B47MDGTJA3P2WX3KWLLESWTC7RJUSVUSBI42SATEYZVPL5K": null,
+ "YYLWTHMS5POBP3WVX5Q4NXQ77STWJTAHE6QK7GYMBIJU3TSX": null,
+ "JI7Q6GUWUTSJPHKUII5IVOUZ2QQ53EWNWCUM4PKECXWSVSEK": null,
+ "XR4W6GZYNYIDAFU7MWMIGFGF63OLKU4FWQZ4RAN3HWNXUINB": null,
+ "3KX2TVZZAQSYQHLDSWMVZVF4UAXYONTXXFWSGI6CJ56DXU6O": null,
+ "UR6JGWK36D4CU63DYI722UFUKLB2S52ZI4OAVZM7CVGGY3SW": null,
+ "VGQOGZH3H5IAFESOYWHOQGU5FHP4BJAUUK2B7AKDCJX3PUE5": null,
+ "Y5GO3VITRDTHWTMUULEA44BVX3GHVLIWFMTNUY2APWRL3JLD": null,
+ "F7U4AV4VU7YAEDK6SI64JJUNEHG2MEFLKNOI77IVDQS7BGJK": null,
+ "D77762UIMSS52GNAPWFCEEFPWGYLBPKWMBN75S3HCOI2SYCL": null,
+ "NNRBK2PM7FI7MVFBSUUCZVFTDOKXLNVK6I4MMUXU4AKDPTCK": null,
+ "YSGZXEZQRGZ3DSMNCNH6GSWGCRWQSIRD3IOR5E3XEUH5RORJ": null,
+ "P6KRZXZTESTNZHYLZFTDLZMIGIN5H74H2KYUTNRIC3JWCNJ2": null,
+ "QK36OWDC6RHQIASJXU2HZVIBARNIESSCWKICTRQ4B3OFUB6D": null,
+ "JQBWWRLDDMH3HACHKR7EKXFCAAR5E62DX3ALK22Y5AFA4JDZ": null,
+ "WWOLYDEZIQARIEC65MFSVB5RH3236B3E2YSGNEN2QY6A2G54": null,
+ "QT5UVU5QUPEY7VCTTW26JTO2FBUUBCRBYZORWGTYQZ2JZSCH": null,
+ "PJQFD75BGF35X4N33WD423KSDLIAWJNAZUBXQTUGHOW4PTXJ": null,
+ "A5VRG2DRN3CKKTP2DN5YNILXVCZRTKFXWILKWLZ6PNVKJTM5": null,
+ "TY4YPLWS4MDSKPG2HHIRSAWK37LFVB357RGGBRFP2P332HJL": null,
+ "SUC7ZGB6YKDYNAP6NTUZVEVNDL22KBCRZIGAWSOBUAL55LDE": null,
+ "Z5I7WKVA6754S4G7QWWXYTRZ3SGEG4B3KG5MLHP3GJDI3H7M": null,
+ "VLGCWOT665AT2R6EMOAVHNKVM2NKPSV4KI4CMNEUZ2YMI3UP": null,
+ "YJMQW3C2NIIZKTJY34XRL4HQ5A7EUMLMXTJFHHRE3NR3QGZF": null,
+ "TOEB56GVW7OQ7QLL25ZY3ABP4ZQS2ZZMIJRNTILE5CWA2IZB": null,
+ "5RGLCKE6D2MM5YH74OJBDHTOZIM7LN3EIYBLXVF4PGNBZON4": null,
+ "QMQPPFLB6NCEBYCQ5U2YWVYWRKZSFJLCDAAPYSPURDLXAU6G": null,
+ "UTAFBURT6XHHZV3Y5OZJBJJQT4342SSCOLWT35GZIJUPWTTM": null,
+ "XCIXTAB5SB5EMQLZW7GCBUS2N3XU44YELMLSYIFAJHHGP3VS": null,
+ "LWL5AM7Q4JPEDEORTLNDWUF5X4AIUI4QC5S4CWUXKXIWP6FP": null,
+ "M4RONO5HAPE25Q46SSRBVQLEXPCVQLKOKX2NYQWX2SNNGEVB": null,
+ "UVSHBLSXOHEF3AGG5PDTTDFVXNQPRHCNUTXYDEXJVXI7JCPL": null,
+ "C3PB24XOHCI52DU64XQL2V2OKZZYG5B4T6PUU44DZCH4DMSS": null,
+ "VGACAPDUB2J7KLW5PA474JQZWZ6QCDYYB2I32ZFYGXR64M2Y": null,
+ "NNDVFWEC2OE56D5PLJWEEVG25TMXCXISOUOYDOUEMUZRMZK4": null,
+ "57TIZBR3DXRX74YXCSJ2RXLZRXKX3K7H6WPS7DVONX7DOJY3": null,
+ "RFSCST6ITGG53EAZEBXD2VFQTJ53ATEOORQV6SQG5OSDR3FM": null,
+ "YLIXTKYNMODZNBM3L2EL435GD2LRJ5XAJBDZSYCU3OPZ4N4V": null,
+ "FBEPPECF3L4RB6QBQLGL44JDBCQCTQ5MOFYFCUQVNL4DCQYV": null,
+ "PAJST32KEXY6I2Y57OASSUFLF2BLPQQ7NZMVN6EVR7JS5LY3": null,
+ "76MHL43MEQWH6R552TULI3TLBOR22YDMJC5ZYQVWCNI4BWF2": null,
+ "A6KZM4OXBKW2NJ7X545F4LIDSC7LIAFYJ4CJSWW2BWSIRWUY": null,
+ "VND76C7TCKQT6R4X56OD4UYSOBZGC5BQ3LR6RXOX6LA3I5F6": null,
+ "CE2NODHXCRS4ML26HTI77Q57R7ZXKZO433LHHA66I5U3Y5GP": null,
+ "3DGAXWQDLZBPUYZPBGMRZG5DOBPTIHKAXFSCBLMEQHZ2A4W2": null,
+ "NAOTRV3ZNB2PK6RZJZ4UEQVF5M3YISGJNFZQQWPV2S5RL7XM": null,
+ "HLCSR65OBO7BJQPOA65Q6BRDVFPOL7FJII2LOANRJNUM2DDU": null,
+ "YCBI6X4JLTHKGAFR7XYKELWE7JW6VHLMFJIWF2ZC7BPCQFFR": null,
+ "QEF3LB5GFEMHAUDKPPNYGRKUUV6PAWU5XXYCFIHXI7PLGVGW": null,
+ "ABBQK5JKJZLMX4KGFODWSEHOPDTRHGDZCBO3ULBVOGUIAAGI": null,
+ "HZLWUQNBAZJSDZEB6IPXQIUMVWUPYVMVP2N72NJ4MOZFUKGT": null,
+ "7SQCYMGSMYW47TXUWC2J5674L4CRDIAO34D342D7IJ6OE23F": null,
+ "YAQCDYBXIOY3KZGFJCPS5VD7YQBPBFFFYEA4DPWFWJCWCJXA": null,
+ "HCZ7SSO422NW6O3ARCBUGNBCMUVEAHXMVKAJSDBHAQSFXIMV": null,
+ "DPX2FNJNMFQT34DLAOEIN4KMWJYLOEGV7U4VDH635AG6UA5T": null,
+ "QUO6FPOFFXUUKAZXYRN7N2MMT7IOJEG6NLFIH7B5JI5V2Y44": null,
+ "UJ6G5JMOINYVRLVISHWTGQDDDWA6X3QDFICKY4QQIHG3QMF4": null,
+ "ZR3VRUOZMQE4EMVT2WDB45TJ7KB5AGU5UBBPNL2A2D255MOL": null,
+ "2AFEUH4R6YAJZEODKJBMLDM4ANLCKRU2C33HFSVU2LLXZW5Y": null,
+ "3S4PV2VOBFB6GFRPG5SB3EHMZE5M7VAAFRJ3JQYHZEFTEKFX": null,
+ "6EFK4THSCBEG4LDSVE5N5FXSQJTYB5SQ7LKJRBL6IYIREWTN": null,
+ "HHYCWLKLIII7MJ4MYU7CJZ4YPOOUVWOKLXHZV5NT6LU7WWGX": null,
+ "XYRSXFI6XRY3YACAIVIZJAVKFTZPRH5FXD7E4P4LYUGX6I5U": null,
+ "6W72FMK5AP56TNCZ3LE5OTYZ3WYPARBB5AOXDVHGCBOTWZTO": null,
+ "7YNUW4DUCHUDJSSAWSYOYM2QXWTVSJWGDPIG2EAABTU4QLU5": null,
+ "HNVXP5XULHDT666ND2M3X2APGXOBCB7SCQB2D7MFQKKNVOS4": null,
+ "MLCMV4777C55OEVW3SFO4VHH56O7BSIDLZFYYTY3JXNN4DWG": null,
+ "MSNRSOCYC3HQCUXRLCBYFYQOMJFBDOSHJ3HYYYOHEPODETEE": null,
+ "BJB2U3W5ZF7WQVTL6R2F542WSS6FQDSVDMXNYWIC5PHED4HH": null,
+ "E26RFAVZYOV5WZ6WQDVINCGNG6ZYU2XCV4FPEKR45IASGARQ": null,
+ "4BK33GLSBFLRZHOHECAVVYT3LJHSQ5RFBSMKLMGTK4Z5RGZO": null,
+ "5I3526BP3QPLNDBEIPVQL2GOAMRBAYWOMILMQK5IT7RES3EV": null,
+ "IBHOZ4VNFYMLMUNOZIGK743IVASI3DXHCY2RH6SO4EKNGR4A": null,
+ "CCZT4EOMTISCMIVGMB2ZRUGFIR3R6WKU3ISSJ3VZVA6SBLFC": null,
+ "OGJUH7B3WKG3W2UFEBL63KLQGPSPRNIHUUKWTKQMBN5QG42E": null,
+ "Y6JCIA2AYVA3RDOUQFYWI4EMF64H5FIFNAHSKZ6LXCRXCFGW": null,
+ "VX3OCLLJZPGXWTLGERIMK5IS4OXKU65SMC4YS5JZND6VEPO7": null,
+ "UXWF26BRES53JKXYXEG5DWJXCR6USGPBWQBDJEVEBA2PPUAI": null,
+ "IB5SSNMYSFCNB4ODT5OQ2GAGPIVDWOBEI3P3EBWI7AUGC7BR": null,
+ "ASIAQKC3VSFJE7ZW472ZOAXX2T7JTCLZBN5BYEOAE7E67F5Z": null,
+ "BKQ3GY255BDDVZ52IIR5K3NFIEKV6GXBVTX3ROY3IN7XDAHA": null,
+ "JTV5ULWFJJOSFTX32FA6DJWADX5UL3NV4RZZS3Z64IPXDZNK": null,
+ "GSZ7MZXCFKAWFBXKRVYUDULPJEH3WSI2K634LAAA36M2FRF3": null,
+ "HSPTZMNCONTGJGIUWP7ZR277AYWTDIKPAWO4RODOIHQGEUF3": null,
+ "4ABCWRBBUAO5TVOSOZDF3KMCUCKIUCRJSBGH4WGKDHWH3LLN": null,
+ "K3BK4XFUTDJLS7KY4WJBS7RTZ65HY4N5NJ6AMKNKGO3K6DXG": null,
+ "S4VZEKYRNOXUITHJENCBKJN6CC6QV7Y4MIHQ6NLN24OJFMBP": null,
+ "MRM4HMHS2KAISLXU2XYFQCQH7XRVVC3EXSP6JU7FIM2DJHVV": null,
+ "QMNCR2JQYOST5MD3HI2I4MCTSJDFCAGUTEE6XKM2THC4WXI3": null,
+ "ANIF4DT5IA4IY7M5OISD4IW4J2TDVHHFIPEONUU4CV75LOFZ": null,
+ "TQHJIX3NKO5CMVRNOG4WP3YDSGPLTTCRBA3RDBPECWO6EN5U": null,
+ "6KI4L4RRXZ6WL3TRMCZLAA2W7AQRXDCC43O6AGYJ75NUEQO6": null,
+ "VL57QTQMHQOAX5MFQTX7GUWOECHVTLYJHIBRKMWIRF4QMN6M": null,
+ "JFTGBEP2LSZGDDFGV6IV2JAS3J3HB7BDRB6WEYHSC5EIFNA3": null,
+ "WLEZIN5PPCJE4W2LGEPW4N6AWQ4RLE2AOGFBTETY5HNRSZCY": null,
+ "LUJRHNRDNK7YOKST7KRVQGVE2ERU3LUVPZLC5YYLCUAX2EEU": null,
+ "F2OOXAP3FFVMQMJP5IVDLRVV6IP2NUTGT5MGZCJMR2IFNA55": null,
+ "SVL525L4TVBTLMH22DTXVCNECAZVUTMMYDTA3UQGV7U6P3YU": null,
+ "546BD77L33PUPQ7TW3GJJVVJTYKHIIKF7YOO4SSGIIIOIJ2Z": null,
+ "FCZRNOURTDJI2BE7HJ3P4MMY4WYAPFFBCTVFXVTYSK4UB4JK": null,
+ "S2U5XQEC7I4HOUUR6HFXUF2PR2CLNF5UEIPJHTNF2JM5BZUJ": null,
+ "JTQGSOTIPVYKGYJBUQC3Y44RWE372S7MPMFDETMH6OEGUJWA": null,
+ "W3DTWDN6YOEPVUJVUDNPWCLQMXXCLXQPVYU27675LZM4ONDF": null,
+ "LJ7P7AJNNHJE24PNWQDK7J4VGGNZKKR3OPVRFV5A4U6LRFRW": null,
+ "I4QO3SZC4455G5PQIJPUUNI4A2BPJKTH5MBA7LN3HRIW6EFZ": null,
+ "NNR3EXDDDPBTOKTRBPR5SO4OFPXU376ZIEHA6YHEJK57ZRGH": null,
+ "4MBIV5HD4ZMXY5NIKZQIFKFO7S642PC7CWVX7ATXAXWQWNGU": null,
+ "A6S5KTN66UWYBWG5CZXJVCJ2F2EA22BCZDFQMM523DU7VFBG": null,
+ "AOAPML4IEVJZSZUOONTTDYSEN465IHW7MZXHSQ55E47TJ2NW": null,
+ "ZIW5DXTPGQLTTRHPRQB7SADQPCSTXQRMKHZIXA6T6YW2BMRS": null,
+ "OUHF6P7JPB5Z2C2E5MEPNQ5R3NY56KNQFHG3RYGWXBYKRRI7": null,
+ "M3JXOC3CTIEMVHTQW7HB2WQ7L7Q54AWFY6F2UBTSZMDXHTDI": null,
+ "WQQA7JW5NTSAI73WVQMMAJ4IO6OKZR32GTQTMUWE2HLC7DRH": null,
+ "WGDVRLD5YWTXFOFTGBBEFCG455EK3BZCZEE2POAX56O3EOQW": null,
+ "6KAR3LTBYTJ6WRGOUQ2TEPZKWVVBPGCO4OVAN2ADNDNLTOSM": null,
+ "VEWL2DORBATRWF5HJ7LG66NYWMXH37JJU6XWVGJNDVL3OSAM": null,
+ "B4HXCGMG5S3VEOZR5IUYOZAEFL6WPRLXB26SLWZHRY3WL3ZU": null,
+ "REKI5EIO6TNXBWJIENJDQ5CAYEYZC2GXVPAOIWGVXKN2K3OE": null,
+ "RBOY2SVFDRIKJZWTWVEGSJLHGIMAZXIF5HNBZAKPVRTEFR3A": null,
+ "SIOSHIHS52CHIB73RFONJOM2HJBTRLGGDFW6JAWTR6UPJBVB": null,
+ "ZGHKTW43CXC3CBOLSENIMDQUIR22VNXSE6HFBT6ZUA3TPODL": null,
+ "XA576OGJNZK3AXE3FJLSSGN5MGRK4FJJ2XX3UHHFI6NO7P25": null,
+ "22VL7B7ZI53VMYEYHKBI7XYNKRQW634B6RLBRXRJN4CQJA6G": null,
+ "YVHEMU6OLF3FI2MTMZ25QKT5F2OUO3H6CX4WRNEXVH4BO3WZ": null,
+ "3VJOBPUJI5DUFHNRM456UWSAHIZYXICY7ZFYMECCUHDTG444": null,
+ "BXLYOEBYW7R4MWPNTOZ2ZJPDDXBHV7JMH75NCD26VGS2VRH7": null,
+ "GCZOZTTLMHTAKVUQ4TSDOOPHEGK6PH4JQ3ULKZCUIEDW2HLX": null,
+ "TE6B4JOPAY2CEQ46KJV7N6MY7OAI4VA3UBBXGPOELN7KY5T7": null,
+ "62BPAKDHZ7ZRJOMVZ2SX2WAKFQATUQLKDQ7YGACJPL2NP4UR": null,
+ "6U3MTBST24MIPS3HSZJPTBSZJ54T63GMZGZQPGFBS7JGBUVX": null,
+ "SXBYC5BKXYT4DFNVSS4OVRYLNA5JY4TXMVTIFSCRT6Q5C265": null,
+ "TAMMZOCU5GDDOIRG6U53NW3UUEUGI3QWW6YY6GWNE7WIHRNE": null,
+ "O37BSKPNGDUUN24XFSCR2IQHWFYUZJBPWSNC4L43MH5HV272": null,
+ "AZFWV3I3DANXV3HJB66QMCFJ3UTVJGS3R3IP7VROF2D5JF6U": null,
+ "W2BLY5MU4PA7HSENYW4MO6VHHPBXUFCFMSBWTCL5F3BIPBFT": null,
+ "ILFL3JG2XQGZCFBJHZFQRZMLGHZWVRBX3M5Z3HXW2A4GDMNK": null,
+ "O7VDC3EDG5I567RK5BKXMKA2R6XPHQQPDXQTCZP7BHKV5BK6": null,
+ "5ZMIJOTL3NPRKBEPS7542ICCNHHUJ2BNOZ7LSL2ICTCUFGSC": null,
+ "FCTKLPX7PYRSVVBH4KN46HEYLJEYSRTQ3PCUU5RY3BROUZKU": null,
+ "7EAMJ4C7NUA3XMDDOF3YRJA7Q2BFXFCI4J24ZXSVE7REBRFU": null,
+ "NOQ6OL6G7QD4ILQ3FAEMEMROBCK4OK3LX3CRMHMA6GG5YIYK": null,
+ "N3XXFRDRYPWGZ3LDGLIXGLLJYKEHPW4565BUUL67OLMXP554": null,
+ "GFHEEY3HHESZDI2YHTDDCBKGE3ZPWPXW2WE5AKNL2Y2TJCNJ": null,
+ "JTUQIEPPBM2QC6XBY3KP2NSDM6WUCJMORCBXNU6ZPXPOHEIW": null,
+ "V5VTVJ36JZDDO5FIOEZNAKYWPRQSUSTEZAKARDOHQEIFLACE": null,
+ "KUTOUNOS2QL4O6HF266ANCBNYUSIT66TANXCGYALCPZXULQH": null,
+ "CJILUW3VUBZCSO5DXTSE4HSVW5UJAJHHCSHGHADKCQE5OTBU": null,
+ "HD72YVUCR4IY5MG3E73UM35ARFCUIHEPIMUSQXOKLVTT2V67": null,
+ "ELVTZXW3ZAKR76K6IV6ZHX7WTMKPKIFRPHIU3LK67WQR6IQG": null,
+ "NIZTNRLCIS4JDLMOTEAKPA6B2JOE76ZBQDEUUGXENEJBYJFV": null,
+ "FE743ELPJYDYWTJ374PZVE4TNGZPDZWSNUO5PATNYUYBDTBJ": null,
+ "FIT3JHSZMFJ7N2E7BL6PHEUUHSBHU55YBIH763TGSZQTIAZY": null,
+ "AP7SXAQ6HW373QPCHKKA4R7NFFUCD7CFB7EERZBNXRGM2Z7R": null,
+ "BAW6TALQRWXK2OWS2O2UV72BKZGBZCUPR6AXKFZ7WHZXZXWX": null,
+ "SM3FE7H4NI76AS5YCH6O34LTROZKJ7FEP4IKL33JUBI7FWZJ": null,
+ "BNO2EJXVMAPFDVF34NBTPSIYKI3UPFI5G2K6KGVU35TIHOQL": null,
+ "INHCLRC6WPTE2U7OQRSSRGCN4B5K4BUVSGFHEKG5DWJWICOF": null,
+ "OEHWM7QZ3H67QC4ZQY2USKQA62NLMESA543KWPBUKV7N65TQ": null,
+ "BN3U5KDJP3QGOSBX3TH5R2DR6PZA5Z7BEGVG6MYRW5GWUCGT": null,
+ "ID7S7JEGBCI7ES3ZN7PIW5NEP67WTL5H5IB6WVRYS47EEEJ2": null,
+ "BG4MHZNCCLZQN563CZ2D72CPT5TASZZ6N6L4JOW2XPR7GIDQ": null,
+ "IAQKAEEUCCT3ZZY5LCO4AZW6F6ZNGUAF56UCD43OPOKSMBHR": null,
+ "LFCSYYMAFZ5IAB5O4QIEN5GERYIGTH4JH266LORQ36SB2A26": null,
+ "J7W62H5B42N3YUEFS5F2MECESYBUVHXSIGRMZL6ZNQMCYQMQ": null,
+ "J24FG5J3MUQOCDAVVCHM6BJWZW4Y7VCSC73DW32TMKIUOXPB": null,
+ "DGJE6OPBSV3JW45P5WC3EGUMIETVT7MIZX4EA5SCY2F3JKFL": null,
+ "KWTJYJJT2LMBHE6WH4LNJEHNMNJVOEQ7SLLXGJKWPGOFDYHQ": null,
+ "7XZDDO3CCV34UECRKEM344EDKKUFD6YDUJ7EW4OAETABTYWV": null,
+ "BPS2OSY2SOAFFPRY24IEXGZVBEUNVIWZYTVVZRUWT7XM727T": null,
+ "6GRVGHI3FMCQ5MQ4JR7ORANBXK6GMSI4XRQVE35LPH44XROO": null,
+ "MZHRR2BS6HII6JD3H32DPSYTTHCVXE4WSC7NUURU43Z5SD56": null,
+ "QJBSWHFQKABG4CALELT62JWLMW2JVZP35RDYHWHQPZYTIX5M": null,
+ "K2Y3YRBFB7F5PJJUFJDH5Z5NL2MYOQWGT5T5VI5SP7TVM5NW": null,
+ "QLONNH4NMZX5WLEJPQEWJECL5JTLTWDSK234NU5H55GA6PFG": null,
+ "NSSRUR3GI6B7NBK77ZQIIHOA4TEEA5UXVVMRWVLMRIP6SN3T": null,
+ "WB2TXRE7EPSBGACXUA4YE23M4WLMG3PVRMD2OOCIHNGQVDRY": null,
+ "3MDCQC5BPGFGGFDO4C4IY53NPTWZMRK5MWLJG2KX7OWVQNFO": null
+}
diff --git a/bin/unittestschema/address.json b/bin/unittestschema/address.json
new file mode 100644
index 000000000..c3cf64261
--- /dev/null
+++ b/bin/unittestschema/address.json
@@ -0,0 +1,139 @@
+{
+ "type": "object",
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/decimal_type"
+ },
+ "address": {
+ "$ref": "#/definitions/address_type"
+ },
+ "phones": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 2,
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/phone_type"
+ }
+ },
+ "names": {
+ "type": "array",
+ "items": [
+ { "type": "string" },
+ { "type": "string" }
+ ],
+ "additionalItems": false
+ },
+ "extra": {
+ "type": "object",
+ "patternProperties": {
+ "^S_": { "type": "string" }
+ }
+ },
+ "gender": {
+ "type": "string",
+ "enum": ["M", "F"]
+ }
+ },
+ "additionalProperties": false,
+ "dependencies": {
+ "address": [ "version" ],
+ "names": {
+ "properties": {
+ "version": { "$ref": "#/definitions/decimal_type" }
+ },
+ "required": ["version"]
+ }
+ },
+ "definitions": {
+ "address_type": {
+ "type": "object",
+ "properties": {
+ "number": {
+ "$ref": "#/definitions/positiveInt_type"
+ },
+ "street1": {
+ "type": "string"
+ },
+ "street2": {
+ "type": ["string", "null"]
+ },
+ "street3": {
+ "not": { "type": ["boolean", "number", ",integer", "object", "null"] }
+ },
+ "city": {
+ "type": "string",
+ "maxLength": 10,
+ "minLength": 4
+ },
+ "area": {
+ "oneOf": [
+ { "$ref": "#/definitions/county_type" },
+ { "$ref": "#/definitions/province_type" }
+ ]
+ },
+ "country": {
+ "allOf": [
+ { "$ref": "#/definitions/country_type" }
+ ]
+ },
+ "postcode": {
+ "anyOf": [
+ { "type": "string", "pattern": "^[A-Z]{2}[0-9]{1,2} [0-9][A-Z]{2}$" },
+ { "type": "string", "pattern": "^[0-9]{5}$" }
+ ]
+ }
+ },
+ "minProperties": 7,
+ "required": [
+ "number",
+ "street1",
+ "city"
+ ]
+ },
+ "country_type": {
+ "type": "string",
+ "enum": ["UK", "Canada"]
+ },
+ "county_type": {
+ "type": "string",
+ "enum": ["Sussex", "Surrey", "Kent"]
+ },
+ "province_type": {
+ "type": "string",
+ "enum": ["Quebec", "BC", "Alberta"]
+ },
+ "date_type": {
+ "pattern": "^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)?$",
+ "type": "string"
+ },
+ "positiveInt_type": {
+ "minimum": 0,
+ "exclusiveMinimum": true,
+ "maximum": 100,
+ "exclusiveMaximum": true,
+ "type": "integer"
+ },
+ "decimal_type": {
+ "multipleOf": 1.0,
+ "type": "number"
+ },
+ "time_type": {
+ "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]+)?$",
+ "type": "string"
+ },
+ "unsignedInt_type": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 99999
+ },
+ "phone_type": {
+ "pattern": "^[0-9]*-[0-9]*",
+ "type": "string"
+ },
+ "url_type": {
+ "pattern": "^\\S*$",
+ "type": "string"
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/unittestschema/allOf_address.json b/bin/unittestschema/allOf_address.json
new file mode 100644
index 000000000..fd501f66d
--- /dev/null
+++ b/bin/unittestschema/allOf_address.json
@@ -0,0 +1,7 @@
+{
+ "allOf": [
+ {
+ "$ref": "http://localhost:1234/address.json#"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/bin/unittestschema/anyOf_address.json b/bin/unittestschema/anyOf_address.json
new file mode 100644
index 000000000..5c90308f4
--- /dev/null
+++ b/bin/unittestschema/anyOf_address.json
@@ -0,0 +1,7 @@
+{
+ "anyOf": [
+ {
+ "$ref": "http://localhost:1234/address.json#"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/bin/unittestschema/idandref.json b/bin/unittestschema/idandref.json
new file mode 100644
index 000000000..ad485d29f
--- /dev/null
+++ b/bin/unittestschema/idandref.json
@@ -0,0 +1,69 @@
+{
+ "id": "http://example.com/root.json",
+ "definitions": {
+ "A": {
+ "id": "#foo",
+ "type": "integer"
+ },
+ "B": {
+ "id": "other.json",
+ "definitions": {
+ "X": {
+ "id": "#bar",
+ "type": "boolean"
+ },
+ "Y": {
+ "$ref": "#/definitions/X"
+ },
+ "W": {
+ "$ref": "#/definitions/Y"
+ },
+ "Z": {
+ "$ref": "#bar"
+ },
+ "N": {
+ "properties": {
+ "NX": {
+ "$ref": "#/definitions/X"
+ }
+ }
+ }
+ }
+ }
+ },
+ "properties": {
+ "PA1": {
+ "$ref": "http://example.com/root.json#/definitions/A"
+ },
+ "PA2": {
+ "$ref": "#/definitions/A"
+ },
+ "PA3": {
+ "$ref": "#foo"
+ },
+ "PX1": {
+ "$ref": "#/definitions/B/definitions/X"
+ },
+ "PX2Y": {
+ "$ref": "#/definitions/B/definitions/Y"
+ },
+ "PX3Z": {
+ "$ref": "#/definitions/B/definitions/Z"
+ },
+ "PX4": {
+ "$ref": "http://example.com/other.json#/definitions/X"
+ },
+ "PX5": {
+ "$ref": "other.json#/definitions/X"
+ },
+ "PX6": {
+ "$ref": "other.json#bar"
+ },
+ "PX7W": {
+ "$ref": "#/definitions/B/definitions/W"
+ },
+ "PX8N": {
+ "$ref": "#/definitions/B/definitions/N"
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/unittestschema/oneOf_address.json b/bin/unittestschema/oneOf_address.json
new file mode 100644
index 000000000..a5baadd2a
--- /dev/null
+++ b/bin/unittestschema/oneOf_address.json
@@ -0,0 +1,7 @@
+{
+ "oneOf": [
+ {
+ "$ref": "http://localhost:1234/address.json#"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/contrib/natvis/rapidjson.natvis b/contrib/natvis/rapidjson.natvis
index a804b7bf6..e7bd44b6e 100644
--- a/contrib/natvis/rapidjson.natvis
+++ b/contrib/natvis/rapidjson.natvis
@@ -5,8 +5,8 @@
null
true
false
- {data_.ss.str}
- {(const char*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF)}
+ {(const Ch*)data_.ss.str,na}
+ {(const Ch*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF),na}
{data_.n.i.i}
{data_.n.u.u}
{data_.n.i64}
diff --git a/doc/dom.zh-cn.md b/doc/dom.zh-cn.md
index 8fcd53875..7a555dc1c 100644
--- a/doc/dom.zh-cn.md
+++ b/doc/dom.zh-cn.md
@@ -1,6 +1,6 @@
# DOM
-文档对象模型(Document Object Model, DOM)是一种罝于内存中的 JSON 表示方式,以供查询及操作。我们己于 [教程](doc/tutorial.zh-cn.md) 中介绍了 DOM 的基本用法,本节将讲述一些细节及高级用法。
+文档对象模型(Document Object Model, DOM)是一种罝于内存中的 JSON 表示方式,以供查询及操作。我们已于 [教程](doc/tutorial.zh-cn.md) 中介绍了 DOM 的基本用法,本节将讲述一些细节及高级用法。
[TOC]
diff --git a/doc/faq.md b/doc/faq.md
index 9abfdf1cf..55fa2af88 100644
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -64,11 +64,11 @@
JSON are commonly used in web applications for transferring structured data. It is also used as a file format for data persistence.
-2. Does RapidJSON conform to the JSON standard?
+3. Does RapidJSON conform to the JSON standard?
Yes. RapidJSON is fully compliance with [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm). It can handle corner cases, such as supporting null character and surrogate pairs in JSON strings.
-3. Does RapidJSON support relaxed syntax?
+4. Does RapidJSON support relaxed syntax?
Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/Tencent/rapidjson/issues/36).
diff --git a/doc/faq.zh-cn.md b/doc/faq.zh-cn.md
index bdacfcee7..cf1124d82 100644
--- a/doc/faq.zh-cn.md
+++ b/doc/faq.zh-cn.md
@@ -18,7 +18,7 @@
4. RapidJSON 是免费的么?
- 是的,它在 MIT 特許條款下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。
+ 是的,它在 MIT 协议下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。
5. RapidJSON 很小么?它有何依赖?
@@ -64,13 +64,13 @@
JSON 常用于网页应用程序,以传送结构化数据。它也可作为文件格式用于数据持久化。
-2. RapidJSON 是否符合 JSON 标准?
+3. RapidJSON 是否符合 JSON 标准?
是。RapidJSON 完全符合 [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) 及 [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)。它能处理一些特殊情况,例如支持 JSON 字符串中含有空字符及代理对(surrogate pair)。
-3. RapidJSON 是否支持宽松的语法?
+4. RapidJSON 是否支持宽松的语法?
- 现时不支持。RapidJSON 只支持严格的标准格式。宽松语法现时在这 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
+ 目前不支持。RapidJSON 只支持严格的标准格式。宽松语法可以在这个 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
## DOM 与 SAX
@@ -271,7 +271,7 @@
有些应用程序需要处理非常大的 JSON 文件。而有些后台应用程序需要处理大量的 JSON。达到高性能同时改善延时及吞吐量。更广义来说,这也可以节省能源。
-## 八挂
+## 八卦
1. 谁是 RapidJSON 的开发者?
@@ -279,11 +279,11 @@
2. 为何你要开发 RapidJSON?
- 在 2011 年开始这项目是,它仅一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个仅有头文件并且快速的程序库。
+ 在 2011 年开始这项目时,它只是一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个快速的仅有头文件的程序库。
3. 为什么开发中段有一段长期空档?
- 主要是个人因素,例如加入新家庭成员。另外,Milo Yip 也花了许多业馀时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
+ 主要是个人因素,例如加入新家庭成员。另外,Milo Yip 也花了许多业余时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
4. 为什么这个项目从 Google Code 搬到 GitHub?
diff --git a/doc/stream.md b/doc/stream.md
index 04c865c7a..5d0b0f35e 100644
--- a/doc/stream.md
+++ b/doc/stream.md
@@ -1,6 +1,6 @@
# Stream
-In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we first show how to use streams provided. And then see how to create a custom stream.
+In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we'll first show you how to use provided streams. And then see how to create a custom stream.
[TOC]
@@ -51,7 +51,7 @@ d.Accept(writer);
const char* output = buffer.GetString();
~~~~~~~~~~
-When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and a initial capacity.
+When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and an initial capacity.
~~~~~~~~~~cpp
StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024
@@ -89,7 +89,7 @@ d.ParseStream(is);
fclose(fp);
~~~~~~~~~~
-Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. It will be discussed very soon.
+Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. We will discuss more about this later in this tutorial.
Apart from reading file, user can also use `FileReadStream` to read `stdin`.
@@ -119,11 +119,11 @@ d.Accept(writer);
fclose(fp);
~~~~~~~~~~
-It can also directs the output to `stdout`.
+It can also redirect the output to `stdout`.
# iostream Wrapper {#iostreamWrapper}
-Due to users' requests, RapidJSON provided official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
+Due to users' requests, RapidJSON also provides official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
## IStreamWrapper {#IStreamWrapper}
@@ -181,7 +181,7 @@ As mentioned above, UTF-8 byte streams can be read directly. However, UTF-16 and
Besides, it also need to handle [byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark). When reading from a byte stream, it is needed to detect or just consume the BOM if exists. When writing to a byte stream, it can optionally write BOM.
-If the encoding of stream is known in compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
+If the encoding of stream is known during compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
Note that, these encoded streams can be applied to streams other than file. For example, you may have a file in memory, or a custom byte stream, be wrapped in encoded streams.
@@ -231,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // Write BOM
-Writer, UTF8<>> writer(eos);
+Writer, UTF32LE<>> writer(eos);
d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory
fclose(fp);
diff --git a/doc/stream.zh-cn.md b/doc/stream.zh-cn.md
index 7f2f356f7..6e379bbd6 100644
--- a/doc/stream.zh-cn.md
+++ b/doc/stream.zh-cn.md
@@ -231,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // 写入 BOM
-Writer, UTF8<>> writer(eos);
+Writer, UTF32LE<>> writer(eos);
d.Accept(writer); // 这里从内存的 UTF-8 生成 UTF32-LE 文件
fclose(fp);
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 4bde2faf4..a86aafdfc 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -12,7 +12,7 @@ Each JSON value is stored in a type called `Value`. A `Document`, representing t
# Query Value {#QueryValue}
-In this section, we will use excerpt of `example/tutorial/tutorial.cpp`.
+In this section, we will use excerpt from `example/tutorial/tutorial.cpp`.
Assume we have the following JSON stored in a C string (`const char* json`):
~~~~~~~~~~js
@@ -85,7 +85,7 @@ assert(document["i"].IsNumber());
// In this case, IsUint()/IsInt64()/IsUint64() also return true.
assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt());
-// Alternative (int)document["i"]
+// Alternatively (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
@@ -113,7 +113,7 @@ a[2] = 3
a[3] = 4
~~~~~~~~~~
-Note that, RapidJSON does not automatically convert values between JSON types. If a value is a string, it is invalid to call `GetInt()`, for example. In debug mode it will fail an assertion. In release mode, the behavior is undefined.
+Note that, RapidJSON does not automatically convert values between JSON types. For example, if a value is a string, it is invalid to call `GetInt()`. In debug mode it will fail on assertion. In release mode, the behavior is undefined.
In the following sections we discuss details about querying individual types.
@@ -168,9 +168,9 @@ Type of member pi is Number
Type of member a is Array
~~~~~~~~~~
-Note that, when `operator[](const char*)` cannot find the member, it will fail an assertion.
+Note that, when `operator[](const char*)` cannot find the member, it will fail on assertion.
-If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of member and obtain its value at once:
+If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of a member and obtain its value at once:
~~~~~~~~~~cpp
Value::ConstMemberIterator itr = document.FindMember("hello");
@@ -221,18 +221,18 @@ When obtaining the numeric values, `GetDouble()` will convert internal integer r
## Query String {#QueryString}
-In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why.
+In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why:
-According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats ``\0'` as the terminator symbol.
+According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats `\0` as the terminator symbol.
-To conform RFC 4627, RapidJSON supports string containing `U+0000`. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length.
+To conform with RFC 4627, RapidJSON supports string containing `U+0000` character. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length.
-For example, after parsing a the following JSON to `Document d`:
+For example, after parsing the following JSON to `Document d`:
~~~~~~~~~~js
{ "s" : "a\u0000b" }
~~~~~~~~~~
-The correct length of the value `"a\u0000b"` is 3. But `strlen()` returns 1.
+The correct length of the string `"a\u0000b"` is 3, as returned by `GetStringLength()`. But `strlen()` returns 1.
`GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer.
@@ -246,7 +246,7 @@ which accepts the length of string as parameter. This constructor supports stori
## Comparing values
-You can use `==` and `!=` to compare values. Two values are equal if and only if they are have same type and contents. You can also compare values with primitive types. Here is an example.
+You can use `==` and `!=` to compare values. Two values are equal if and only if they have same type and contents. You can also compare values with primitive types. Here is an example:
~~~~~~~~~~cpp
if (document["hello"] == document["n"]) /*...*/; // Compare values
@@ -264,7 +264,7 @@ Note that, currently if an object contains duplicated named member, comparing eq
There are several ways to create values. After a DOM tree is created and/or modified, it can be saved as JSON again using `Writer`.
## Change Value Type {#ChangeValueType}
-When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
+When creating a `Value` or `Document` by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
~~~~~~~~~~cpp
Document d; // Null
@@ -285,7 +285,7 @@ Value u(123u); // calls Value(unsigned)
Value d(1.5); // calls Value(double)
~~~~~~~~~~
-To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one shot:
+To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one call:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -299,7 +299,7 @@ A very special decision during design of RapidJSON is that, assignment of value
~~~~~~~~~~cpp
Value a(123);
Value b(456);
-b = a; // a becomes a Null value, b becomes number 123.
+a = b; // b becomes a Null value, a becomes number 456.
~~~~~~~~~~

@@ -367,7 +367,7 @@ RapidJSON provides two strategies for storing string.
Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing a string literal, and for in-situ parsing which will be mentioned in the DOM section.
-To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing a allocator (or Document) pointer per Value.
+To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing an allocator (or Document) pointer per Value.
Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator:
diff --git a/example/schemavalidator/schemavalidator.cpp b/example/schemavalidator/schemavalidator.cpp
index 06bbe4dd9..8c7e26c79 100644
--- a/example/schemavalidator/schemavalidator.cpp
+++ b/example/schemavalidator/schemavalidator.cpp
@@ -2,14 +2,131 @@
// The example validates JSON text from stdin with a JSON schema specified in the argument.
+#define RAPIDJSON_HAS_STDSTRING 1
+
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
+#include
+#include
+#include
using namespace rapidjson;
+typedef GenericValue, CrtAllocator > ValueType;
+
+// Forward ref
+static void CreateErrorMessages(const ValueType& errors, size_t depth, const char* context);
+
+// Convert GenericValue to std::string
+static std::string GetString(const ValueType& val) {
+ std::ostringstream s;
+ if (val.IsString())
+ s << val.GetString();
+ else if (val.IsDouble())
+ s << val.GetDouble();
+ else if (val.IsUint())
+ s << val.GetUint();
+ else if (val.IsInt())
+ s << val.GetInt();
+ else if (val.IsUint64())
+ s << val.GetUint64();
+ else if (val.IsInt64())
+ s << val.GetInt64();
+ else if (val.IsBool() && val.GetBool())
+ s << "true";
+ else if (val.IsBool())
+ s << "false";
+ else if (val.IsFloat())
+ s << val.GetFloat();
+ return s.str();}
+
+// Create the error message for a named error
+// The error object can either be empty or contain at least member properties:
+// {"errorCode": , "instanceRef": "", "schemaRef": "" }
+// Additional properties may be present for use as inserts.
+// An "errors" property may be present if there are child errors.
+static void HandleError(const char* errorName, const ValueType& error, size_t depth, const char* context) {
+ if (!error.ObjectEmpty()) {
+ // Get error code and look up error message text (English)
+ int code = error["errorCode"].GetInt();
+ std::string message(GetValidateError_En(static_cast(code)));
+ // For each member property in the error, see if its name exists as an insert in the error message and if so replace with the stringified property value
+ // So for example - "Number '%actual' is not a multiple of the 'multipleOf' value '%expected'." - we would expect "actual" and "expected" members.
+ for (ValueType::ConstMemberIterator insertsItr = error.MemberBegin();
+ insertsItr != error.MemberEnd(); ++insertsItr) {
+ std::string insertName("%");
+ insertName += insertsItr->name.GetString(); // eg "%actual"
+ size_t insertPos = message.find(insertName);
+ if (insertPos != std::string::npos) {
+ std::string insertString("");
+ const ValueType &insert = insertsItr->value;
+ if (insert.IsArray()) {
+ // Member is an array so create comma-separated list of items for the insert string
+ for (ValueType::ConstValueIterator itemsItr = insert.Begin(); itemsItr != insert.End(); ++itemsItr) {
+ if (itemsItr != insert.Begin()) insertString += ",";
+ insertString += GetString(*itemsItr);
+ }
+ } else {
+ insertString += GetString(insert);
+ }
+ message.replace(insertPos, insertName.length(), insertString);
+ }
+ }
+ // Output error message, references, context
+ std::string indent(depth * 2, ' ');
+ std::cout << indent << "Error Name: " << errorName << std::endl;
+ std::cout << indent << "Message: " << message.c_str() << std::endl;
+ std::cout << indent << "Instance: " << error["instanceRef"].GetString() << std::endl;
+ std::cout << indent << "Schema: " << error["schemaRef"].GetString() << std::endl;
+ if (depth > 0) std::cout << indent << "Context: " << context << std::endl;
+ std::cout << std::endl;
+
+ // If child errors exist, apply the process recursively to each error structure.
+ // This occurs for "oneOf", "allOf", "anyOf" and "dependencies" errors, so pass the error name as context.
+ if (error.HasMember("errors")) {
+ depth++;
+ const ValueType &childErrors = error["errors"];
+ if (childErrors.IsArray()) {
+ // Array - each item is an error structure - example
+ // "anyOf": {"errorCode": ..., "errors":[{"pattern": {"errorCode\": ...\"}}, {"pattern": {"errorCode\": ...}}]
+ for (ValueType::ConstValueIterator errorsItr = childErrors.Begin();
+ errorsItr != childErrors.End(); ++errorsItr) {
+ CreateErrorMessages(*errorsItr, depth, errorName);
+ }
+ } else if (childErrors.IsObject()) {
+ // Object - each member is an error structure - example
+ // "dependencies": {"errorCode": ..., "errors": {"address": {"required": {"errorCode": ...}}, "name": {"required": {"errorCode": ...}}}
+ for (ValueType::ConstMemberIterator propsItr = childErrors.MemberBegin();
+ propsItr != childErrors.MemberEnd(); ++propsItr) {
+ CreateErrorMessages(propsItr->value, depth, errorName);
+ }
+ }
+ }
+ }
+}
+
+// Create error message for all errors in an error structure
+// Context is used to indicate whether the error structure has a parent 'dependencies', 'allOf', 'anyOf' or 'oneOf' error
+static void CreateErrorMessages(const ValueType& errors, size_t depth = 0, const char* context = 0) {
+ // Each member property contains one or more errors of a given type
+ for (ValueType::ConstMemberIterator errorTypeItr = errors.MemberBegin(); errorTypeItr != errors.MemberEnd(); ++errorTypeItr) {
+ const char* errorName = errorTypeItr->name.GetString();
+ const ValueType& errorContent = errorTypeItr->value;
+ if (errorContent.IsArray()) {
+ // Member is an array where each item is an error - eg "type": [{"errorCode": ...}, {"errorCode": ...}]
+ for (ValueType::ConstValueIterator contentItr = errorContent.Begin(); contentItr != errorContent.End(); ++contentItr) {
+ HandleError(errorName, *contentItr, depth, context);
+ }
+ } else if (errorContent.IsObject()) {
+ // Member is an object which is a single error - eg "type": {"errorCode": ... }
+ HandleError(errorName, errorContent, depth, context);
+ }
+ }
+}
+
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n");
@@ -65,6 +182,8 @@ int main(int argc, char *argv[]) {
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid schema: %s\n", sb.GetString());
fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
+ fprintf(stderr, "Invalid code: %d\n", validator.GetInvalidSchemaCode());
+ fprintf(stderr, "Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode()));
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
@@ -73,6 +192,7 @@ int main(int argc, char *argv[]) {
PrettyWriter w(sb);
validator.GetError().Accept(w);
fprintf(stderr, "Error report:\n%s\n", sb.GetString());
+ CreateErrorMessages(validator.GetError());
return EXIT_FAILURE;
}
}
diff --git a/example/traverseaspointer.cpp b/example/traverseaspointer.cpp
new file mode 100644
index 000000000..7e0c89923
--- /dev/null
+++ b/example/traverseaspointer.cpp
@@ -0,0 +1,39 @@
+#include "rapidjson/document.h"
+#include "rapidjson/filereadstream.h"
+#include "rapidjson/pointer.h"
+#include "rapidjson/stringbuffer.h"
+#include
+
+using namespace rapidjson;
+
+void traverse(const Value& v, const Pointer& p) {
+ StringBuffer sb;
+ p.Stringify(sb);
+ std::cout << sb.GetString() << std::endl;
+
+ switch (v.GetType()) {
+ case kArrayType:
+ for (SizeType i = 0; i != v.Size(); ++i)
+ traverse(v[i], p.Append(i));
+ break;
+ case kObjectType:
+ for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m)
+ traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength()));
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int, char*[]) {
+ char readBuffer[65536];
+ FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
+
+ Document d;
+ d.ParseStream(is);
+
+ Pointer root;
+ traverse(d, root);
+
+ return 0;
+}
diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h
index cc67c8971..12bc5bafc 100644
--- a/include/rapidjson/allocators.h
+++ b/include/rapidjson/allocators.h
@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@@ -16,6 +16,13 @@
#define RAPIDJSON_ALLOCATORS_H_
#include "rapidjson.h"
+#include "internal/meta.h"
+
+#include
+
+#if RAPIDJSON_HAS_CXX11
+#include
+#endif
RAPIDJSON_NAMESPACE_BEGIN
@@ -77,19 +84,26 @@ class CrtAllocator {
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
- return std::malloc(size);
+ return RAPIDJSON_MALLOC(size);
else
return NULL; // standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize;
if (newSize == 0) {
- std::free(originalPtr);
+ RAPIDJSON_FREE(originalPtr);
return NULL;
}
- return std::realloc(originalPtr, newSize);
+ return RAPIDJSON_REALLOC(originalPtr, newSize);
+ }
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
+
+ bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
+ return true;
+ }
+ bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
+ return false;
}
- static void Free(void *ptr) { std::free(ptr); }
};
///////////////////////////////////////////////////////////////////////////////
@@ -113,16 +127,64 @@ class CrtAllocator {
*/
template
class MemoryPoolAllocator {
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ struct SharedData {
+ ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
+ size_t refcount;
+ bool ownBuffer;
+ };
+
+ static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
+ static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
+
+ static inline ChunkHeader *GetChunkHead(SharedData *shared)
+ {
+ return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA);
+ }
+ static inline uint8_t *GetChunkBuffer(SharedData *shared)
+ {
+ return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
+ }
+
+ static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
+
public:
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.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
+ explicit
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ chunk_capacity_(chunkSize),
+ baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
+ shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
{
+ RAPIDJSON_ASSERT(baseAllocator_ != 0);
+ RAPIDJSON_ASSERT(shared_ != 0);
+ if (baseAllocator) {
+ shared_->ownBaseAllocator = 0;
+ }
+ else {
+ shared_->ownBaseAllocator = baseAllocator_;
+ }
+ shared_->chunkHead = GetChunkHead(shared_);
+ shared_->chunkHead->capacity = 0;
+ shared_->chunkHead->size = 0;
+ shared_->chunkHead->next = 0;
+ shared_->ownBuffer = true;
+ shared_->refcount = 1;
}
//! Constructor with user-supplied buffer.
@@ -136,41 +198,101 @@ class MemoryPoolAllocator {
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ chunk_capacity_(chunkSize),
+ baseAllocator_(baseAllocator),
+ shared_(static_cast(AlignBuffer(buffer, size)))
+ {
+ RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
+ shared_->chunkHead = GetChunkHead(shared_);
+ shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
+ shared_->chunkHead->size = 0;
+ shared_->chunkHead->next = 0;
+ shared_->ownBaseAllocator = 0;
+ shared_->ownBuffer = false;
+ shared_->refcount = 1;
+ }
+
+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ chunk_capacity_(rhs.chunk_capacity_),
+ baseAllocator_(rhs.baseAllocator_),
+ shared_(rhs.shared_)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ ++shared_->refcount;
+ }
+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
{
- RAPIDJSON_ASSERT(buffer != 0);
- RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
- chunkHead_ = reinterpret_cast(buffer);
- chunkHead_->capacity = size - sizeof(ChunkHeader);
- chunkHead_->size = 0;
- chunkHead_->next = 0;
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ ++rhs.shared_->refcount;
+ this->~MemoryPoolAllocator();
+ baseAllocator_ = rhs.baseAllocator_;
+ chunk_capacity_ = rhs.chunk_capacity_;
+ shared_ = rhs.shared_;
+ return *this;
}
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
+ chunk_capacity_(rhs.chunk_capacity_),
+ baseAllocator_(rhs.baseAllocator_),
+ shared_(rhs.shared_)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ rhs.shared_ = 0;
+ }
+ MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ this->~MemoryPoolAllocator();
+ baseAllocator_ = rhs.baseAllocator_;
+ chunk_capacity_ = rhs.chunk_capacity_;
+ shared_ = rhs.shared_;
+ rhs.shared_ = 0;
+ return *this;
+ }
+#endif
+
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
- ~MemoryPoolAllocator() {
+ ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
+ if (!shared_) {
+ // do nothing if moved
+ return;
+ }
+ if (shared_->refcount > 1) {
+ --shared_->refcount;
+ return;
+ }
Clear();
- RAPIDJSON_DELETE(ownBaseAllocator_);
+ BaseAllocator *a = shared_->ownBaseAllocator;
+ if (shared_->ownBuffer) {
+ baseAllocator_->Free(shared_);
+ }
+ RAPIDJSON_DELETE(a);
}
- //! Deallocates all memory chunks, excluding the user-supplied buffer.
- void Clear() {
- while (chunkHead_ && chunkHead_ != userBuffer_) {
- ChunkHeader* next = chunkHead_->next;
- baseAllocator_->Free(chunkHead_);
- chunkHead_ = next;
+ //! Deallocates all memory chunks, excluding the first/user one.
+ void Clear() RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ for (;;) {
+ ChunkHeader* c = shared_->chunkHead;
+ if (!c->next) {
+ break;
+ }
+ shared_->chunkHead = c->next;
+ baseAllocator_->Free(c);
}
- if (chunkHead_ && chunkHead_ == userBuffer_)
- chunkHead_->size = 0; // Clear user buffer
+ shared_->chunkHead->size = 0;
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
- size_t Capacity() const {
+ size_t Capacity() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t capacity = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
capacity += c->capacity;
return capacity;
}
@@ -178,25 +300,35 @@ class MemoryPoolAllocator {
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
- size_t Size() const {
+ size_t Size() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t size = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
size += c->size;
return size;
}
+ //! Whether the allocator is shared.
+ /*! \return true or false.
+ */
+ bool Shared() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ return shared_->refcount > 1;
+ }
+
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
- if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;
- void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
- chunkHead_->size += size;
+ void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
+ shared_->chunkHead->size += size;
return buffer;
}
@@ -205,6 +337,7 @@ class MemoryPoolAllocator {
if (originalPtr == 0)
return Malloc(newSize);
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (newSize == 0)
return NULL;
@@ -216,10 +349,10 @@ class MemoryPoolAllocator {
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
- if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
+ if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
size_t increment = static_cast(newSize - originalSize);
- if (chunkHead_->size + increment <= chunkHead_->capacity) {
- chunkHead_->size += increment;
+ if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
+ shared_->chunkHead->size += increment;
return originalPtr;
}
}
@@ -235,50 +368,325 @@ class MemoryPoolAllocator {
}
//! Frees a memory block (concept Allocator)
- static void Free(void *ptr) { (void)ptr; } // Do nothing
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
-private:
- //! Copy constructor is not permitted.
- MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
- //! Copy assignment operator is not permitted.
- MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+ //! Compare (equality) with another MemoryPoolAllocator
+ bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ return shared_ == rhs.shared_;
+ }
+ //! Compare (inequality) with another MemoryPoolAllocator
+ bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
+ return !operator==(rhs);
+ }
+private:
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
- ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
- if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
+ shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
+ if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
- chunk->next = chunkHead_;
- chunkHead_ = chunk;
+ chunk->next = shared_->chunkHead;
+ shared_->chunkHead = chunk;
return true;
}
else
return false;
}
- static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
-
- //! Chunk header for perpending to each chunk.
- /*! Chunks are stored as a singly linked list.
- */
- struct ChunkHeader {
- size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
- size_t size; //!< Current size of allocated memory in bytes.
- ChunkHeader *next; //!< Next chunk in the linked list.
- };
+ static inline void* AlignBuffer(void* buf, size_t &size)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
+ const uintptr_t mask = sizeof(void*) - 1;
+ const uintptr_t ubuf = reinterpret_cast(buf);
+ if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
+ const uintptr_t abuf = (ubuf + mask) & ~mask;
+ RAPIDJSON_ASSERT(size >= abuf - ubuf);
+ buf = reinterpret_cast(abuf);
+ size -= abuf - ubuf;
+ }
+ return buf;
+ }
- ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
- void *userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
- BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+ SharedData *shared_; //!< The shared data of the allocator
};
+namespace internal {
+ template
+ struct IsRefCounted :
+ public FalseType
+ { };
+ template
+ struct IsRefCounted::Type> :
+ public TrueType
+ { };
+}
+
+template
+inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
+{
+ RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T));
+ return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
+}
+
+template
+inline T *Malloc(A& a, size_t n = 1)
+{
+ return Realloc(a, NULL, 0, n);
+}
+
+template
+inline void Free(A& a, T *p, size_t n = 1)
+{
+ static_cast(Realloc(a, p, n, 0));
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
+#endif
+
+template
+class StdAllocator :
+ public std::allocator
+{
+ typedef std::allocator allocator_type;
+#if RAPIDJSON_HAS_CXX11
+ typedef std::allocator_traits traits_type;
+#else
+ typedef allocator_type traits_type;
+#endif
+
+public:
+ typedef BaseAllocator BaseAllocatorType;
+
+ StdAllocator() RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_()
+ { }
+
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ template
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(std::move(rhs)),
+ baseAllocator_(std::move(rhs.baseAllocator_))
+ { }
+#endif
+#if RAPIDJSON_HAS_CXX11
+ using propagate_on_container_move_assignment = std::true_type;
+ using propagate_on_container_swap = std::true_type;
+#endif
+
+ /* implicit */
+ StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_(allocator)
+ { }
+
+ ~StdAllocator() RAPIDJSON_NOEXCEPT
+ { }
+
+ template
+ struct rebind {
+ typedef StdAllocator other;
+ };
+
+ typedef typename traits_type::size_type size_type;
+ typedef typename traits_type::difference_type difference_type;
+
+ typedef typename traits_type::value_type value_type;
+ typedef typename traits_type::pointer pointer;
+ typedef typename traits_type::const_pointer const_pointer;
+
+#if RAPIDJSON_HAS_CXX11
+
+ typedef typename std::add_lvalue_reference::type &reference;
+ typedef typename std::add_lvalue_reference::type>::type &const_reference;
+
+ pointer address(reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return std::addressof(r);
+ }
+ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return std::addressof(r);
+ }
+
+ size_type max_size() const RAPIDJSON_NOEXCEPT
+ {
+ return traits_type::max_size(*this);
+ }
+
+ template
+ void construct(pointer p, Args&&... args)
+ {
+ traits_type::construct(*this, p, std::forward(args)...);
+ }
+ void destroy(pointer p)
+ {
+ traits_type::destroy(*this, p);
+ }
+
+#else // !RAPIDJSON_HAS_CXX11
+
+ typedef typename allocator_type::reference reference;
+ typedef typename allocator_type::const_reference const_reference;
+
+ pointer address(reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::address(r);
+ }
+ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::address(r);
+ }
+
+ size_type max_size() const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::max_size();
+ }
+
+ void construct(pointer p, const_reference r)
+ {
+ allocator_type::construct(p, r);
+ }
+ void destroy(pointer p)
+ {
+ allocator_type::destroy(p);
+ }
+
+#endif // !RAPIDJSON_HAS_CXX11
+
+ template
+ U* allocate(size_type n = 1, const void* = 0)
+ {
+ return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n);
+ }
+ template
+ void deallocate(U* p, size_type n = 1)
+ {
+ RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n);
+ }
+
+ pointer allocate(size_type n = 1, const void* = 0)
+ {
+ return allocate(n);
+ }
+ void deallocate(pointer p, size_type n = 1)
+ {
+ deallocate(p, n);
+ }
+
+#if RAPIDJSON_HAS_CXX11
+ using is_always_equal = std::is_empty;
+#endif
+
+ template
+ bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT
+ {
+ return baseAllocator_ == rhs.baseAllocator_;
+ }
+ template
+ bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT
+ {
+ return !operator==(rhs);
+ }
+
+ //! rapidjson Allocator concept
+ static const bool kNeedFree = BaseAllocator::kNeedFree;
+ static const bool kRefCounted = internal::IsRefCounted::Value;
+ void* Malloc(size_t size)
+ {
+ return baseAllocator_.Malloc(size);
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
+ {
+ return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
+ }
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT
+ {
+ BaseAllocator::Free(ptr);
+ }
+
+private:
+ template
+ friend class StdAllocator; // access to StdAllocator.*
+
+ BaseAllocator baseAllocator_;
+};
+
+#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17
+template
+class StdAllocator :
+ public std::allocator
+{
+ typedef std::allocator allocator_type;
+
+public:
+ typedef BaseAllocator BaseAllocatorType;
+
+ StdAllocator() RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_()
+ { }
+
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ template
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ /* implicit */
+ StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_(baseAllocator)
+ { }
+
+ ~StdAllocator() RAPIDJSON_NOEXCEPT
+ { }
+
+ template
+ struct rebind {
+ typedef StdAllocator other;
+ };
+
+ typedef typename allocator_type::value_type value_type;
+
+private:
+ template
+ friend class StdAllocator; // access to StdAllocator.*
+
+ BaseAllocator baseAllocator_;
+};
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/include/rapidjson/cursorstreamwrapper.h b/include/rapidjson/cursorstreamwrapper.h
index 52c11a7c0..fd6513db1 100644
--- a/include/rapidjson/cursorstreamwrapper.h
+++ b/include/rapidjson/cursorstreamwrapper.h
@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h
index 1a59a14e2..1cdc29c08 100644
--- a/include/rapidjson/document.h
+++ b/include/rapidjson/document.h
@@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@@ -24,7 +24,7 @@
#include "encodedstream.h"
#include // placement new
#include
-#ifdef __cpp_impl_three_way_comparison
+#ifdef __cpp_lib_three_way_comparison
#include
#endif
@@ -42,12 +42,21 @@ RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible lo
RAPIDJSON_DIAG_OFF(effc++)
#endif // __GNUC__
+#ifdef GetObject
+// see https://github.com/Tencent/rapidjson/issues/1448
+// a former included windows.h might have defined a macro called GetObject, which affects
+// GetObject defined here. This ensures the macro does not get applied
+#pragma push_macro("GetObject")
+#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
+#undef GetObject
+#endif
+
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include // std::random_access_iterator_tag
#endif
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include // std::move
+#if RAPIDJSON_USE_MEMBERSMAP
+#include