osrm-backend/include/rapidjson/document.h
Siarhei Fedartsou 0a2b8372ae Squashed 'third_party/rapidjson/' changes from f54b0e47a..f9d53419e
f9d53419e Add Hasher tests for objects where key eq value
6f79698b3 Fix swapped high and low offset basis values
eee82cb07 Fix object hashing in schema
b4a6da3e6 unit tests for 'Stringify NaN, Inf as null'
e7b6e5a20 Fix: 'Stringify NaN, Inf as null'
476ffa2fd Rename to fix allocator shadowing
5e17dbed3 Eliminate old style cast warning
956063dbc Fixing printf format warning
30f54566a Merge pull request #1901 from JackBoosY/master
516d04739 Remove empty cross-reference in comment
52dd94709 Merge branch 'master' into pr/1901
a95e013b9 Stringify NaN, Inf as null if needs
973dc9c06 Avoid ptrdiff between pointers to different allocations
2a1f586ba Check for __GNUC__ definition
0e88d5e40 Eliminate missing prototypes warning
949c771b0 Resolve conflict with Windows header about max macro
083f359f5 CMakeLists: fix optflags for ppc
012be8528 Use passed in allocator.
1ce516e50 Suppress uritest
778dc8b03 fix #1
76281ff38 fix a typo in error.h: literial -> literal
a98e99992 do not define operator!= in C++20
b08672d46 review comment updates
55eca66f3 code & tests for openapi 2.0 & 3.0 suppprt
80b6d1c83 small corrections for schema.h
97fd83017 attempt to fix SEH
7cad78e23 tidy up after merge from master
794248ee6 fix build break
2d87923e9 remove unnecessary templating from schema tests
aa1f22251 correct address.json so tests pass
ecb8d9e3a add dump of unexpected schema errors in schematest.cpp
89f6717f0 corrections
338d8defd initial
06d58b9e8 Update dtoa.h
22a62fcc2 Update allocators.h
27c3a8dc0 docs: fix simple typo, perecent -> percent
232389d4f delete unused variable
64faab2e9 gate definition of symmetric equality operators on impl, not lib
719304b11 fixes for natvis
dd3f730d7 Make schema dtor robust against exceptions
781a4e667 Try to fix MSVC build.
88f8ddd70 Include conceptual change from PR 2001.
469595356 Avoid exit-time destructors.
0390b1ad5 Avoid exit-time destructors.
2b2c80450 encdedstreamtest: fix use-after-free compile error with gcc-12
1f59c69cd valuetest: fix potential write of terminating nul past the end of the destination
3445e155e Merge branch 'master' into master
fcb23c2db Merge pull request #2008 from agate-pris/access-to-allocator-types
bdc49ad80 Merge pull request #2014 from lazydroid/dev/lenik/fix_shadowed_variables
6b500986c fix shadowed variable, take 2
3988c5e25 fix shadowed variable
386d31ab6 Allow access to the template parameter StackAllocator in the GenericDocument
79d7a448e Allow the macro RAPIDJSON_DEFAULT_STACK_ALLOCATOR to be used in any namespace
9965ab37f Allow the macro RAPIDJSON_DEFAULT_ALLOCATOR to be used in any namespace
8261c1ddf Merge pull request #1969 from MalcolmTyrrell/MalcolmTyrrell/sanitizeSchemaCode
0d78b1ce9 Merge pull request #1989 from adamcalhoon/really-fix-placement-new-alignment
1dff2abff Fix the alignment of placement new buffer for GenericValue.
e4bde9774 Merge pull request #1988 from Tencent/revert-1987-fix-placement-new-alignment
88bbd87dd Revert "Fix the alignment of placement new buffer for GenericValue."
bf8ca5da8 Merge pull request #1987 from adamcalhoon/fix-placement-new-alignment
5b242b6b2 Fix the alignment of placement new buffer for GenericValue.
fd3dc29a5 Merge pull request #1944 from ilelann/patch-1
53602ec6b Sanitize the code in schema.h
0d4517f15 Merge pull request #1961 from jedwardsol/issue1960_arm64ec_intrinsic
060c348ea use softintrin on arm64ec
4d6cb0818 Merge pull request #1949 from ardb-uk/master
033bef3c6 Merge pull request #1 from ardb-uk/ardb-uk-patch-1
befba39af Merge pull request #2 from ardb-uk/ardb-uk-patch-1-1
4bbaf28ff Add files via upload
14f1e37f8 Resolve issue 1948
e6736d1ba Support CMake none targets
2e8f5d897 Merge pull request #1940 from smhdfdl/issue-1924
9ea3f45db fix the warning
b9ae2499e Merge pull request #1941 from DiamondI/patch-1
553a3ea31 typo on documentation dom.zh-cn.md: "己于" -> "已于"
864e44aef Merge branch 'master' of https://github.com/Tencent/rapidjson
00dbcf2c6 Merge pull request #1926 from Kyrega/master
22ee8b07c Correct WIStreamWrapper
a3d52c75b No default template parameter for older compilers
19b55c904 No default template parameter for older compilers
128b1031b Use rapidjson internal::SelectIf
8710d7e98 Do not depend on c++11 conditional
e0512e094 Using unsigned for WIStreamWrapper
7fac34f7b Added typename
b952a592a Fix RawNumber for longer char types
28c59ab4c Merge pull request #1922 from jack-perisich/grisu2_precision
bb0621108 Fix small errors in dtoa output for certain doubles
7ee918fc8 Merge branch 'master' of https://github.com/Tencent/rapidjson
48fbd8cd2 Merge pull request #1848 from smhdfdl/id-and-ref
8d16abd98 Uri Parse improvements
b557259f8 Merge pull request #1904 from Tencent/issue1899_pointerappend
a21cf9f7b equiv fix for issue 1899
8c29a7b49 Fix Pointer::Append() crash for custom allocator on Windows
12b88efa6 fix coverage again
f6ebcb200 fix Uri.Match optional arg
3df804c12 fix coverage, unit test allocators and equality
18ab3b16b remove temp debug statements
6d253c160 remove compiler warning
28bcbd3f3 make std::string optional
f4be0ada8 Use modern cmake function export to generate target
494447b73 remove copyright & debug statements
6e58a53f4 fix coverage
3987d82f4 Merge branch 'master' of https://github.com/Tencent/rapidjson into id-and-ref
9c1002f94 rge branch 'master' of https://github.com/Tencent/rapidjson
17aa824c9 Merge pull request #1885 from saurabhchardereal/master
cd737fb54 Improve documentation
25fa7a119 Merge pull request #1883 from nkolotov/fix/issues/1882
3aa8d04b7 Fixed -Wshadow warning.
e0f68a435 Merge pull request #1877 from hendrikmuhs/windows-GetObject-conflict-#1418
3cdfde14d replace auto with concrete type
d179facf9 don't let the GetObject macro rewrite the GetObject method, add a GetObj alias
3168d7c34 add a test that provokes a compile time error on windows
47b837e14 Merge pull request #1485 from ylavic/MemberMap
be4a5a908 Turn some Tests to RAPIDJSON_USE_MEMBERSMAP in CI.
fc08f4f61 Tests for Members in std::multimap.
71f0fa7eb Set RAPIDJSON_USE_MEMBERSMAP to use a (std::multi)map for object members.
7d801bbe4 Merge pull request #1503 from ylavic/sub_value_assignment
03676c9bf Merge pull request #1870 from ylavic/allocators_rvalues
aa0675ffd Try some tests with -D_GLIBCXX_DEBUG and coverage with -O0.
5c764d9a8 Tests for Allocators copy by rvalue reference.
683010b02 Add rvalue copy and assignment to MemoryPoolAllocator and StdAllocator.
117276c41 Fix would-crash tests if the default allocator used were kNeedFree.
49aa0fc15 Merge pull request #1868 from ylavic/cpp17_in_ci
a8bd93176 Tests for C++17 with VS 2019.
6bed9b266 Don't define StdAllocator<void> from C++17.
e336667b4 Handle C++17 (and C++11 with MSVC) in CI.
b996a2371 Merge pull request #1866 from ylavic/std_allocator_traits
08cf9a56c Make StdAllocator C++17-20 compatible.
02f42604b Make StdAllocator C++17-20 compatible.
cd5ee4dfe Merge pull request #1858 from ylavic/std_allocator
3d77d11e2 add traverse as pointer example
2e6f76145 Tests for StdAllocator.
49e4dd619 Provide StdAllocator, STL compatible, for use with STL types.
50cb424c3 Test assignment from inner Value.
c033292ae Safer GenericValue& operator=(GenericValue& rhs).
d51dd2d0e RAPIDJSON_NOEXCEPT_ASSERT should assert regardless of RAPIDJSON_HAS_CXX11_NOEXCEPT.
cdb2d4757 Provide RAPIDJSON_HAS_CXX11 and use it for RAPIDJSON_HAS_CXX11_RVALUE_REFS and RAPIDJSON_HAS_CXX11_NOEXCEPT.
bc026e3fb satisfy all compilers 3
24b9b7e27 satisfy all compilers 2
32722fa31 satisfy all compilers
8768b5b1d correct #defines in uri.h
6c9da69ab remove comma
6b57738e4 handle internal refs properly
1c2c8e085 doc: fix incorrect template parameters in EncodedOutputStream example
fe1a29ca6 fix platform-dependent compiler error with >>
ad73c032e fix compile errors
892f6e3fd fix bracket
cabc3d5aa merge
7698b3cd4 code and tests
dad85cab9 Merge pull request #2 from smhdfdl/multiple-validation-failures-and-validation-messages
b1a4d91a5 Merge pull request #1779 from pavel-pimenov/fix-1778-part-1
8be64594f Merge pull request #1847 from stac47/fix_1846
24ebd5128 Fix recursive operator== call in C++20 (#1846)
8bce684cd Merge pull request #1844 from smhdfdl/multiple-validation-failures-and-validation-messages
9bb81e20f fix crash where simple type with sub-schema has a bad value
13dfc96c9 Merge pull request #1837 from smhdfdl/multiple-validation-failures-and-validation-messages
167efb4fa work around issue 1089
28dc42d8d restore coverage
a3757456f correct workaround for issue 1805
7fee368be Revert "revert perftest"
221e8d536 revert perftest
f89e75af7 remove C++ 11 std::string to_string() syntax
c491dd521 remove C++ 11 enum syntax
6f3cccd6e remove debug std::cout, handle empty error object in example
05e7b3397 code and tests
5d17b24e5 Merge pull request #1 from Tencent/master
585042c02 Merge pull request #1821 from slsyy/master
cbf62de55 Add implicit conversion from Object and Array to Value (#1404)
3cdd3c837 Merge pull request #1817 from lukedan/lukedan_cpp20
5e50f27ed also initialize class member
1e4f59d3a add return statement & comment
d742a030a add body to private copy constructor & copy assignment
300692623 suppress enum bitwise operation warnings on msvc
13f5ab4f4 fix schema test compile error
56f215e5c Merge pull request #1568 from ericrannaud/ericrannaud/memberiterator-public
0ccdbf364 Merge pull request #1786 from ssb22/master
b7734d97c Remove unnecessary wording from BSD license not needed for MIT license (fixes #528)
3a65e2dd7 fix https://github.com/Tencent/rapidjson/issues/1778 (part 1)
ce81bc9ed Merge pull request #1760 from escherstair/fix_ce6_support
5fbf8bf89 fix unit test
7f559ec80 fix naive implementation for clzll()
58e296485 add unit test for clzll()
aa5dd6086 fix naive version implementation
91940e84b fallback to the naive version for CE6
6364c8e5a fix _BitScanReverse() usage for CE6
f56928de8 Merge pull request #1744 from lklein53/improve-surrogate-handling
6694c996b Add test case for low surrogate handling
ed73d7bdb Improve surrogate handling
88bd956d6 Merge pull request #1453 from eidosmontreal/custom_malloc
004e8e61a Merge branch 'master' into custom_malloc
1a803826f Merge pull request #1720 from madeso/master
ac0fc79c7 Fixes issue #1718
8f4c021fa Merge pull request #1689 from g199209/master
1ce28f454 Add CMake minimum version required.
f37669082 Add a target to RapidJSONConfig.cmake.in (#1350)
234ff044f ci: upgrade distro to xenial and add arm64 test cases (#1662)
36481c30b Update Visual Studio Visualizer (#1665)
d4f03d0d0 Doc: Fix some typos. (#1675)
ebcbd0448 Three-way comparison for CLang 10 fix (#1679)
2661a17c7 Avoid warnings when using -std=c++20 and clang 10: use three way comparision for iterators when possible. (#1667)
814bb27bf Replace RAPIDJSON_CLZLL with internal clzll (#1660)
563fe5bbb PrettyWriter constructor uninitialized member (#1654)
2bed293f4 Update biginteger.h (#1652)
b16cec1a1 Closes #1643 (#1644)
98f52b6bb Fix simple typo: drived -> derived (#1646)
a895ce150 Allow escaped apostrophe in values (#1639)
418331e99 Merge pull request #1631 from PhoebeHui/dev/Phoebe/vcpkg_instructions
b4cf6e738 Add vcpkg installation instructions
dfbe1db9d Merge pull request #1502 from ylavic/compilation_fixes
eeb9d553f Merge pull request #1617 from JPEWdev/master
134af9d81 Remove shadow typedef
35e480fc4 Merge pull request #1609 from piratf/readme_contributing
6cadd4b2c add contributing section in readme.md, introduced the basic cooperation process.
6534506e8 Merge pull request #1603 from piratf/cmakelist_upgrade
46d980b46 fix CMake policy CMP0048 warning #1154
c4c6a6541 Merge pull request #1548 from TranslucentTB/master
e54aca700 Merge branch 'master' of https://github.com/Tencent/rapidjson
bb5f966b9 Merge pull request #1591 from veekxt/patch-1
67b245e07 doc: fix a typo
1a825d24f Merge pull request #1529 from rkoshy/master
6a6bed275 Merge pull request #1582 from crazyscot/master
5592c2eed Merge pull request #1544 from fredgan/master
39db1177b fix some misspellings
4116912cd Use C++17 fallthrough tag instead of disabling warning
d67a69a9c Merge pull request #1490 from MalcolmTyrrell/fixCompileErrorInPointerH
577729149 Merge pull request #1579 from Tencent/vs2010
88a1ba9e3 Provide default implementations for move constructor/assignment in GenericMember
c36b713c4 Disable copy constructor in GenericMember
6006d6b67 Merge pull request #1573 from esrrhs/master
02d4ae838 Update travis-doxygen.sh
4c1d9edb3 Update travis-doxygen.sh
c136acf02 Update travis-doxygen.sh
b2861565a Update travis-doxygen.sh
ed234bf74 Update .travis.yml
d3c4b2b2b Update .travis.yml
ebc003e20 Make GenericMemberIterator::Iterator public again (RAPIDJSON_NOMEMBERITERATORCLASS)
fcec7735d Merge pull request #1567 from AtnNn/master
123d7c89a add test for non-null-terminated token
6102f0bd0 fix template parameter
6fe99777e Allow pointer tokens to have non-null-terminated strings
2648a732d Merge pull request #1557 from MBoldyrev/doc/fix-uint-case
8973b279c fixed Uint case in docs
02230fecb Change #ifdef to #if defined
dfc0b3536 Update comment
0d671a2e1 Fix signedness error
07e1d7870 Fix build error under non-Clang compilers
d5d7171f6 Fix ARM NEON under MSVC
a133b1669 Merge pull request #1 from Tencent/master
d87b698d0 Change all GenericMemberIterator from struct to class
c43697c16 - Fixed a build issue by initializing "index" in the header file
4b3d7c2f4 Merge pull request #1506 from ylavic/CreatePattern
92f99bc2e RAPIDJSON_NOEXCEPT_ASSERT() should never throw.
b4538b536 Fix compilation of sortkeys.cpp with MSVC 2013 (hopefully).
94fc46380 Add missing curly brackets in STDREGEX's CreatePattern().
c840a7ae1 Fix vs2017 compile error C2105: '--' needs l-value
01950eb7a Merge pull request #1488 from somone23412/somone23412-fix-typo-1
0798d5b26 fix typo
e80257a92 Merge pull request #1481 from liangdzou/patch-1
13687a6e3 add missing header "ios"
e123f650a Merge pull request #1479 from MaxXSoft/patch-tutorial
d5c5b87f0 doc/tutorial.zh-cn: fixed some typos
55c3c241c Merge pull request #1477 from eisaev/patch-1
9264a9a7e Update allocators.h
091de040e Merge pull request #1462 from ra1u/master
40cae03b0 Allow user to define custom RAPIDJSON_NOEXCEPT_ASSERT macro
3cf4f7c5a Merge pull request #727 from mapbox/silence-dereference-null-pointer
7484e06c5 Update doxygen download URL
1ede098e9 Workaround of sortkeys example
cef07fb1b Added parameters to RAPIDJSON_MALLOC, RAPIDJSON_REALLOC and RAPIDJSON_FREE
ad2e5369b Adding a single customization point that ensures all allocations within rapidjson can be performed with a custom memory allocator; Introduces the macros RAPIDJSON_MALLOC, RAPIDJSON_REALLOC, and RAPIDJSON_FREE.
b94c2a120 Adding swap() for GenericMember
0739a3e88 Fix gcc compilation error in sortkeys
f595f8a6a Update sortkeys.cpp
189201321 Merge pull request #1421 from HomeControlAS/sort_by_name_example
79a6dabd0 Merge pull request #1439 from ylavic/schema_pointer_allocator
93cb84a7b Merge pull request #1442 from rbilovol/cmake-fixup
efad25970 Merge pull request #1444 from leolchat/patch-1
bf0939728 Correct complexity claim
8d272e53a CMake: remove hardcoded CMAKECONFIG_INSTALL_DIR path
dbb594bdb Use the allocator of the Schema for its Pointer.
bfdcf4911 Merge pull request #1426 from ylavic/pointer_less_than
b56eb2857 Merge branch 'master' into pointer_less_than
8549e3db6 Merge pull request #1431 from ylavic/pointer_swap
2ce91b823 Pointer tests now need <algorithm> (for std::swap), but no tabs.
a66cf7924 Allow to (std::)Swap two pointers.
eb6ee17d2 Speed up Pointer::operator<().
0e34ed43f Rework Pointer::operator<() loop.
af17f196c Unit test for Pointer::operator<().
055f1fa61 Add less than operator to Pointer.
66eb6067b Merge pull request #1425 from ylavic/filereadstream_peek4
b4b0e13b4 Merge pull request #1424 from ylavic/file_input_streams
eea3e57bc Merge pull request #1416 from ylavic/regex_syntax_noassert
38d25d745 Fix FileReadStream::Peek4().
8aab3db12 Base buffered BasicIStreamWrapper on the original (better performing) FileReadStream algorithm.
124e8b607 Possibly std::ios::binary helps with streams on Windows
2498c5776 Optimize FileReadStream and BasicIStreamWrapper.
d0188462d removed std::string and receiving const Value in printIt
c9060b4a5 added example for sorting keys
8c1478739 Unit test for invalid GenericRegex (unclosed parenthesis).
be96f4d7f GenericRegex: don't throw/abort on syntax error (unclosed parenthesis).
30d92a639 Merge pull request #1413 from ylavic/schema_regex_leak
1c5b90f40 Merge pull request #1414 from ylavic/regex_allocator
3e6956767 Fix a memory leak for invalid std::regex in Schema.
b0c96f9ba Use passed in allocator for internal regex parser.
a63216054 Merge pull request #1388 from yhager/yhager/clang-7
595ed48d5 Merge pull request #1403 from jcmonnin/fix-warning
51ca982aa Fix warning when NDEBUG is defined [-Wunused-variable]
0cc44c82c Update test/unittest/pointertest.cpp
a77b49dcb silence clang-7 self-assign-overloaded warning
67fac85e9 Merge pull request #1373 from lelit/issue1368
91d50c849 Add test case on kParseNumbersAsStringsFlag being able to load big ints
16872af88 Avoid pointer arithmetic on null pointer to remove undefined behavior
663f076c7 Merge pull request #1362 from jiapengwen/master
2a5e733b6 Merge pull request #1364 from jcourtat/fixfaq
68349ed91 faq: fix document insertion example
1cfa861d4 fix tutorial error
c0ca05f6d Merge pull request #1329 from pah/fix-noexcept
c2aa79dc8 Merge pull request #1356 from gongminmin/AppVeyor2017
783b819e6 Update rapidjson.h
a6be583ef Update appveyor rule to support VS2017.
8a96a95de Merge branch 'master' into fix-noexcept
f5f6052c5 Merge pull request #1327 from gongminmin/FixCompileInVS
08b1a8a41 Merge pull request #1302 from chwarr/min-max-guard
81af404b7 Merge pull request #1284 from mobileben/noexcept-assert
73063f500 Merge pull request #1340 from lelit/issue1336
c9eabf9e1 Extend the test on issue #1336 to cover all basic types
3fc9299b8 Add simple test for issue #1336
11defb7aa Wrap all WriteXxx() calls within EndValue(), to ensure a flush after root-level scalar value
6a905f931 Merge pull request #1331 from JPEWdev/mem-alignment-fix
91df56313 Merge pull request #1335 from IceTrailer/master
cd2824861 Fixed parentheses in reader.h which were required to prevent the using of max macro
748a652f0 Fix SIGBUS due to unaligned access
f54f6b5aa Add RAPIDJSON_NOEXCEPT_ASSERT
ff7634333 Update the code to adapt the new gtest.
2bbd33b33 Merge pull request #1323 from pah/fix-memaccess
152511689 Suppress -Wformat-overflow warning/error
a26267d16 Fix -Wsign-conversion warnings/errors
fa5963a2f Fix -Wclass-memaccess warnings/errors
4b4583bdb Merge pull request #1320 from AnomalRoil/master
93331cb0c Removing always true if condition
960b9cfd1 Guard against min/max being macros in reader.h
129d19ba7 Merge pull request #1312 from erikfroseth/issue-1308
3e255af03 Detect C++11 features for Developer Studio
b81438ea9 Merge pull request #1307 from moretromain/preprocessor_cleanup
fdd2db930 Updated google test to latest commit
4595cc488 Rename a few internal preprocessor macros to avoid potential naming conflicts
7e68aa0a2 Merge pull request #1252 from StilesCrisis/issue-1251-test
c511ce303 Merge pull request #1250 from StilesCrisis/issue-1249-test
6cc3910a1 Merge pull request #1290 from abolz/fix-strtod
7101911d9 Run all the new tests in full-precision mode only
319944a11 Disable failing test for now
a757a2aeb Add more tests
179277817 Add a test for BigInteger::operator<<
a0f9c5fc4 [Debug - clean up]
879ae853f Fix offset computation in BigInteger::operator<<
8b98f4a78 Workaround incorrect rounding in MSVC
a2813b673 Limit exponents
6cd5cd7b9 [Debug - Initialize variable]
292f787c0 [Debug]
695c9cb97 Use C macros with the correct header instead of std::numeric_limits and static_cast
1d636de81 Fix another signed/unsigned warning
a2a7d97b3 Use std::numeric_limits instead of macros
fc85fbeef Fix implicit signed/unsigned conversion and a small glitch in the error computation - part 2
16c97cd7c Fix implicit signed/unsigned conversion and a small glitch in the error computation
2ea43433e Fix bogus gcc warning
a78c8e3a4 Add more tests (which need to be fixed)
cb009f305 Return infinity if binary exponent is too large
7acbb87c2 Some more tests
4e9b4f6d6 Return 0 if binary exponent is too small
f5e5d47fa Properly test for overflow
d83d2ba26 Trim all zeros from input
c59ecc857 Replace unsigned with signed integer arithmetic in strtod
29b6c9b7d Add assertions to check preconditions of functions and unsigned integer arithmetic
80dba56ac Add tests for issues with string-to-double conversions (#849, #1249, #1251, #1253, #1256, #1259)
01c71740c Merge pull request #1287 from Nekto89/msvc_config
2b0843037 Autodetect RAPIDJSON_HAS_CXX11_NOEXCEPT and RAPIDJSON_HAS_CXX11_TYPETRAITS for Visual Studio
5b0610a74 Handle non-throwing exception specifications that can still throw #1280
c0daf7547 Merge pull request #1279 from bogaotory/master
6f7dcb30d again, in relation to solving issue #784, use `SizeType`-typed variable to indicate a none-zero length string has been given in the schema as default value for the json property; added an unittest `Object_Required_PassWithDefault`
fa98b5b4b in relation to solving issue #784, this commit enables the schema to recognise the "default" property, and avoids a missing property error when a default is given in the schema
af223d44f Merge pull request #1261 from fmalita/exponent-underflow
8269bc2bc Prevent int underflow when parsing exponents
1329cdecc Added test for issue #1251
cad380573 Update readertest.cpp
f7d2cd222 added test for parsing 0e100
532cba142 Merge pull request #4 from Tencent/master
a09103584 Merge pull request #1240 from ksergey/FIX_Reader
d0a78bf56 Added const for Reader methods
b32cd9421 Merge pull request #1217 from tresorit/win-clang-fix
ed72564e3 Merge pull request #1231 from steveire/patch-1
73b8774ab Use rvalue refs with clang-cl
5fd779d91 Merge pull request #1222 from DynonAvionics/adjustable_default_chunk_capacity
6f587466a Added macro RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY to allow default chunk capacity to be lowered for embedded devices with < 64k stack sizes
0fdd8040c fix compilation on windows with clang
8022a5f79 Merge pull request #1210 from foxtacles/fix-missing-remote-ref-p
9640209f7 remove superfluous typename
f8c8c32b4 fix C++03 compatibility
c8530d022 add test case for remote ref issue
8a6c345bc add remote ref to schemaMap_
67a17cfdb Merge pull request #1207 from vim2meta/master
de6681e29 ensure the pragma is only applied to MSVC
f0177eb93 Merge pull request #1203 from KuangLei/doc_AddingWriter
f9c933976 Adding a few missing includes
0f96b5605 Merge pull request #1202 from Sumoren/msc_long_part2
27424d5c0 Change long/ulong as int/uint on MSC unit tests to be more inline with other templated functions unit tests
d79533c65 Merge pull request #1199 from kachanovskiy/master
2e5dcceda Fixes #1198
3b638e671 Merge pull request #1191 from Sumoren/msc_long
a37f9d1ec Fix unsigned long as unsigned unit test
a040fc334 Add unittest for long as int in MSC platforms
294a5aca8 Support long and unsined long as int and unsigned on Microsft platforms
8bf4f7b97 Merge pull request #1188 from Martinfx/master
72481d5a0 Fix warnings Dereference of null pointer
9dfc43747 Merge pull request #1182 from Romain-Geissler-1A/ignore-gcc-8-warnings
91cd12313 Merge pull request #1181 from luzpaz/misc-typos
54dab1eeb Ignore GCC 8 warnings.
915218878 Misc. typos
49562271b Fix Windows build
59181a052 Revert "Fix API constness"
0d2580f1f Fix API constness
a1909a942 Merge pull request #1179 from Tencent/issue1153_rawvalueencoding
966987625 Add transcoding/validation to Writer::RawValue()
e2d0437a9 Fix false alarm from clang-tidy
82b5c4256 Fix Compile error because of -Werror=effc++ is on
672e7dd37 Fix invalid type in Pointer
daabb88e0 Merge pull request #1068 from yurikhan/violationDetails
7641af690 Merge pull request #1122 from svart-riddare/issue-1108
cdc899a3f Merge pull request #1124 from DerDakon/CMake-cleanup
fc7cda78a Fix -Werror=effc++
b1e556d71 Merge branch 'master' into violationDetails
03f5de9d7 Merge pull request #1065 from yurikhan/invalidSchemaPointer
9338148f5 Merge pull request #1161 from xiaoPierre/master
a735badbd Merge pull request #1162 from Tencent/travis
d48290e38 Another try to fix travis build
62e785bab Merge branch 'master' into travis
0d95d58f8 Try to fix travis build
b8c12c9cc Bug when switching to std regex
6043ad868 Merge pull request #1138 from Tencent/archiver_example
83f149e70 Merge pull request #1148 from lelit/fix-filewritestream-doc
a7f687fdf Merge pull request #1153 from Haffon/master
7dfeee862 GetParseOffset to GetErrorOffset
53eadd218 GetParseOffset to GetErrorOffset
20d44d9c4 Fix FileWriteStream doc
802ece6d7 Merge pull request #1147 from DrumMeister/master
9bfa0bb56 Fix uninitilized member Reader::state_
f2a28ee47 Add archiver example
87d4e07ff Merge pull request #1137 from pah/fixes/1131-iterator-deprecation
d75bb90a5 Avoid inheritance from std::iterator
7caa4b216 Merge pull request #1129 from thorade/patch-1
79d5e2367 Delete .DS_Store
80079f1fa Delete .DS_Store
195dc90d2 Delete .DS_Store
25c1b78f3 ignore DS_Store files
44f2f9aa5 Added relevant unit tests for issue #1108 suggested improvement.
ff59b6179 CMake: automatically handle C++11 settings if possible
4c9a28a28 CMake: do not pass -march=native or -mcpu=native when crosscompiling
4e1c7363c CMake: avoid neeless variable expansion
86e280f63 Solves #1108. The default copy constructor of GenericPointer will use the allocator of the copied object. The extra copy constructor that takes an allocator as a parameter is distinct if someone really wants to create a copy with a null allocator.
17ae6ffa8 Merge pull request #1110 from martinlindhe/master
8684c9960 fix some typos
5aa79b727 Merge pull request #1105 from clach04/issue_1104_solaris_fread
1be14d04a Fix issue #1104 Solaris compilation errors fread()/fwrite()
75a71441d Merge pull request #1102 from m-tayel/1019-proposed-fix
f4b1f761f Fixed typo in CMake file
7dddd0546 Merge pull request #1070 from KaitoHH/line-col
93f6cf4e8 Merge pull request #1081 from datatypevoid/patch-1
bf822593e Merge pull request #1083 from piotr-kaminski-intel/master
3c07cecdb Add anchors to Schema.md
db305dcf2 Fix schema.md TOC
4db8c3da1 Merge pull request #1098 from h46incon/MemberCapacity
a8e999060 Add MemberCapacity() and MemberReserve() interface for object type.
7d424c0bb Merge pull request #1092 from m-tayel/1019-proposed-fix
7bd9b5a1a enable cross compiling by adding option to remove -march/-cpu
bb99ccb03 Init variable in the constructor
d71ad0064 Merge pull request #1079 from captaincrutches/cmake-include-dir
495266271 Use SOURCE_DIR instead of CMAKE_DIR for build tree
f64b77300 Partially fix #1077
d5c1be5a0 Merge pull request #1082 from svart-riddare/regex-allocator
b217cc640 Removing Klocwork issues from schema.h
6e08e2942 Initialized regex with schema allocator.
f0391747e chore: correct spelling
84ca485e5 Make RapidJSON_INCLUDE_DIR non-blank in Config.cmake
8c182e51e Flatten allOf keyword violations
8353e868d Move schema violation docs into Schema chapter
1f7540270 refactor Schema: Keep ErrorHandler reference in Context
473553bd5 fix gcc & cl warning
9394b8444 remove unnecessary code
66541b892 add unit test for cursorstreamwrapper
799fdea9f add cursor wrapper
143641c75 suppress C4512, C4702 warning
79d9c71f9 fix stream wrapper initializer
b16ff281f Add feature of locating line and column number of error
2a0bc6062 Update gitbook zh-cn link
0b8adabab Fix #1071 gitbook link
a4b62ff61 Update schemavalidator example to demonstrate GetError()
384df14e6 Document schema violation format
056671680 Extend schema validation tests to compare error object
f716c3bfb Report schema violation details (#619)
c2371584a Keep schema URI in GenericSchemaDocument and internal::Schema
2bfd0cc6c internal::Schema: Keep pointer for future use
379b33744 Add failing test for the case when a remote schema is violated (#1064)
4c0f0036b Update appveyor badge and link
4a2f2729f Change from miloyip/rapidjson to Tencent/rapidjson
2a53253e7 Merge pull request #1056 from chwarr/assert-enum-lower
a683902b2 Assert Type enum lower bound as well
5db5dd552 Merge pull request #1057 from chwarr/paren-minmax
4bb4926c9 Merge pull request #1055 from chwarr/fix-doc-build-windows
e4c0ecf86 Guard against min/max macros in tests too
6e38649ec Guard against min/max being macros in document.h
bbdf5d1d4 Fix Windows doc build MSBuild error MSB6001
1e4609100 Merge pull request #1051 from gongminmin/master
e9373fc13 Merge pull request #1052 from Crunkle/master
9ce6a7ebb Fix processor check when empty
f91405801 Specifies the endian of msvc ARM64 configuration.
f05edc929 Merge pull request #1034 from bluehero/master
f9004b90c modify
c83167502 modify
5fb06596a modify
8ba1f84f4 modify unittest
9eb7bf895 add unittest
7c1f20825 modify
f7dd496cd Merge pull request #1 from miloyip/master
d6305514f Merge pull request #1030 from bmuzzin/issue1028_natvis
707fd36af Issue #1028: Visual Studio natvis file.
c34e3dfc7 Merge pull request #1018 from miloyip/issue1017_allOfHandler
fcd2e1f60 Fix #1017 allOf keyword fail with Writer handler
1a77513e6 Merge pull request #1013 from pah/fixes/1010-assert-stringref
2d27ce46b Merge pull request #1012 from pah/fixes/993-doxygen-internals
70171f979 GenericStringRef: move assert out of expression
7161894f4 travis-doxygen.sh: upgrade to Doxygen 1.8.13
37ea16df9 Merge pull request #1009 from pah/setup/travis-trusty
f624a3037 Merge pull request #1010 from pah/fixes/817-stringref-null
73df6c932 Merge pull request #1008 from pah/fixes/989-parseresult
4da20e21c Merge pull request #1002 from FluxLemur/patch-1
47c3c1ec9 Improved handling of NULL strings
f1ba61c7b unittest.h: change RAPIDJSON_ASSERT to allow usage in expressions
eefb618ec Travis: Switch to Ubuntu 14.04 (Trusty)
14218aeb0 ParseResult: improve bool conversion and add operator!=
3aafe12c9 undo changes to links and some minor changes to make the readme more easily readable
0d62f5cd3 Tutorial: fix typos in examples and broken links
2f45319b4 Merge pull request #968 from TomaszNo/icc-preprocessor-guard
77ae0b979 Merge pull request #987 from sledgeh/master
6a8f672ca Merge pull request #994 from Chocobo1/svg
a31a380cb Improve readme.md
6e81d49b3 Fixed #985 : Unittest failed with MinGWx64. And few small improvement were done while looking for mistakes.
b596f4e99 Merge pull request #977 from miloyip/issue825_patternProperties
df6362d45 Fix patternProperties & additionalProperties lead to ASSERT
342a616a7 Merge pull request #969 from pah/fixes/962-copy-const-strings
68c96e987 Fixup #964 by forwarding copyConstStrings recursively
33443e63a Merge pull request #967 from TomaszNo/storage-class-first
294ad93e3 To avoid Intel C++ Compiler #1879 warnings: warning #1879: unimplemented pragma ignored: #pragma intrinsic(_BitScanReverse64) warning #1879: unimplemented pragma ignored: #pragma intrinsic(_umul128)
77d2fadfb If storage class is not specified as first in declaration then Intel C++ Compiler 2017 generates message: message #82: storage class is not first
3202b0a3d Merge pull request #964 from pah/fixes/962-copy-const-strings
4ef1ff4fb GenericValue::CopyFrom: add option to force copying of strings
0033268c1 Update tutorial.zh-cn.md
56b7216ef Fix #949 about -Werror=conversion
f8eb7bae8 Remove -Weverything
b61bbbfe3 Fix #947 -Weffc++ warning
67b062b3c Merge pull request #946 from hwiesmann/master
568107e17 Add convenience method Key(std::basic_string<Ch> const&) to Writer
fe2b3603e Merge pull request #941 from harrywong/master
cba45fe9d Onley apply to GCC 7
fe19b7b60 Supress implicit fallthrough in GCC
a13acda97 Merge pull request #937 from bytePro17124/patch-1
4fe02e15f typo
b45c5408d Merge pull request #932 from JunHe77/master
d2fce9243 Merge pull request #933 from OlegHahm/minor_fixes
885b5cd2f common notation of empty if/else case
63423eb6f fix return values
2291258bb Added ARM-Neon support for SIMD.SkipWhitespace*
e6d7247ed Merge pull request #924 from lichray/fix-gcc7-warning
c6aec19ed Merge pull request #930 from pah/feature/cxx11-static_assert
f93a29bec RAPIDJSON_STATIC_ASSERT: use C++11 static_assert, if available
ec90588c7 Fix a non-type template parameter type mismatch
fcd263c61 Merge pull request #923 from miloyip/issue910_casting
77f643dc5 Fix #910 incorrect casting
5d9d0f78b Merge pull request #909 from miloyip/issue905_PrettyWriterWriteFlags
d88be8ef1 Fix #905 unable to set writeFlags for PrettyWriter
b8f0414b9 Merge pull request #907 from almavi/master
85500e8c8 Changed error code for invalid special ascii chars, fixed writer tests
3c6e2cf03 Added unittests for invalid ascii control chars
da4fd6794 Fixed bug on space hexadecimal encoding
430e8d4c9 Update schema.zh-cn.md
3f78a026c Merge pull request #903 from shadeware/patch-1
a38104a16 fix typos in doc code
1391e4257 Merge pull request #3 from miloyip/master
e5635fb27 Fix #899
0bc856a74 Merge pull request #894 from belveder79/master
bba388b4f Merge pull request #896 from StilesCrisis/writer-flush-api
465fab45c Merge pull request #897 from StilesCrisis/issue-889-pretty-writer
d5d18cf69 Fix template length optimization issue in PrettyWriter
31c6c50ac Provide a Flush() API within Writer
c7703f831 Merge branch 'lookahead-parser-improvements' into writer-flush-api
5b593bba1 Merge pull request #2 from miloyip/master
b91c515af update to create config file which is independent from actual install location
f0c108b5c Remove all switch
6723e3296 Initialize v_ to placate GCC
bf19c1a0b Remove switch
266870df8 Merge pull request #890 from StilesCrisis/issue-889
e7fd70769 Improve LookaheadParser
55f8a3202 Remove broken templatized string length optimization
84a035660 Add unit test for Issue 889
33a9f5850 Merge remote-tracking branch 'miloyip/master'
5de06bfa3 Merge pull request #882 from StilesCrisis/lookaheadparser
260e2f372 Merge remote-tracking branch 'refs/remotes/origin/lookaheadparser'
036f30021 Merge remote-tracking branch 'refs/remotes/miloyip/master'
2df32fbfa Merge pull request #881 from TedLyngmo/issue_874_Werror_effcplusplus
8da89f54b Fix GCC warning
d4669bbc8 Add lookahead parser example
ef22ca173 Fix -Werror=effc++ errors with GNU 6.3.1
c64f378f1 Fix -Werror=effc++ errors with GNU 6.3.1
237d2f2ea Merge remote-tracking branch 'miloyip/master'
a1fac159d Merge pull request #872 from StilesCrisis/issue845_native_strlen
c4e3d6243 Fix msvc x64 compilation issue
cdea825a0 Assert that String() and Key() are given null-terminated strings
61f8c4ef0 Quoted strings to String() or Key() are auto-sized by template
dd97ede84 Quoted strings to String() or Key() are auto-sized by template
7116c355d Merge remote-tracking branch 'miloyip/master' into issue845_native_strlen
02de69892 Merge pull request #876 from erikfroseth/issue-875
d6e9cf5d5 Remove executable bit
66b564f38 Remove unneeded change
db8d3bb4d Remove unneeded change
6ae50ad6e Once again
534f13526 Try again to suppress Valgrind
3f9ebfe9e Trivial change to trigger Travis CI
13e99d8d5 Trivial change to re-trigger Travis CI
9ae349c62 Merge pull request #871 from StilesCrisis/token-by-token-doc
4b822a41a Attempt to suppress valgrind wcslen error
6e2e5c7db Specialize StrLen for char/wchar_t
f349456bc Merge remote-tracking branch 'miloyip/master' into issue845_native_strlen
0f3bf99d5 Tiny fix
5c2bb1877 Add IterativeParse docs
e6b192a75 Merge pull request #869 from StilesCrisis/writer-key-fix
9cabd6372 Merge pull request #870 from StilesCrisis/null-handler-fix
4643104b8 Fix null handler construction
0ec4e86f1 Unit test
fa84cd18f Add matching fix for PrettyWriter
2e9b7b1ae Added assertion
595b11421 Unit test
26e089b9a Merge remote-tracking branch 'miloyip/master'
97e2f7f16 Try fixing Error compilation Ubuntu 14.04 #834
7f753fe76 Merge pull request #867 from oviradoi/issue858
82295b1f4 Merge pull request #842 from StilesCrisis/token-by-token-parsing
a677b8570 Merge pull request #866 from ylavic/patch-1
5f92c3926 Fix creating the nuget package with Raggles' fork of CoApp
b977fd3c9 Missing "internal" namespace for StrLen
0eaa0d288 Merge pull request #862 from StilesCrisis/nan-inf-parse-fix
ecf3d6429 Merge branch 'nan-inf-parse-fix' into token-by-token-parsing
5e785d3db Fix parsing of NaN/Inf
c4117c68c Put in unit tests to catch parser failure
bd4c282d7 Test coverage up
0f8389e78 Restored original IterativeParse implementation
488252eca Merge remote-tracking branch 'miloyip/master' into token-by-token-parsing
933eb839d Merge remote-tracking branch 'miloyip/master'
0163a53f4 Merge pull request #841 from StilesCrisis/improve-unit-test-reporting
a11ec6979 More C++98 fixes
6288d95d1 SimplePullReader C++98 support
4232e407f Clean up example code
d84d5fe05 Add example SimplePullHandler code
4394b3bac Add LIKELY and UNLIKELY hints
82a423db7 Added unit test for pull parsing
116f65994 Improve coverage and performance
5de725847 Improve performance
1a7c5ea51 Fix Dev Studio bool-conversion warning
20f5caa8f Token-by-token pull parsing
6769f3e33 Improved reporting
738864c53 Remove non-ASCII character
3693e942b Fix output character type in writers
942bb4608 Merge pull request #827 from lichray/fix-signed
265fb6ee8 Fix #831 RAPIDJSON_HAS_CXX11_RANGE_FOR is error defined
3cc77d5d6 Treat signed-unsigned conversions as errors.
835f2f4a7 Update Doxyfile.zh-cn.in
e61b66c38 Merge pull request #816 from SuperSodaSea/master
dba981600 Translate doc/internals.md Part 2
af4ec9b7e Translate doc/internals.md Part 1
03a739104 Merge pull request #757 from patcheng/feature/fix_clang_warning
369e07d1c Merge pull request #811 from glebov-andrey/improved_new_macro
41ceb8624 - replaced RAPIDJSON_NEW with C++98 compatible version
3f120caee - replaced RAPIDJSON_NEW calls in fwdtest.cpp
9fe93bb98 - replaced RAPIDJSON_NEW macro with variadic varient
014097e51 Merge pull request #800 from ivankravets/patch-3
ba34c9453 Update version to 1.1.0
0024592c2 Update sax.zh-cn.md
bff326fb2 Update sax.md
eb6831a4c Merge pull request #790 from SuperSodaSea/master
a077baa9c 修复拼写错误
fbcd7acfd Merge pull request #788 from miloyip/issue786_CopyFrom
e07d0e943 Move GenericValue deep-clone constructor into the class declaration.
95b346c3c Refactor GenericValue deep-clone constructor
d57944fc2 Merge pull request #783 from FrozenGene/master
c4db88a31 support IBM PowerPC / ppc64 / ppc64le and XL compiler
381d8f85e Merge pull request #782 from miloyip/issue781_aix
d7dd4106e Remove empty NumberStream::~NumberStream()
d6c8b378d Merge pull request #777 from miloyip/issue728_threadsafe
992b7f5f8 Fix nullHandler allocation bug
fba9ebd9b Merge pull request #776 from miloyip/issue728_threadsafe
59bcebbf3 Merge pull request #773 from bluehero/master
bf0cc7bea Fixed a bug for SchemaDocument move constructor
31ace3b76 use _mm_cmpistri
7c4e511eb Change Schema::GetTypeless() from singleton to instance
ddbd2ef05 Restore missing deallocation of GenericSchemaValidator::nullHandler_
b963eb447 Change SchemaValidator::GetNullHandler() from singleton to instance.
97fb9bc85 Merge pull request #770 from miloyip/issue728_threadsafe
3b1a03749 Merge pull request #748 from sfinktah/sfinktah-minwindef-fix
517dd4dbb Fix failing to resolve $ref in allOf causes crash in SchemaValidator::StartObject()
9b6af5552 Merge branch 'master' into issue728_threadsafe
236322797 Add Value::Value(float) and static_cast for suppressing clang warning
8eaa122c2 Update dom.zh-cn.md
94b36dc97 Merge pull request #763 from miloyip/issue762_move
3f2339759 Remove unncessary std::move()
11df748a3 Revert "Another try for fixing schema.md"
c490d880a Another try for fixing schema.md
a3300bf4b Fix schema.zh-cn.md
ba56498d1 Merge pull request #760 from icechen1/patch-1
48f8364f6 FIx typo in documentation
b4dae2b77 Merge pull request #755 from AdamMajer/fix_old_gcc
95224aff7 When length is 0, the code does nothing, so skip it completely.
91a803d46 Reserve() is sometimes called when stackTop_ is null. The assert is invalid.
9d8df28c1 added assertion to help suppress clang warnings
cb017cbf5 Fix compilation with older GCC versions
ffc794285 Merge pull request #750 from bennyyip/master
6a15e40b6 fix #749
51a31ce00 Fix for winmindef.h defining min/max macros
7a3917277 Merge pull request #746 from miloyip/issue744_stringbuffergetlength
5cd62c235 Add StringBuffer::GetLength()
0761ac126 Remove lambda expression in (pretty)writertest
f28203c7a Fix #741
185a7cc21 Merge pull request #740 from CreoValis/writer-move-ctor
1a64cd099 Tests for Writer, PrettyWriter move constructors
62dc1077e Move constructor support for PrettyWriter
307e02160 Move constructor support for Writer
52682115f Merge pull request #739 from miloyip/issue728_threadsafe
769185d68 Refactor regex
328ead0e1 Merge pull request #732 from miloyip/issue731_writerstringassert
3e2172bd5 Add preconditions in writer and string functions
8979c14fb Merge branch 'master' into issue716_parsebyparts
9f6688289 Merge pull request #730 from myd7349/master
6023ed3a0 Fix typo in doc
cdb345428 Merge pull request #723 from niukuo/master
250cf666d fix wrong length in remote schema
9bd618f54 Merge pull request #719 from yachoor/remove_broken_assignment
0f9dbe0a9 Defer thread creation in parsebypart example
862c39be3 Explicitly disable copy assignment operator
3b2441b87 Removed non-compiling assignment operator. Fixed #718

git-subtree-dir: third_party/rapidjson
git-subtree-split: f9d53419e912910fd8fa57d5705fa41425428c35
2024-05-26 09:34:45 +02:00

3044 lines
131 KiB
C++

// 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.
//
// 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
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_DOCUMENT_H_
#define RAPIDJSON_DOCUMENT_H_
/*! \file document.h */
#include "reader.h"
#include "internal/meta.h"
#include "internal/strfunc.h"
#include "memorystream.h"
#include "encodedstream.h"
#include <new> // placement new
#include <limits>
#ifdef __cpp_lib_three_way_comparison
#include <compare>
#endif
RAPIDJSON_DIAG_PUSH
#ifdef __clang__
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(c++98-compat)
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#endif
#ifdef __GNUC__
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 <iterator> // std::random_access_iterator_tag
#endif
#if RAPIDJSON_USE_MEMBERSMAP
#include <map> // std::multimap
#endif
RAPIDJSON_NAMESPACE_BEGIN
// Forward declaration.
template <typename Encoding, typename Allocator>
class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
/*! \def RAPIDJSON_DEFAULT_ALLOCATOR
\ingroup RAPIDJSON_CONFIG
\brief Allows to choose default allocator.
User can define this to use CrtAllocator or MemoryPoolAllocator.
*/
#ifndef RAPIDJSON_DEFAULT_ALLOCATOR
#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator>
#endif
/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR
\ingroup RAPIDJSON_CONFIG
\brief Allows to choose default stack allocator for Document.
User can define this to use CrtAllocator or MemoryPoolAllocator.
*/
#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR
#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator
#endif
/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
\ingroup RAPIDJSON_CONFIG
\brief User defined kDefaultObjectCapacity value.
User can define this as any natural number.
*/
#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
// number of objects that rapidjson::Value allocates memory for by default
#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16
#endif
/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
\ingroup RAPIDJSON_CONFIG
\brief User defined kDefaultArrayCapacity value.
User can define this as any natural number.
*/
#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
// number of array elements that rapidjson::Value allocates memory for by default
#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16
#endif
//! Name-value pair in a JSON object value.
/*!
This class was internal to GenericValue. It used to be a inner struct.
But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
https://code.google.com/p/rapidjson/issues/detail?id=64
*/
template <typename Encoding, typename Allocator>
class GenericMember {
public:
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
GenericValue<Encoding, Allocator> value; //!< value of member.
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT
: name(std::move(rhs.name)),
value(std::move(rhs.value))
{
}
//! Move assignment in C++11
GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT {
return *this = static_cast<GenericMember&>(rhs);
}
#endif
//! Assignment with move semantics.
/*! \param rhs Source of the assignment. Its name and value will become a null value after assignment.
*/
GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT {
if (RAPIDJSON_LIKELY(this != &rhs)) {
name = rhs.name;
value = rhs.value;
}
return *this;
}
// swap() for std::sort() and other potential use in STL.
friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT {
a.name.Swap(b.name);
a.value.Swap(b.value);
}
private:
//! Copy constructor is not permitted.
GenericMember(const GenericMember& rhs);
};
///////////////////////////////////////////////////////////////////////////////
// GenericMemberIterator
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
//! (Constant) member iterator for a JSON object value
/*!
\tparam Const Is this a constant iterator?
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
\tparam Allocator Allocator type for allocating memory of object, array and string.
This class implements a Random Access Iterator for GenericMember elements
of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
\note This iterator implementation is mainly intended to avoid implicit
conversions from iterator values to \c NULL,
e.g. from GenericValue::FindMember.
\note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
pointer-based implementation, if your platform doesn't provide
the C++ <iterator> header.
\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
*/
template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator {
friend class GenericValue<Encoding,Allocator>;
template <bool, typename, typename> friend class GenericMemberIterator;
typedef GenericMember<Encoding,Allocator> PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
public:
//! Iterator type itself
typedef GenericMemberIterator Iterator;
//! Constant iterator type
typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
//! Non-constant iterator type
typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
/** \name std::iterator_traits support */
//@{
typedef ValueType value_type;
typedef ValueType * pointer;
typedef ValueType & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
//@}
//! Pointer to (const) GenericMember
typedef pointer Pointer;
//! Reference to (const) GenericMember
typedef reference Reference;
//! Signed integer type (e.g. \c ptrdiff_t)
typedef difference_type DifferenceType;
//! Default constructor (singular value)
/*! Creates an iterator pointing to no element.
\note All operations, except for comparisons, are undefined on such values.
*/
GenericMemberIterator() : ptr_() {}
//! Iterator conversions to more const
/*!
\param it (Non-const) iterator to copy from
Allows the creation of an iterator from another GenericMemberIterator
that is "less const". Especially, creating a non-constant iterator
from a constant iterator are disabled:
\li const -> non-const (not ok)
\li const -> const (ok)
\li non-const -> const (ok)
\li non-const -> non-const (ok)
\note If the \c Const template parameter is already \c false, this
constructor effectively defines a regular copy-constructor.
Otherwise, the copy constructor is implicitly defined.
*/
GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
//! @name stepping
//@{
Iterator& operator++(){ ++ptr_; return *this; }
Iterator& operator--(){ --ptr_; return *this; }
Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
//@}
//! @name increment/decrement
//@{
Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
//@}
//! @name relations
//@{
template <bool Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; }
template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; }
template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; }
template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; }
#ifdef __cpp_lib_three_way_comparison
template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
#endif
//@}
//! @name dereference
//@{
Reference operator*() const { return *ptr_; }
Pointer operator->() const { return ptr_; }
Reference operator[](DifferenceType n) const { return ptr_[n]; }
//@}
//! Distance
DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
private:
//! Internal constructor from plain pointer
explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
Pointer ptr_; //!< raw pointer
};
#else // RAPIDJSON_NOMEMBERITERATORCLASS
// class-based member iterator implementation disabled, use plain pointers
template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator;
//! non-const GenericMemberIterator
template <typename Encoding, typename Allocator>
class GenericMemberIterator<false,Encoding,Allocator> {
public:
//! use plain pointer as iterator type
typedef GenericMember<Encoding,Allocator>* Iterator;
};
//! const GenericMemberIterator
template <typename Encoding, typename Allocator>
class GenericMemberIterator<true,Encoding,Allocator> {
public:
//! use plain const pointer as iterator type
typedef const GenericMember<Encoding,Allocator>* Iterator;
};
#endif // RAPIDJSON_NOMEMBERITERATORCLASS
///////////////////////////////////////////////////////////////////////////////
// GenericStringRef
//! Reference to a constant string (not taking a copy)
/*!
\tparam CharType character type of the string
This helper class is used to automatically infer constant string
references for string literals, especially from \c const \b (!)
character arrays.
The main use is for creating JSON string values without copying the
source string via an \ref Allocator. This requires that the referenced
string pointers have a sufficient lifetime, which exceeds the lifetime
of the associated GenericValue.
\b Example
\code
Value v("foo"); // ok, no need to copy & calculate length
const char foo[] = "foo";
v.SetString(foo); // ok
const char* bar = foo;
// Value x(bar); // not ok, can't rely on bar's lifetime
Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
Value y(StringRef(bar, 3)); // ok, explicitly pass length
\endcode
\see StringRef, GenericValue::SetString
*/
template<typename CharType>
struct GenericStringRef {
typedef CharType Ch; //!< character type of the string
//! Create string reference from \c const character array
#ifndef __clang__ // -Wdocumentation
/*!
This constructor implicitly creates a constant string reference from
a \c const character array. It has better performance than
\ref StringRef(const CharType*) by inferring the string \ref length
from the array length, and also supports strings containing null
characters.
\tparam N length of the string, automatically inferred
\param str Constant character array, lifetime assumed to be longer
than the use of the string in e.g. a GenericValue
\post \ref s == str
\note Constant complexity.
\note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
#endif
template<SizeType N>
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
: s(str), length(N-1) {}
//! Explicitly create string reference from \c const character pointer
#ifndef __clang__ // -Wdocumentation
/*!
This constructor can be used to \b explicitly create a reference to
a constant string pointer.
\see StringRef(const CharType*)
\param str Constant character pointer, lifetime assumed to be longer
than the use of the string in e.g. a GenericValue
\post \ref s == str
\note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the
GenericValue instead.
*/
#endif
explicit GenericStringRef(const CharType* str)
: s(str), length(NotNullStrLen(str)) {}
//! Create constant string reference from pointer and length
#ifndef __clang__ // -Wdocumentation
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\param len length of the string, excluding the trailing NULL terminator
\post \ref s == str && \ref length == len
\note Constant complexity.
*/
#endif
GenericStringRef(const CharType* str, SizeType len)
: s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
//! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; }
const Ch* const s; //!< plain CharType pointer
const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
private:
SizeType NotNullStrLen(const CharType* str) {
RAPIDJSON_ASSERT(str != 0);
return internal::StrLen(str);
}
/// Empty string - used when passing in a NULL pointer
static const Ch emptyString[];
//! Disallow construction from non-const array
template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */;
//! Copy assignment operator not permitted - immutable type
GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
};
template<typename CharType>
const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
//! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
\tparam CharType Character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\return GenericStringRef string reference object
\relatesalso GenericStringRef
\see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str) {
return GenericStringRef<CharType>(str);
}
//! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
This version has better performance with supplied length, and also
supports string containing null characters.
\tparam CharType character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\param length The length of source string.
\return GenericStringRef string reference object
\relatesalso GenericStringRef
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
return GenericStringRef<CharType>(str, SizeType(length));
}
#if RAPIDJSON_HAS_STDSTRING
//! Mark a string object as constant string
/*! Mark a string object (e.g. \c std::string) as a "string literal".
This function can be used to avoid copying a string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
\tparam CharType character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\return GenericStringRef string reference object
\relatesalso GenericStringRef
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
}
#endif
///////////////////////////////////////////////////////////////////////////////
// GenericValue type traits
namespace internal {
template <typename T, typename Encoding = void, typename Allocator = void>
struct IsGenericValueImpl : FalseType {};
// select candidates according to nested encoding and allocator types
template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
: IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
// helper to match arbitrary GenericValue instantiations, including derived classes
template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal
///////////////////////////////////////////////////////////////////////////////
// TypeHelper
namespace internal {
template <typename ValueType, typename T>
struct TypeHelper {};
template<typename ValueType>
struct TypeHelper<ValueType, bool> {
static bool Is(const ValueType& v) { return v.IsBool(); }
static bool Get(const ValueType& v) { return v.GetBool(); }
static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, int> {
static bool Is(const ValueType& v) { return v.IsInt(); }
static int Get(const ValueType& v) { return v.GetInt(); }
static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, unsigned> {
static bool Is(const ValueType& v) { return v.IsUint(); }
static unsigned Get(const ValueType& v) { return v.GetUint(); }
static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
};
#ifdef _MSC_VER
RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int));
template<typename ValueType>
struct TypeHelper<ValueType, long> {
static bool Is(const ValueType& v) { return v.IsInt(); }
static long Get(const ValueType& v) { return v.GetInt(); }
static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); }
static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
};
RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned));
template<typename ValueType>
struct TypeHelper<ValueType, unsigned long> {
static bool Is(const ValueType& v) { return v.IsUint(); }
static unsigned long Get(const ValueType& v) { return v.GetUint(); }
static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); }
static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
};
#endif
template<typename ValueType>
struct TypeHelper<ValueType, int64_t> {
static bool Is(const ValueType& v) { return v.IsInt64(); }
static int64_t Get(const ValueType& v) { return v.GetInt64(); }
static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, uint64_t> {
static bool Is(const ValueType& v) { return v.IsUint64(); }
static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, double> {
static bool Is(const ValueType& v) { return v.IsDouble(); }
static double Get(const ValueType& v) { return v.GetDouble(); }
static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, float> {
static bool Is(const ValueType& v) { return v.IsFloat(); }
static float Get(const ValueType& v) { return v.GetFloat(); }
static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, const typename ValueType::Ch*> {
typedef const typename ValueType::Ch* StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return v.GetString(); }
static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
};
#if RAPIDJSON_HAS_STDSTRING
template<typename ValueType>
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
typedef std::basic_string<typename ValueType::Ch> StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
};
#endif
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Array> {
typedef typename ValueType::Array ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(ValueType& v) { return v.GetArray(); }
static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
typedef typename ValueType::ConstArray ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(const ValueType& v) { return v.GetArray(); }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Object> {
typedef typename ValueType::Object ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(ValueType& v) { return v.GetObject(); }
static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstObject> {
typedef typename ValueType::ConstObject ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(const ValueType& v) { return v.GetObject(); }
};
} // namespace internal
// Forward declarations
template <bool, typename> class GenericArray;
template <bool, typename> class GenericObject;
///////////////////////////////////////////////////////////////////////////////
// GenericValue
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
/*!
A JSON value can be one of 7 types. This class is a variant type supporting
these types.
Use the Value if UTF8 and default allocator
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
\tparam Allocator Allocator type for allocating memory of object, array and string.
*/
template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR >
class GenericValue {
public:
//! Name-value pair in an object.
typedef GenericMember<Encoding, Allocator> Member;
typedef Encoding EncodingType; //!< Encoding type from template parameter.
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
typedef GenericArray<false, ValueType> Array;
typedef GenericArray<true, ValueType> ConstArray;
typedef GenericObject<false, ValueType> Object;
typedef GenericObject<true, ValueType> ConstObject;
//!@name Constructors and destructor.
//@{
//! Default constructor creates a null value.
GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
rhs.data_.f.flags = kNullFlag; // give up contents
}
#endif
private:
//! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Moving from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
//! Move assignment from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
#endif
public:
//! Constructor with JSON value type.
/*! This creates a Value of specified type with default content.
\param type Type of the value.
\note Default content for number is zero.
*/
explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
static const uint16_t defaultFlags[] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
kNumberAnyFlag
};
RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType);
data_.f.flags = defaultFlags[type];
// Use ShortString to store empty string.
if (type == kStringType)
data_.ss.SetLength(0);
}
//! Explicit copy constructor (with allocator)
/*! Creates a copy of a Value by using the given Allocator
\tparam SourceAllocator allocator of \c rhs
\param rhs Value to copy from (read-only)
\param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
\see CopyFrom()
*/
template <typename SourceAllocator>
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
switch (rhs.GetType()) {
case kObjectType:
DoCopyMembers(rhs, allocator, copyConstStrings);
break;
case kArrayType: {
SizeType count = rhs.data_.a.size;
GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();
for (SizeType i = 0; i < count; i++)
new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);
data_.f.flags = kArrayFlag;
data_.a.size = data_.a.capacity = count;
SetElementsPointer(le);
}
break;
case kStringType:
if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
}
else
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
break;
default:
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
}
}
//! Constructor for boolean value.
/*! \param b Boolean value
\note This constructor is limited to \em real boolean values and rejects
implicitly converted types like arbitrary pointers. Use an explicit cast
to \c bool, if you want to construct a boolean JSON value in such cases.
*/
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template <typename T>
explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
#else
explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif
: data_() {
// safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
data_.f.flags = b ? kTrueFlag : kFalseFlag;
}
//! Constructor for int value.
explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i;
data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
}
//! Constructor for unsigned value.
explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u;
data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
}
//! Constructor for int64_t value.
explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i64;
data_.f.flags = kNumberInt64Flag;
if (i64 >= 0) {
data_.f.flags |= kNumberUint64Flag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
data_.f.flags |= kUintFlag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
//! Constructor for uint64_t value.
explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u64;
data_.f.flags = kNumberUint64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
data_.f.flags |= kInt64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
data_.f.flags |= kUintFlag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
data_.f.flags |= kIntFlag;
}
//! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
//! Constructor for float value.
explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
//! Constructor for constant string (i.e. do not make a copy of string)
explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#if RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string)
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#endif
//! Constructor for Array.
/*!
\param a An array obtained by \c GetArray().
\note \c Array is always pass-by-value.
\note the source array is moved into this value and the sourec array becomes empty.
*/
GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
a.value_.data_ = Data();
a.value_.data_.f.flags = kArrayFlag;
}
//! Constructor for Object.
/*!
\param o An object obtained by \c GetObject().
\note \c Object is always pass-by-value.
\note the source object is moved into this value and the sourec object becomes empty.
*/
GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
o.value_.data_ = Data();
o.value_.data_.f.flags = kObjectFlag;
}
//! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string.
*/
~GenericValue() {
// 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) {
case kArrayFlag:
{
GenericValue* e = GetElementsPointer();
for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue();
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
Allocator::Free(e);
}
}
break;
case kObjectFlag:
DoFreeMembers();
break;
case kCopyStringFlag:
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
Allocator::Free(const_cast<Ch*>(GetStringPointer()));
}
break;
default:
break; // Do nothing for other types.
}
}
}
//@}
//!@name Assignment operators
//@{
//! Assignment with move semantics.
/*! \param rhs Source of the assignment. It will become a null value after assignment.
*/
GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
if (RAPIDJSON_LIKELY(this != &rhs)) {
// Can't destroy "this" before assigning "rhs", otherwise "rhs"
// could be used after free if it's an sub-Value of "this",
// hence the temporary danse.
GenericValue temp;
temp.RawAssign(rhs);
this->~GenericValue();
RawAssign(temp);
}
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
return *this = rhs.Move();
}
#endif
//! Assignment of constant string reference (no copy)
/*! \param str Constant string reference to be assigned
\note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
\see GenericStringRef, operator=(T)
*/
GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
GenericValue s(str);
return *this = s;
}
//! Assignment with primitive types.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param value The value to be assigned.
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref SetString(const Ch*, Allocator&) (for copying) or
\ref StringRef() (to explicitly mark the pointer as constant) instead.
All other pointer types would implicitly convert to \c bool,
use \ref SetBool() instead.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
operator=(T value) {
GenericValue v(value);
return *this = v;
}
//! Deep-copy assignment from Value
/*! Assigns a \b copy of the Value to the current Value object
\tparam SourceAllocator Allocator type of \c rhs
\param rhs Value to copy from (read-only)
\param allocator Allocator to use for copying
\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
*/
template <typename SourceAllocator>
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
this->~GenericValue();
new (this) GenericValue(rhs, allocator, copyConstStrings);
return *this;
}
//! Exchange the contents of this value with those of other.
/*!
\param other Another value.
\note Constant complexity.
*/
GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
GenericValue temp;
temp.RawAssign(*this);
RawAssign(other);
other.RawAssign(temp);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Prepare Value for move semantics
/*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
//@}
//!@name Equal-to and not-equal-to operators
//@{
//! Equal-to operator
/*!
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
\note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings).
*/
template <typename SourceAllocator>
bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
typedef GenericValue<Encoding, SourceAllocator> RhsType;
if (GetType() != rhs.GetType())
return false;
switch (GetType()) {
case kObjectType: // Warning: O(n^2) inner-loop
if (data_.o.size != rhs.data_.o.size)
return false;
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
return false;
}
return true;
case kArrayType:
if (data_.a.size != rhs.data_.a.size)
return false;
for (SizeType i = 0; i < data_.a.size; i++)
if ((*this)[i] != rhs[i])
return false;
return true;
case kStringType:
return StringEqual(rhs);
case kNumberType:
if (IsDouble() || rhs.IsDouble()) {
double a = GetDouble(); // May convert from integer to double.
double b = rhs.GetDouble(); // Ditto
return a >= b && a <= b; // Prevent -Wfloat-equal
}
else
return data_.n.u64 == rhs.data_.n.u64;
default:
return true;
}
}
//! Equal-to operator with const C-string pointer
bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
#if RAPIDJSON_HAS_STDSTRING
//! Equal-to operator with string object
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
#endif
//! Equal-to operator with primitive types
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
*/
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
#ifndef __cpp_impl_three_way_comparison
//! Not-equal-to operator
/*! \return !(*this == rhs)
*/
template <typename SourceAllocator>
bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
//! Not-equal-to operator with const C-string pointer
bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
//! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs)
*/
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
//! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs)
*/
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
//! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs)
*/
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
//@}
#endif
//!@name Type
//@{
Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
bool IsNull() const { return data_.f.flags == kNullFlag; }
bool IsFalse() const { return data_.f.flags == kFalseFlag; }
bool IsTrue() const { return data_.f.flags == kTrueFlag; }
bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
bool IsObject() const { return data_.f.flags == kObjectFlag; }
bool IsArray() const { return data_.f.flags == kArrayFlag; }
bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
// Checks whether a number can be losslessly converted to a double.
bool IsLosslessDouble() const {
if (!IsNumber()) return false;
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
return (d >= 0.0)
&& (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))
&& (u == static_cast<uint64_t>(d));
}
if (IsInt64()) {
int64_t i = GetInt64();
volatile double d = static_cast<double>(i);
return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
&& (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
&& (i == static_cast<int64_t>(d));
}
return true; // double, int, uint are always lossless
}
// Checks whether a number is a float (possible lossy).
bool IsFloat() const {
if ((data_.f.flags & kDoubleFlag) == 0)
return false;
double d = GetDouble();
return d >= -3.4028234e38 && d <= 3.4028234e38;
}
// Checks whether a number can be losslessly converted to a float.
bool IsLosslessFloat() const {
if (!IsNumber()) return false;
double a = GetDouble();
if (a < static_cast<double>(-(std::numeric_limits<float>::max)())
|| a > static_cast<double>((std::numeric_limits<float>::max)()))
return false;
double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal
}
//@}
//!@name Null
//@{
GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
//@}
//!@name Bool
//@{
bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
//!< Set boolean value
/*! \post IsBool() == true */
GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
//@}
//!@name Object
//@{
//! Set this value as an empty object.
/*! \post IsObject() == true */
GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
//! Get the number of members in the object.
SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
//! Get the capacity of object.
SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }
//! Check whether the object is empty.
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
//! Get a value from an object associated with the name.
/*! \pre IsObject() == true
\tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
\note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
Since 0.2, if the name is not correct, it will assert.
If user is unsure whether a member exists, user should use HasMember() first.
A better approach is to use FindMember().
\note Linear time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
GenericValue n(StringRef(name));
return (*this)[n];
}
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
//! Get a value from an object associated with the name.
/*! \pre IsObject() == true
\tparam SourceAllocator Allocator of the \c name value
\note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
And it can also handle strings with embedded null characters.
\note Linear time complexity.
*/
template <typename SourceAllocator>
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator member = FindMember(name);
if (member != MemberEnd())
return member->value;
else {
RAPIDJSON_ASSERT(false); // see above note
#if RAPIDJSON_HAS_CXX11
// Use thread-local storage to prevent races between threads.
// Use static buffer and placement-new to prevent destruction, with
// alignas() to ensure proper alignment.
alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(_MSC_VER) && _MSC_VER < 1900
// There's no way to solve both thread locality and proper alignment
// simultaneously.
__declspec(thread) static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(__GNUC__) || defined(__clang__)
// This will generate -Wexit-time-destructors in clang, but that's
// better than having under-alignment.
__thread static GenericValue buffer;
return buffer;
#else
// Don't know what compiler this is, so don't know how to ensure
// thread-locality.
static GenericValue buffer;
return buffer;
#endif
}
}
template <typename SourceAllocator>
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
#if RAPIDJSON_HAS_STDSTRING
//! Get a value from an object associated with name (string object).
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
#endif
//! Const member iterator
/*! \pre IsObject() == true */
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
//! Const \em past-the-end member iterator
/*! \pre IsObject() == true */
ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
//! Member iterator
/*! \pre IsObject() == true */
MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
//! \em Past-the-end member iterator
/*! \pre IsObject() == true */
MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
//! Request the object to have enough capacity to store members.
/*! \param newCapacity The capacity that the object at least need to have.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note Linear time complexity.
*/
GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
RAPIDJSON_ASSERT(IsObject());
DoReserveMembers(newCapacity, allocator);
return *this;
}
//! Check whether a member exists in the object.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
#if RAPIDJSON_HAS_STDSTRING
//! Check whether a member exists in the object with string object.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
#endif
//! Check whether a member exists in the object with GenericValue name.
/*!
This version is faster because it does not need a StrLen(). It can also handle string with null character.
\param name Member name to be searched.
\pre IsObject() == true
\return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain the value as well.
\note Linear time complexity.
*/
template <typename SourceAllocator>
bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
//! Find member by name.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
\note Earlier versions of Rapidjson returned a \c NULL pointer, in case
the requested member doesn't exist. For consistency with e.g.
\c std::map, this has been changed to MemberEnd() now.
\note Linear time complexity.
*/
MemberIterator FindMember(const Ch* name) {
GenericValue n(StringRef(name));
return FindMember(n);
}
ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
//! Find member by name.
/*!
This version is faster because it does not need a StrLen(). It can also handle string with null character.
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
\note Earlier versions of Rapidjson returned a \c NULL pointer, in case
the requested member doesn't exist. For consistency with e.g.
\c std::map, this has been changed to MemberEnd() now.
\note Linear time complexity.
*/
template <typename SourceAllocator>
MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
return DoFindMember(name);
}
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING
//! Find member by string object name.
/*!
\param name Member name to be searched.
\pre IsObject() == true
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
*/
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
#endif
//! Add a member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value Value of any type.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note The ownership of \c name and \c value will be transferred to this object on success.
\pre IsObject() && name.IsString()
\post name.IsNull() && value.IsNull()
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
DoAddMember(name, value, allocator);
return *this;
}
//! Add a constant string value as member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
#if RAPIDJSON_HAS_STDSTRING
//! Add a string object as member (name-value pair) to the object.
/*! \param name A string value as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
GenericValue v(value, allocator);
return AddMember(name, v, allocator);
}
#endif
//! Add any primitive value as member (name-value pair) to the object.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param name A string value as name of member.
\param value Value of primitive type \c T as value of member
\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
AddMember(StringRefType, StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized Constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
AddMember(GenericValue& name, T value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Add a member (name-value pair) to the object.
/*! \param name A constant string reference as name of member.
\param value Value of any type.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note The ownership of \c value will be transferred to this object on success.
\pre IsObject()
\post value.IsNull()
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
//! Add a constant string value as member (name-value pair) to the object.
/*! \param name A constant string reference as name of member.
\param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
\note Amortized Constant time complexity.
*/
GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
GenericValue v(value);
return AddMember(name, v, allocator);
}
//! Add any primitive value as member (name-value pair) to the object.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param name A constant string reference as name of member.
\param value Value of primitive type \c T as value of member
\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\pre IsObject()
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
AddMember(StringRefType, StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized Constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
AddMember(StringRefType name, T value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
//! Remove all members in the object.
/*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
\note Linear time complexity.
*/
void RemoveAllMembers() {
RAPIDJSON_ASSERT(IsObject());
DoClearMembers();
}
//! Remove a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note This function may reorder the object members. Use \ref
EraseMember(ConstMemberIterator) if you need to preserve the
relative order of the remaining members.
\note Linear time complexity.
*/
bool RemoveMember(const Ch* name) {
GenericValue n(StringRef(name));
return RemoveMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
RemoveMember(m);
return true;
}
else
return false;
}
//! Remove a member in object by iterator.
/*! \param m member iterator (obtained by FindMember() or MemberBegin()).
\return the new iterator after removal.
\note This function may reorder the object members. Use \ref
EraseMember(ConstMemberIterator) if you need to preserve the
relative order of the remaining members.
\note Constant time complexity.
*/
MemberIterator RemoveMember(MemberIterator m) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
return DoRemoveMember(m);
}
//! Remove a member from an object by iterator.
/*! \param pos iterator to the member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
\return Iterator following the removed element.
If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
\note This function preserves the relative order of the remaining object
members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
\note Linear time complexity.
*/
MemberIterator EraseMember(ConstMemberIterator pos) {
return EraseMember(pos, pos +1);
}
//! Remove members in the range [first, last) from an object.
/*! \param first iterator to the first member to remove
\param last iterator following the last member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
\return Iterator following the last removed element.
\note This function preserves the relative order of the remaining object
members.
\note Linear time complexity.
*/
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(first >= MemberBegin());
RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= MemberEnd());
return DoEraseMembers(first, last);
}
//! Erase a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note Linear time complexity.
*/
bool EraseMember(const Ch* name) {
GenericValue n(StringRef(name));
return EraseMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
EraseMember(m);
return true;
}
else
return false;
}
Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
//@}
//!@name Array
//@{
//! Set this value as an empty array.
/*! \post IsArray == true */
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
//! Get the number of elements in array.
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
//! Get the capacity of array.
SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
//! Check whether the array is empty.
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
//! Remove all elements in the array.
/*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
\note Linear time complexity.
*/
void Clear() {
RAPIDJSON_ASSERT(IsArray());
GenericValue* e = GetElementsPointer();
for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue();
data_.a.size = 0;
}
//! Get an element from array by index.
/*! \pre IsArray() == true
\param index Zero-based index of element.
\see operator[](T*)
*/
GenericValue& operator[](SizeType index) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(index < data_.a.size);
return GetElementsPointer()[index];
}
const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
//! Element iterator
/*! \pre IsArray() == true */
ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
//! \em Past-the-end element iterator
/*! \pre IsArray() == true */
ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
//! Constant element iterator
/*! \pre IsArray() == true */
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
//! Constant \em past-the-end element iterator
/*! \pre IsArray() == true */
ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
//! Request the array to have enough capacity to store elements.
/*! \param newCapacity The capacity that the array at least need to have.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note Linear time complexity.
*/
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
RAPIDJSON_ASSERT(IsArray());
if (newCapacity > data_.a.capacity) {
SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
data_.a.capacity = newCapacity;
}
return *this;
}
//! Append a GenericValue at the end of the array.
/*! \param value Value to be appended.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\post value.IsNull() == true
\return The value itself for fluent API.
\note The ownership of \c value will be transferred to this array on success.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note Amortized constant time complexity.
*/
GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsArray());
if (data_.a.size >= data_.a.capacity)
Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
GetElementsPointer()[data_.a.size++].RawAssign(value);
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
return PushBack(value, allocator);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Append a constant string reference at the end of the array.
/*! \param value Constant string reference to be appended.
\param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\return The value itself for fluent API.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note Amortized constant time complexity.
\see GenericStringRef
*/
GenericValue& PushBack(StringRefType value, Allocator& allocator) {
return (*this).template PushBack<StringRefType>(value, allocator);
}
//! Append a primitive value at the end of the array.
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
\param value Value of primitive type T to be appended.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true
\return The value itself for fluent API.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note The source type \c T explicitly disallows all pointer types,
especially (\c const) \ref Ch*. This helps avoiding implicitly
referencing character strings with insufficient lifetime, use
\ref PushBack(GenericValue&, Allocator&) or \ref
PushBack(StringRefType, Allocator&).
All other pointer types would implicitly convert to \c bool,
use an explicit cast instead, if needed.
\note Amortized constant time complexity.
*/
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
PushBack(T value, Allocator& allocator) {
GenericValue v(value);
return PushBack(v, allocator);
}
//! Remove the last element in the array.
/*!
\note Constant time complexity.
*/
GenericValue& PopBack() {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(!Empty());
GetElementsPointer()[--data_.a.size].~GenericValue();
return *this;
}
//! Remove an element of array by iterator.
/*!
\param pos iterator to the element to remove
\pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
\return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
\note Linear time complexity.
*/
ValueIterator Erase(ConstValueIterator pos) {
return Erase(pos, pos + 1);
}
//! Remove elements in the range [first, last) of the array.
/*!
\param first iterator to the first element to remove
\param last iterator following the last element to remove
\pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
\return Iterator following the last removed element.
\note Linear time complexity.
*/
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(data_.a.size > 0);
RAPIDJSON_ASSERT(GetElementsPointer() != 0);
RAPIDJSON_ASSERT(first >= Begin());
RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= End());
ValueIterator pos = Begin() + (first - Begin());
for (ValueIterator itr = pos; itr != last; ++itr)
itr->~GenericValue();
std::memmove(static_cast<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
data_.a.size -= static_cast<SizeType>(last - first);
return pos;
}
Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
//@}
//!@name Number
//@{
int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
//! Get the value as double type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
*/
double GetDouble() const {
RAPIDJSON_ASSERT(IsNumber());
if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
}
//! Get the value as float type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
*/
float GetFloat() const {
return static_cast<float>(GetDouble());
}
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
//@}
//!@name String
//@{
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
//! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
*/
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
//! 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.
\param s source string pointer.
\param length The length of source string, excluding the trailing null terminator.
\return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == length
\see SetString(StringRefType)
*/
GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
//! Set this value as a string without copying source string.
/*! \param s source string reference
\return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == s.length
*/
GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
//! Set this value as a string by copying from source string.
/*! This version has better performance with supplied length, and also support string containing null character.
\param s source string.
\param length The length of source string, excluding the trailing null terminator.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
//! Set this value as a string by copying from source string.
/*! \param s source string reference
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
#if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
#endif
//@}
//!@name Array
//@{
//! Templated version for checking whether this value is type T.
/*!
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
*/
template <typename T>
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
template <typename T>
T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
template <typename T>
T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
template<typename T>
ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
template<typename T>
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
//@}
//! Generate events of this value to a Handler.
/*! This function adopts the GoF visitor pattern.
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
It can also be used to deep clone this value via GenericDocument, which is also a Handler.
\tparam Handler type of handler.
\param handler An object implementing concept Handler.
*/
template <typename Handler>
bool Accept(Handler& handler) const {
switch(GetType()) {
case kNullType: return handler.Null();
case kFalseType: return handler.Bool(false);
case kTrueType: return handler.Bool(true);
case kObjectType:
if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
return false;
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
return false;
if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
return false;
}
return handler.EndObject(data_.o.size);
case kArrayType:
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
return false;
for (ConstValueIterator v = Begin(); v != End(); ++v)
if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
return false;
return handler.EndArray(data_.a.size);
case kStringType:
return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
default:
RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsDouble()) return handler.Double(data_.n.d);
else if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsUint()) return handler.Uint(data_.n.u.u);
else if (IsInt64()) return handler.Int64(data_.n.i64);
else return handler.Uint64(data_.n.u64);
}
}
private:
template <typename, typename> friend class GenericValue;
template <typename, typename, typename> friend class GenericDocument;
enum {
kBoolFlag = 0x0008,
kNumberFlag = 0x0010,
kIntFlag = 0x0020,
kUintFlag = 0x0040,
kInt64Flag = 0x0080,
kUint64Flag = 0x0100,
kDoubleFlag = 0x0200,
kStringFlag = 0x0400,
kCopyFlag = 0x0800,
kInlineStrFlag = 0x1000,
// Initial flags of different types.
kNullFlag = kNullType,
// These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types.
kTrueFlag = static_cast<int>(kTrueType) | static_cast<int>(kBoolFlag),
kFalseFlag = static_cast<int>(kFalseType) | static_cast<int>(kBoolFlag),
kNumberIntFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag),
kNumberUintFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag),
kNumberInt64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kInt64Flag),
kNumberUint64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUint64Flag),
kNumberDoubleFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kDoubleFlag),
kNumberAnyFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag),
kConstStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag),
kCopyStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag | kCopyFlag),
kShortStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag | kCopyFlag | kInlineStrFlag),
kObjectFlag = kObjectType,
kArrayFlag = kArrayType,
kTypeMask = 0x07
};
static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY;
static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY;
struct Flag {
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
#elif RAPIDJSON_64BIT
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
#else
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
#endif
uint16_t flags;
};
struct String {
SizeType length;
SizeType hashcode; //!< reserved
const Ch* str;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
// (excluding the terminating zero) and store a value to determine the length of the contained
// string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
// to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
// the string terminator as well. For getting the string length back from that value just use
// "MaxSize - str[LenPos]".
// This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
// 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
struct ShortString {
enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
Ch str[MaxChars];
inline static bool Usable(SizeType len) { return (MaxSize >= len); }
inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// By using proper binary layout, retrieval of different integer types do not need conversions.
union Number {
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
struct I {
int i;
char padding[4];
}i;
struct U {
unsigned u;
char padding2[4];
}u;
#else
struct I {
char padding[4];
int i;
}i;
struct U {
char padding2[4];
unsigned u;
}u;
#endif
int64_t i64;
uint64_t u64;
double d;
}; // 8 bytes
struct ObjectData {
SizeType size;
SizeType capacity;
Member* members;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct ArrayData {
SizeType size;
SizeType capacity;
GenericValue* elements;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
union Data {
String s;
ShortString ss;
Number n;
ObjectData o;
ArrayData a;
Flag f;
}; // 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* 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* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
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); }
#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.
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
data_.f.flags = kArrayFlag;
if (count) {
GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
SetElementsPointer(e);
std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue));
}
else
SetElementsPointer(0);
data_.a.size = data_.a.capacity = count;
}
//! Initialize this value as object with initial data, without calling destructor.
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
data_.f.flags = kObjectFlag;
if (count) {
Member* m = DoAllocMembers(count, allocator);
SetMembersPointer(m);
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
SetMembersPointer(0);
data_.o.size = data_.o.capacity = count;
}
//! Initialize this value as constant string, without calling destructor.
void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
data_.f.flags = kConstStringFlag;
SetStringPointer(s);
data_.s.length = s.length;
}
//! Initialize this value as copy string with initial data, without calling destructor.
void SetStringRaw(StringRefType s, Allocator& allocator) {
Ch* str = 0;
if (ShortString::Usable(s.length)) {
data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length);
str = data_.ss.str;
} else {
data_.f.flags = kCopyStringFlag;
data_.s.length = s.length;
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
SetStringPointer(str);
}
std::memcpy(str, s, s.length * sizeof(Ch));
str[s.length] = '\0';
}
//! Assignment without calling destructor
void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
data_ = rhs.data_;
// data_.f.flags = rhs.data_.f.flags;
rhs.data_.f.flags = kNullFlag;
}
template <typename SourceAllocator>
bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
RAPIDJSON_ASSERT(IsString());
RAPIDJSON_ASSERT(rhs.IsString());
const SizeType len1 = GetStringLength();
const SizeType len2 = rhs.GetStringLength();
if(len1 != len2) { return false; }
const Ch* const str1 = GetString();
const Ch* const str2 = rhs.GetString();
if(str1 == str2) { return true; } // fast path for constant string
return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
}
Data data_;
};
//! GenericValue with UTF8 encoding
typedef GenericValue<UTF8<> > Value;
///////////////////////////////////////////////////////////////////////////////
// GenericDocument
//! A document for parsing JSON text as DOM.
/*!
\note implements Handler concept
\tparam Encoding Encoding for both parsing and string storage.
\tparam Allocator Allocator for allocating memory for the DOM
\tparam StackAllocator Allocator for allocating memory for stack during parsing.
\warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
*/
template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR, typename StackAllocator = RAPIDJSON_DEFAULT_STACK_ALLOCATOR >
class GenericDocument : public GenericValue<Encoding, Allocator> {
public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter.
//! Constructor
/*! Creates an empty document of specified type.
\param type Mandatory type of object to create.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
}
//! Constructor
/*! Creates an empty document which type is Null.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
: ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)),
parseResult_(rhs.parseResult_)
{
rhs.allocator_ = 0;
rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult();
}
#endif
~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();
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
{
// The cast to ValueType is necessary here, because otherwise it would
// attempt to call GenericValue's templated assignment operator.
ValueType::operator=(std::forward<ValueType>(rhs));
// Calling the destructor here would prematurely call stack_'s destructor
Destroy();
allocator_ = rhs.allocator_;
ownAllocator_ = rhs.ownAllocator_;
stack_ = std::move(rhs.stack_);
parseResult_ = rhs.parseResult_;
rhs.allocator_ = 0;
rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult();
return *this;
}
#endif
//! Exchange the contents of this document with those of another.
/*!
\param rhs Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}
// Allow Swap with ValueType.
// Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.
using ValueType::Swap;
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Populate this document by a generator which produces SAX events.
/*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
\param g Generator functor which sends SAX events to the parameter.
\return The document itself for fluent API.
*/
template <typename Generator>
GenericDocument& Populate(Generator& g) {
ClearStackOnExit scope(*this);
if (g(*this)) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
}
return *this;
}
//!@name Parse from stream
//!@{
//! Parse JSON text from an input stream (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam SourceEncoding Encoding of input stream
\tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
ClearStackOnExit scope(*this);
parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
}
return *this;
}
//! Parse JSON text from an input stream
/*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags, typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
return ParseStream<parseFlags, Encoding, InputStream>(is);
}
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
/*! \tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed.
\return The document itself for fluent API.
*/
template <typename InputStream>
GenericDocument& ParseStream(InputStream& is) {
return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
}
//!@}
//!@name Parse in-place from mutable string
//!@{
//! Parse JSON text from a mutable string
/*! \tparam parseFlags Combination of \ref ParseFlag.
\param str Mutable zero-terminated string to be parsed.
\return The document itself for fluent API.
*/
template <unsigned parseFlags>
GenericDocument& ParseInsitu(Ch* str) {
GenericInsituStringStream<Encoding> s(str);
return ParseStream<parseFlags | kParseInsituFlag>(s);
}
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
/*! \param str Mutable zero-terminated string to be parsed.
\return The document itself for fluent API.
*/
GenericDocument& ParseInsitu(Ch* str) {
return ParseInsitu<kParseDefaultFlags>(str);
}
//!@}
//!@name Parse from read-only string
//!@{
//! Parse JSON text from a read-only string (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\tparam SourceEncoding Transcoding from input Encoding
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<SourceEncoding> s(str);
return ParseStream<parseFlags, SourceEncoding>(s);
}
//! Parse JSON text from a read-only string
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\param str Read-only zero-terminated string to be parsed.
*/
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
return Parse<parseFlags, Encoding>(str);
}
//! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
/*! \param str Read-only zero-terminated string to be parsed.
*/
GenericDocument& Parse(const Ch* str) {
return Parse<kParseDefaultFlags>(str);
}
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
ParseStream<parseFlags, SourceEncoding>(is);
return *this;
}
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<parseFlags, Encoding>(str, length);
}
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<kParseDefaultFlags>(str, length);
}
#if RAPIDJSON_HAS_STDSTRING
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
// c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
return Parse<parseFlags, SourceEncoding>(str.c_str());
}
template <unsigned parseFlags>
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<parseFlags, Encoding>(str.c_str());
}
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<kParseDefaultFlags>(str);
}
#endif // RAPIDJSON_HAS_STDSTRING
//!@}
//!@name Handling parse errors
//!@{
//! Whether a parse error has occurred in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing.
ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return parseResult_.Offset(); }
//! Implicit conversion to get the last parse result
#ifndef __clang // -Wdocumentation
/*! \return \ref ParseResult of the last parse operation
\code
Document doc;
ParseResult ok = doc.Parse(json);
if (!ok)
printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
\endcode
*/
#endif
operator ParseResult() const { return parseResult_; }
//!@}
//! Get the allocator of this document.
Allocator& GetAllocator() {
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
//! Get the capacity of stack in bytes.
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
private:
// clear stack on any exit from ParseStream, e.g. due to exception
struct ClearStackOnExit {
explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
~ClearStackOnExit() { d_.ClearStack(); }
private:
ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&);
GenericDocument& d_;
};
// callers of the following private Handler functions
// template <typename,typename,typename> friend class GenericReader; // for parsing
template <typename, typename> friend class GenericValue; // for deep copying
public:
// Implementation of Handler
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
bool RawNumber(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
else
new (stack_.template Push<ValueType>()) ValueType(str, length);
return true;
}
bool String(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
else
new (stack_.template Push<ValueType>()) ValueType(str, length);
return true;
}
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
bool EndObject(SizeType memberCount) {
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
return true;
}
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
bool EndArray(SizeType elementCount) {
ValueType* elements = stack_.template Pop<ValueType>(elementCount);
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
return true;
}
private:
//! Prohibit copying
GenericDocument(const GenericDocument&);
//! Prohibit assignment
GenericDocument& operator=(const GenericDocument&);
void ClearStack() {
if (Allocator::kNeedFree)
while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
(stack_.template Pop<ValueType>(1))->~ValueType();
else
stack_.Clear();
stack_.ShrinkToFit();
}
void Destroy() {
RAPIDJSON_DELETE(ownAllocator_);
}
static const size_t kDefaultStackCapacity = 1024;
Allocator* allocator_;
Allocator* ownAllocator_;
internal::Stack<StackAllocator> stack_;
ParseResult parseResult_;
};
//! GenericDocument with UTF8 encoding
typedef GenericDocument<UTF8<> > Document;
//! Helper class for accessing Value of array type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetArray().
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericArray {
public:
typedef GenericArray<true, ValueT> ConstArray;
typedef GenericArray<false, ValueT> Array;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef ValueType* ValueIterator; // This may be const or non-const iterator
typedef const ValueT* ConstValueIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
template <typename, typename>
friend class GenericValue;
GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
~GenericArray() {}
operator ValueType&() const { return value_; }
SizeType Size() const { return value_.Size(); }
SizeType Capacity() const { return value_.Capacity(); }
bool Empty() const { return value_.Empty(); }
void Clear() const { value_.Clear(); }
ValueType& operator[](SizeType index) const { return value_[index]; }
ValueIterator Begin() const { return value_.Begin(); }
ValueIterator End() const { return value_.End(); }
GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
GenericArray PopBack() const { value_.PopBack(); return *this; }
ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
ValueIterator begin() const { return value_.Begin(); }
ValueIterator end() const { return value_.End(); }
#endif
private:
GenericArray();
GenericArray(ValueType& value) : value_(value) {}
ValueType& value_;
};
//! Helper class for accessing Value of object type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetObject().
In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericObject {
public:
typedef GenericObject<true, ValueT> ConstObject;
typedef GenericObject<false, ValueT> Object;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
typedef typename ValueType::EncodingType EncodingType;
typedef typename ValueType::Ch Ch;
template <typename, typename>
friend class GenericValue;
GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
~GenericObject() {}
operator ValueType&() const { return value_; }
SizeType MemberCount() const { return value_.MemberCount(); }
SizeType MemberCapacity() const { return value_.MemberCapacity(); }
bool ObjectEmpty() const { return value_.ObjectEmpty(); }
template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
#if RAPIDJSON_HAS_STDSTRING
ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
#endif
MemberIterator MemberBegin() const { return value_.MemberBegin(); }
MemberIterator MemberEnd() const { return value_.MemberEnd(); }
GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }
bool HasMember(const Ch* name) const { return value_.HasMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
#endif
template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING
MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
#endif
GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#if RAPIDJSON_HAS_STDSTRING
GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
void RemoveAllMembers() { value_.RemoveAllMembers(); }
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
#endif
template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
#endif
template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
MemberIterator begin() const { return value_.MemberBegin(); }
MemberIterator end() const { return value_.MemberEnd(); }
#endif
private:
GenericObject();
GenericObject(ValueType& value) : value_(value) {}
ValueType& value_;
};
RAPIDJSON_NAMESPACE_END
RAPIDJSON_DIAG_POP
#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
#pragma pop_macro("GetObject")
#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
#endif
#endif // RAPIDJSON_DOCUMENT_H_