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
3044 lines
131 KiB
C++
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_
|