Compare commits

...

763 Commits

Author SHA1 Message Date
Mikhail Khachayants
24b5e7a8b2 Fix out of bounds read with kParseValidateEncodingFlag 2025-02-05 21:28:08 +08:00
Aikawa Yataro
b1c0c2843f CMakeLists: include path fix + compatibility. 2025-02-05 21:25:33 +08:00
Mikhail Khachayants
d621dc9e9c Fix parsing 0.184467440737095516159 with kParseFullPrecisionFlag 2024-12-18 19:30:59 +08:00
SilverPlate3
58c6938b73 Guard against max being macros in schema.h
Similar to:
Issue - https://github.com/Tencent/rapidjson/issues/1033
Solution - 6e38649ec6

Fix std::numeric_limits::max() compilation confusion on Windows
2024-12-10 17:21:10 +08:00
SilverPlate3
9b5cad1649 Cpp version depended if constexpr schema.h
Fix windows compile warning C4127
2024-12-10 17:19:59 +08:00
SilverPlate3
535636aeae Cpp depended if constexpr pointer.h
Fix windows compile warning C4127
2024-12-10 17:19:59 +08:00
Christian Fersch
ebd87cb468 Increase CMake minimum version to 3.5 (fixes #2159) 2024-12-02 19:40:10 +08:00
RedContritio
858451e5b7 Fix endif condition to match NOT MSVC and VALGRIND_FOUND. 2024-10-07 20:17:31 +08:00
Dmitriy Tretyakov
815e6e7e7e add test for sso optimized string 2024-09-24 17:14:47 +08:00
Dmitriy Tretyakov
805d7ed5df Fix issue 2307
In case sso use memmove to avoid memory overlapping issues
2024-09-24 17:14:47 +08:00
Eyizoha
7c73dd7de7 Fix bug when parsing NaN, Inf with fraction or exponent parts (fixes #2299)
This patch fixes the issue where parsing NaN or Inf values with
fractional or exponent parts would return incorrect results
(e.g., "NaN.2e2" would be parsed as 20).
Before this patch, the parser would continue to process the fractional
and exponent parts even after successfully parsing a valid NaN or Inf,
which could lead to parsing errors. This patch adds a check for such
cases to skips the parsing of the fractional and exponent parts after
completing the NaN and Inf parsing.
2024-08-16 20:24:45 +08:00
Sergey Fedorov
ab1842a2da rapidjson.h: add forgotten ppc64 case 2024-04-09 17:58:25 +08:00
Brian Rogers
5ec44fb920 Add RAPIDJSON_BUILD_CXX20 option
The travis/appveyor files are updated to reference this option, but it is
not yet enabled in any of the build configurations.
2024-03-08 10:18:11 +08:00
Gilles Vollant
676d99db96 fix Visual Studio 2022 (using /std:c++20) warning warning C5232: in C++20 this comparison calls ... recursively 2024-03-08 10:17:06 +08:00
Richard W.M. Jones
68afb49287 tests: Only run valgrind tests if valgrind was found
valgrind is not present on all architectures (eg riscv64) and might
not be installed even on supported architectures.

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
2024-03-07 14:41:57 +08:00
Dylan Burr
3f73edae00 Fix static_cast in regex.h
In the constructor for GenericRegexSearch, there was an issue with a
static_cast casting the result of the Malloc call. The issue was that
the stateSet_ member is of type uint32_t*, and there was an attempt to
assign an unsigned* to it. On some systems, uint32_t is not equivalent
to unsigned, thus yielding a compile error for assigning pointers of
different type.
Change-Id: I5b5036100305510b83cc4893b784a2dc9f3e4849
2024-02-09 21:47:20 +08:00
Esther Wang
5a74efa8c7 Fix comparision of two doubles
One of multipleOf test failed because most floating-point numbers end
up being slightly imprecise. And, the check of multipleOf with two
double numbers using the dividend (a) and the result of multiplying
the multiple after rounding down by the divisor (floor(|a|/|b|)*b) to
compare.

Change to using std::numeric_limits::epsilon to check the error of
the division result.
2024-02-09 19:29:03 +08:00
Bryant Ferguson
060a09a1c5 Fix schema regex preprocessor include logic 2024-02-09 19:28:14 +08:00
Esther Wang
6089180ecb Use correct format for printf
Change the printf format from '%d' to '%u', matching the type of the
arguments.
2023-12-06 19:08:30 +08:00
Aikawa Yataro
f9d53419e9 Add Hasher tests for objects where key eq value 2023-09-28 16:06:09 +01:00
Aikawa Yataro
6f79698b35 Fix swapped high and low offset basis values 2023-09-28 16:06:09 +01:00
Aikawa Yataro
eee82cb078 Fix object hashing in schema 2023-09-28 16:06:09 +01:00
Jeroen Doggen
b4a6da3e63 unit tests for 'Stringify NaN, Inf as null' 2023-09-21 18:42:43 +01:00
Jeroen Doggen
e7b6e5a208 Fix: 'Stringify NaN, Inf as null'
The code path where 'null' is written was never reached when 'writeFlags == kWriteNanAndInfNullFlag'
2023-09-21 18:42:43 +01:00
Albert Hung (Embedded)
476ffa2fd2 Rename to fix allocator shadowing
The identifier 'allocator' in the RapidJSON StdAllocator class declaration shadows the identifier 'allocator' in the
std::allocator class. To fix this, rename the 'allocator'
identifier in the StdAllocator class declaration to a different name.
2023-08-21 11:02:43 +08:00
Albert Hung
5e17dbed34 Eliminate old style cast warning
Use static_cast to replace old style cast.

Change-Id: I30e659c8f2aadc02750555b0f041bfd2e1c8004a
2023-08-17 16:55:04 +08:00
Albert Hung
956063dbc1 Fixing printf format warning
In the BigNestedObject test case of valuetest.c, a dynamically
defined format is used that depends on the signedness of the
'SizeType' type. This allows the 'sprintf' function to use the correct
format for 'SizeType'.

Change-Id: I97222b699bda6c0ccfc9abbc5977c79e16605f2c
2023-08-15 17:03:49 +08:00
Milo Yip
30f54566ad
Merge pull request #1901 from JackBoosY/master
Use modern cmake function export to generate target
2023-08-14 18:08:52 +08:00
Albert Hung
516d047394 Remove empty cross-reference in comment
Remove useless comment block which owns a '\see' cross-reference, but
doesn't provide any data after it. This empty cross-reference triggers
a compiler warning.

Change-Id: I5c01d57579e5efedcb4bf17b80b06db313a61ab3
2023-08-14 18:08:33 +08:00
miloyip
52dd947090 Merge branch 'master' into pr/1901 2023-08-14 11:00:53 +01:00
Jihadist
a95e013b97 Stringify NaN, Inf as null if needs 2023-07-17 11:02:35 +08:00
Leonard Chan
973dc9c06d Avoid ptrdiff between pointers to different allocations
When using running both Undefined Behavior Sanitizer (UBSan) and
Hardware-Assisted Address Sanitizer (HWASan) on Fuchsia, ubsan
complained about a pointer overflow when computing the new token->name pointer.
This happens because the initial pointer diff takes the offset between
two allocations with different tags, so the arithmetic results in a very
large diff that gets added to the original token->name ptr which
overflows.

Any arithmetic between pointers to two allocations is unspecified
behavior, so hwasan+ubsan is catching a bug here. It looks like
rapidjson is just attempting to update the name pointers to strings
copied into the new nameBuffer_ via this arithmetic, but since these
strings and the tokens are in the same buffer, the offset between them
should be the same. For each token we can just get this offset and
adjust the new name pointers accordingly which avoids the bad arithmetic.
2023-05-17 16:16:27 +08:00
Albert Hung
2a1f586ba6 Check for __GNUC__ definition
Wrap code checking against __GNUC__ to ensure it is defined. This can cause errors with compilers which do not define this preprocessor value.
2023-05-10 12:41:04 +08:00
Albert Hung
0e88d5e404 Eliminate missing prototypes warning 2023-05-09 21:28:14 +08:00
Flaviu_
949c771b03 Resolve conflict with Windows header about max macro 2023-04-07 18:45:27 +08:00
Sergey Fedorov
083f359f5c CMakeLists: fix optflags for ppc 2023-03-06 14:36:52 +08:00
supperpiccle
012be85287 Use passed in allocator. 2023-01-12 14:24:04 +08:00
Steve Hanson
1ce516e50b Suppress uritest 2023-01-05 20:34:07 +08:00
Steve Hanson
778dc8b03e fix #1 2023-01-05 20:34:07 +08:00
Tana0910
76281ff388 fix a typo in error.h: literial -> literal 2023-01-04 17:45:39 +08:00
Kent Ross
a98e99992b do not define operator!= in C++20
A change to the semantics of equality operator rewriting in C++20 (P2468R2: The Equality Operator You Are Looking For) means that operator== may not be rewritten with reversed operands if operator!= is also defined. Since operator!= can normally be synthesized from operator== regardless in this language standard, we can and should avoid defining those when the new language semantics are available.

This fixes the compilation of tests (and probably consuming code) in C++20 onwards for compilers that implement this new semantic, including recent nightly builds of clang-16.

Reference: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2468r2.html
2022-12-19 05:30:49 +08:00
Steve Hanson
b08672d469 review comment updates 2022-12-19 05:30:00 +08:00
Steve Hanson
55eca66f39 code & tests for openapi 2.0 & 3.0 suppprt 2022-12-19 05:30:00 +08:00
Steve Hanson
80b6d1c834 small corrections for schema.h 2022-12-01 00:42:44 +08:00
Steve Hanson
97fd830175 attempt to fix SEH 2022-12-01 00:42:44 +08:00
Steve Hanson
7cad78e236 tidy up after merge from master 2022-12-01 00:42:44 +08:00
Steve Hanson
794248ee62 fix build break 2022-12-01 00:42:44 +08:00
Steve Hanson
2d87923e91 remove unnecessary templating from schema tests 2022-12-01 00:42:44 +08:00
Steve Hanson
aa1f22251f correct address.json so tests pass 2022-12-01 00:42:44 +08:00
Steve Hanson
ecb8d9e3a0 add dump of unexpected schema errors in schematest.cpp 2022-12-01 00:42:44 +08:00
Steve Hanson
89f6717f0b corrections 2022-12-01 00:42:44 +08:00
Steve Hanson
338d8defdb initial 2022-12-01 00:42:44 +08:00
jwillcox-telework
06d58b9e84 Update dtoa.h
Fixed DigitGen to use proper suffix for uint64_t numeric types. Change from U suffix to ULL suffix.

On SLED 11.0 compiler, code would not compile.

cd rapidjson-master
g++ -Wall -m32 -ggdb -Iinclude -O1 ./example/simpledom/simpledom.cpp -o simpledom 2>&1 | tee out.txt
2022-08-23 10:52:40 +08:00
jwillcox-telework
22a62fcc2c Update allocators.h
Fixing compiler error on older compilers, such as SLED 11.0.

cd rapidjson-master
g++ -Wall -m32 -ggdb -Iinclude -O1 ./example/simpledom/simpledom.cpp -o simpledom 2>&1 | tee out.txt

Changed SIZE_MAX to std::numeric_limits<size_t>::max() in code to get rid of SIZE_MAX error.
2022-08-23 10:52:40 +08:00
Tim Gates
27c3a8dc0e docs: fix simple typo, perecent -> percent
There is a small typo in test/unittest/pointertest.cpp.

Should read `percent` rather than `perecent`.

Signed-off-by: Tim Gates <tim.gates@iress.com>
2022-07-20 21:53:57 +08:00
Kent Ross
232389d4f1 delete unused variable 2022-05-24 10:03:13 +08:00
Kent Ross
64faab2e92 gate definition of symmetric equality operators on impl, not lib
These operators call themselves recursively if C++20 semantics are present in the compiler, regardless of standard library support for the operator; therefore the test should be on __cpp_impl_three_way_comparison, not __cpp_lib_[...].

This fixes the Value.EqualtoOperator test when the language standard is set to C++20 and the standard library does not yet define the library support macro.
2022-05-24 10:03:13 +08:00
Johnny Shaw
719304b113 fixes for natvis 2022-05-21 15:02:39 +08:00
Johnny Shaw
dd3f730d74 Make schema dtor robust against exceptions 2022-05-21 09:35:41 +08:00
Peter Kasting
781a4e667d Try to fix MSVC build. 2022-05-19 11:55:17 +08:00
Peter Kasting
88f8ddd70c Include conceptual change from PR 2001. 2022-05-19 11:55:17 +08:00
Peter Kasting
4695953567 Avoid exit-time destructors.
operator[]() was recently changed to use the existing code in order to
correctly align the returned pointer; however this broke
-Wexit-time-destructors.  Change to a method that is still correctly
aligned but does not generate a destructor.
2022-05-19 11:55:17 +08:00
Peter Kasting
0390b1ad57 Avoid exit-time destructors.
operator[]() was recently changed to use the existing code in order to
correctly align the returned pointer; however this broke
-Wexit-time-destructors.  Change to a method that is still correctly
aligned but does not generate a destructor.
2022-05-19 11:55:17 +08:00
Tom Briden
2b2c804500 encdedstreamtest: fix use-after-free compile error with gcc-12 2022-05-16 10:23:11 +08:00
Tom Briden
1f59c69cd1 valuetest: fix potential write of terminating nul past the end of the destination
Fixes 2 compile errors with gcc-12, eg:

tesunittest/valuetest.cpp:1516:30: error: 'sprintf' may write a terminating nul past the end of the destination [-Werror=format-overflow=]
test/unittest/valuetest.cpp:1516:20: note: 'sprintf' output between 2 and 11 bytes into a destination of size 10
2022-05-16 10:23:11 +08:00
Jack·Boos·Yu
3445e155e9
Merge branch 'master' into master 2022-05-05 08:03:42 +00:00
Milo Yip
fcb23c2dbf
Merge pull request #2008 from agate-pris/access-to-allocator-types
Access to allocator types
2022-04-06 12:28:13 +08:00
Milo Yip
bdc49ad80a
Merge pull request #2014 from lazydroid/dev/lenik/fix_shadowed_variables
fix shadowed variable
2022-04-06 12:27:10 +08:00
Leonid Terenin
6b500986c4 fix shadowed variable, take 2 2022-04-06 10:42:40 +09:00
Leonid Terenin
3988c5e25e fix shadowed variable 2022-04-06 09:58:56 +09:00
agate-pris
386d31ab69 Allow access to the template parameter StackAllocator in the GenericDocument
Add the typedef declaration `StackAllocatorType` to the class template
`GenericDocument`. This allows the user to access the template parameter
`StackAllocator`.
2022-03-18 19:34:11 +09:00
agate-pris
79d7a448e9 Allow the macro RAPIDJSON_DEFAULT_STACK_ALLOCATOR to be used in any namespace
RAPIDJSON_DEFAULT_STACK_ALLOCATOR uses names in the namespace
`RAPIDJSON_NAMESPACE`. Replace this with a name starting in the global
namespace.
2022-03-18 19:32:01 +09:00
agate-pris
9965ab37f6 Allow the macro RAPIDJSON_DEFAULT_ALLOCATOR to be used in any namespace
`RAPIDJSON_DEFAULT_ALLOCATOR` uses names in the namespace
`RAPIDJSON_NAMESPACE`. Replace this with a name starting in the global
namespace.
2022-03-18 19:22:19 +09:00
Milo Yip
8261c1ddf4
Merge pull request #1969 from MalcolmTyrrell/MalcolmTyrrell/sanitizeSchemaCode
Sanitize the code in schema.h
2022-03-09 12:15:45 +08:00
Milo Yip
0d78b1ce93
Merge pull request #1989 from adamcalhoon/really-fix-placement-new-alignment
Fix the alignment of placement new buffer for GenericValue.
2022-03-08 17:09:47 +08:00
Adam Calhoon
1dff2abff7 Fix the alignment of placement new buffer for GenericValue.
When using operator[] on a GenericValue type clang-tidy complains,
appropriately, about the alignment of the buffer used for placement-new
of the "dummy" GenericValue.
2022-02-08 22:29:15 -05:00
Milo Yip
e4bde97744
Merge pull request #1988 from Tencent/revert-1987-fix-placement-new-alignment
Revert "Fix the alignment of placement new buffer for GenericValue."
2022-02-09 10:48:22 +08:00
Milo Yip
88bbd87ddd
Revert "Fix the alignment of placement new buffer for GenericValue." 2022-02-09 10:48:05 +08:00
Milo Yip
bf8ca5da88
Merge pull request #1987 from adamcalhoon/fix-placement-new-alignment
Fix the alignment of placement new buffer for GenericValue.
2022-02-09 10:47:25 +08:00
Adam Calhoon
5b242b6b2d Fix the alignment of placement new buffer for GenericValue.
When using operator[] on a GenericValue type clang-tidy complains,
appropriately, about the alignment of the buffer used for placement-new
of the "dummy" GenericValue.
2022-02-08 12:03:02 -05:00
Milo Yip
fd3dc29a5c
Merge pull request #1944 from ilelann/patch-1
Support CMake none targets
2021-11-24 23:11:45 +08:00
Malcolm Tyrrell
53602ec6bb Sanitize the code in schema.h 2021-11-17 09:31:22 +00:00
Milo Yip
0d4517f15a
Merge pull request #1961 from jedwardsol/issue1960_arm64ec_intrinsic
use softintrin on arm64ec
2021-10-31 11:07:57 +08:00
jedwards
060c348ea0 use softintrin on arm64ec 2021-10-29 15:31:10 -07:00
Milo Yip
4d6cb08189
Merge pull request #1949 from ardb-uk/master
Resolving issue #1948
2021-10-15 14:34:41 +08:00
ardb-uk
033bef3c6c
Merge pull request #1 from ardb-uk/ardb-uk-patch-1
Resolve issue 1948
2021-10-12 16:33:03 +01:00
ardb-uk
befba39afc
Merge pull request #2 from ardb-uk/ardb-uk-patch-1-1
Resolved issue #1948
2021-10-12 16:32:28 +01:00
ardb-uk
4bbaf28ffc
Add files via upload 2021-10-12 16:23:44 +01:00
ardb-uk
14f1e37f85
Resolve issue 1948
Correct instances of >> as they failed compilation.
2021-10-12 16:22:22 +01:00
Ivan Le Lann
e6736d1baa
Support CMake none targets
When trying to import rapidjson with for exemple : 
fetchcontent_declare(rapidjson GIT_REPOSITORY https://github.com/Tencent/rapidjson.git)

if your CMake/Clang is "bare metal", exemple given : 

set(CMAKE_SYSTEM_NAME none)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_C_COMPILER_TARGET x86_64-elf-none)
set(CMAKE_CXX_COMPILER_TARGET x86_64-elf-none)

CMake fails to process CMakeLists.txt because of the switch on UNIX/CYGWIN/WIN32 for install directory.

Error is: 

CMake Error at cmake-build-debug-clang/_deps/rapidjson-src/CMakeLists.txt:244 (INSTALL):
  INSTALL FILES given no DESTINATION!
2021-10-02 15:26:17 +02:00
Milo Yip
2e8f5d897d
Merge pull request #1940 from smhdfdl/issue-1924
Issue 1924 - stop erroneous compiler warnings
2021-09-24 18:05:03 +08:00
Steve Hanson
9ea3f45dbd fix the warning 2021-09-24 08:51:03 +01:00
Milo Yip
b9ae2499ef
Merge pull request #1941 from DiamondI/patch-1
typo on documentation dom.zh-cn.md: "己于" -> "已于"
2021-09-24 11:47:04 +08:00
Andrew
553a3ea31f
typo on documentation dom.zh-cn.md: "己于" -> "已于" 2021-09-24 10:57:46 +08:00
Steve Hanson
864e44aef8 Merge branch 'master' of https://github.com/Tencent/rapidjson 2021-09-23 14:33:30 +01:00
Milo Yip
00dbcf2c6e
Merge pull request #1926 from Kyrega/master
Fix RawNumber for characters with sizeof(Ch) > sizeof(char)
2021-08-13 12:25:41 +08:00
Kyrega
22ee8b07c8 Correct WIStreamWrapper 2021-08-10 17:39:04 +02:00
Kyrega
a3d52c75b7 No default template parameter for older compilers 2021-08-10 17:38:41 +02:00
Kyrega
19b55c9049 No default template parameter for older compilers 2021-08-10 17:38:23 +02:00
Kyrega
128b1031b0 Use rapidjson internal::SelectIf 2021-08-10 17:38:09 +02:00
Kyrega
8710d7e989 Do not depend on c++11 conditional 2021-08-10 17:37:35 +02:00
Kyrega
e0512e0944 Using unsigned for WIStreamWrapper 2021-08-10 17:36:31 +02:00
Kyrega
7fac34f7bb Added typename 2021-08-10 17:35:49 +02:00
Kyrega
b952a592a4 Fix RawNumber for longer char types 2021-08-10 17:35:07 +02:00
Milo Yip
28c59ab4c6
Merge pull request #1922 from jack-perisich/grisu2_precision
Fix small errors in dtoa output for certain doubles
2021-08-10 22:16:46 +08:00
jack_perisich
bb06211088 Fix small errors in dtoa output for certain doubles 2021-07-27 19:50:51 -04:00
Steve Hanson
7ee918fc8f Merge branch 'master' of https://github.com/Tencent/rapidjson 2021-07-09 10:47:18 +01:00
Milo Yip
48fbd8cd20
Merge pull request #1848 from smhdfdl/id-and-ref
Fix issue 1843 - support Id keyword
2021-07-09 10:57:40 +08:00
Steve Hanson
8d16abd980 Uri Parse improvements 2021-06-30 17:09:52 +01:00
Milo Yip
b557259f88
Merge pull request #1904 from Tencent/issue1899_pointerappend
Fix Pointer::Append() crash for custom allocator on Windows
2021-06-14 22:49:09 +08:00
Steve Hanson
a21cf9f7b8 equiv fix for issue 1899 2021-06-14 11:35:00 +01:00
Milo Yip
8c29a7b493 Fix Pointer::Append() crash for custom allocator on Windows
Fix #1899
2021-06-11 11:49:14 +08:00
Steve Hanson
12b88efa6f fix coverage again 2021-06-09 18:11:04 +01:00
Steve Hanson
f6ebcb2008 fix Uri.Match optional arg 2021-06-09 16:38:40 +01:00
Steve Hanson
3df804c128 fix coverage, unit test allocators and equality 2021-06-09 10:31:09 +01:00
Steve Hanson
18ab3b16bc remove temp debug statements 2021-06-08 17:11:42 +01:00
Steve Hanson
6d253c160d remove compiler warning 2021-06-08 15:31:25 +01:00
Steve Hanson
28bcbd3f35 make std::string optional 2021-06-08 10:53:10 +01:00
JackBoosY
f4be0ada85 Use modern cmake function export to generate target 2021-06-07 02:13:23 -07:00
Steve Hanson
494447b731 remove copyright & debug statements 2021-05-21 15:55:11 +01:00
Steve Hanson
6e58a53f44 fix coverage 2021-05-20 17:44:34 +01:00
Steve Hanson
3987d82f41 Merge branch 'master' of https://github.com/Tencent/rapidjson into id-and-ref 2021-05-20 12:20:12 +01:00
Steve Hanson
9c1002f94d rge branch 'master' of https://github.com/Tencent/rapidjson 2021-05-20 12:18:46 +01:00
Milo Yip
17aa824c92
Merge pull request #1885 from saurabhchardereal/master
Improve documentation
2021-05-07 17:00:48 +08:00
Saurabh Charde
cd737fb545
Improve documentation
Signed-off-by: Saurabh Charde <saurabhchardereal@gmail.com>
2021-05-07 14:13:33 +05:30
Milo Yip
25fa7a119d
Merge pull request #1883 from nkolotov/fix/issues/1882
Fixed -Wshadow warning.
2021-05-06 09:54:52 +08:00
N. Kolotov
3aa8d04b74 Fixed -Wshadow warning. 2021-05-03 01:56:41 +03:00
Milo Yip
e0f68a4356
Merge pull request #1877 from hendrikmuhs/windows-GetObject-conflict-#1418
add a workaround for GetObject macro defined by windows.h
2021-04-20 10:02:53 +08:00
Hendrik Muhs
3cdfde14d6 replace auto with concrete type 2021-04-19 13:15:11 -07:00
Hendrik Muhs
d179facf90 don't let the GetObject macro rewrite the GetObject method, add a GetObj alias 2021-04-19 12:29:11 -07:00
Hendrik Muhs
3168d7c343 add a test that provokes a compile time error on windows 2021-04-18 18:06:35 +02:00
Milo Yip
47b837e14a
Merge pull request #1485 from ylavic/MemberMap
Object members stored in std::multimap
2021-04-08 10:06:28 +08:00
ylavic
be4a5a9087 Turn some Tests to RAPIDJSON_USE_MEMBERSMAP in CI. 2021-04-07 18:22:46 +02:00
ylavic
fc08f4f61b Tests for Members in std::multimap. 2021-04-07 18:22:46 +02:00
ylavic
71f0fa7eb3 Set RAPIDJSON_USE_MEMBERSMAP to use a (std::multi)map for object members.
When RAPIDJSON_USE_MEMBERSMAP is defined, an object Value will store
its members in an (re)allocated array of Members like before, but also
in an std::multimap<GenericValue::Data,SizeType> where the key and value
reference the corresponding Member by its Data and index in the array,
respectively, and in a relocatable manner.

The layout of the members map/array is now:
 {multimap*}<>{capacity}<>{Member[capacity]}<>{multimap::iterator[capacity]}
where <> stands for the RAPIDJSON_ALIGN-ment of each part, if needed.

This layout needs to be reallocated when the current capacity is
exhausted, which requires to take care of the multimap and its iterators
explicitely. The multimap is allocated separately and only its pointer is
saved in this layout, so it can easily be restored in its new position.
As for the old/alive iterators, they must move to their new offset according
to the new capacity.

With this in place, it's immediate to get the multimap::iterator from a
MemberIterator and vice versa, thus the same complexity applies for the
operations with MemberIterator or MapIterator.

For FindMember() and RemoveMember(), the complexity drops from O(n) to
the multimap/rbtree's O(log n).
For EraseMember() it drops from O(n-m) to O((log n)-m), m representing
the move/copy of the trailing members.
For AddMember() though, the complexity grows from O(1) to O(log n) due to
the insertion in the multimap too.

Consequently parsing will be slower, up to ~20% measured in perftests on
my laptop (since it's mainly composed of insertions). But later work on
the Document (usually the goal of parsing...) will be much faster; the
new DocumentFind perftest included in this commit is 8 times faster with
RAPIDJSON_USE_MEMBERSMAP (still on my laptop). Overall the tests are 4%
slower (mainly composed of parsing), and notably 15% slower for schemas
parsing/validation (which supposedly comes from the larger JSON files
parsing, still). As a side note, when RAPIDJSON_USE_MEMBERSMAP is not
defined, this commit does nothing (same results for perftest with regard
to previous versions).

Finally, the multimap is allocated and constructed using StdAllocator,
so they will use the same Allocator than for any other Value allocation,
and thus will benefit from the same performance/safety/security/whatever
provided by the user given Allocator.
2021-04-07 18:22:46 +02:00
Milo Yip
7d801bbe45
Merge pull request #1503 from ylavic/sub_value_assignment
Fix (Sub-)Value assignment
2021-04-07 17:52:51 +08:00
Milo Yip
03676c9bf5
Merge pull request #1870 from ylavic/allocators_rvalues
Add rvalue copy and assignment to MemoryPoolAllocator and StdAllocator.
2021-04-07 17:39:26 +08:00
ylavic
aa0675ffd7 Try some tests with -D_GLIBCXX_DEBUG and coverage with -O0. 2021-04-04 12:51:47 +02:00
ylavic
5c764d9a81 Tests for Allocators copy by rvalue reference. 2021-04-04 12:51:47 +02:00
ylavic
683010b02d Add rvalue copy and assignment to MemoryPoolAllocator and StdAllocator. 2021-04-04 12:51:47 +02:00
ylavic
117276c413 Fix would-crash tests if the default allocator used were kNeedFree.
The allocator cannot be destroyed before the Document, otherwise the
Value destructor double frees.
2021-04-02 21:09:20 +02:00
Milo Yip
49aa0fc15d
Merge pull request #1868 from ylavic/cpp17_in_ci
Handle C++17 (and C++11 with MSVC) in CI.
2021-04-01 14:40:55 +08:00
ylavic
a8bd931766 Tests for C++17 with VS 2019. 2021-03-30 15:58:17 +02:00
ylavic
6bed9b266f Don't define StdAllocator<void> from C++17. 2021-03-30 13:47:04 +02:00
ylavic
e336667b4a Handle C++17 (and C++11 with MSVC) in CI. 2021-03-30 10:12:36 +02:00
Milo Yip
b996a23714
Merge pull request #1866 from ylavic/std_allocator_traits
Make StdAllocator C++17-20 compatible.
2021-03-30 14:31:29 +08:00
ylavic
08cf9a56c0 Make StdAllocator C++17-20 compatible. 2021-03-29 11:32:33 +02:00
ylavic
02f42604bd Make StdAllocator C++17-20 compatible. 2021-03-28 23:48:14 +02:00
Milo Yip
cd5ee4dfe9
Merge pull request #1858 from ylavic/std_allocator
Provide StdAllocator, STL compatible, for use with standard types
2021-03-25 15:22:32 +08:00
miloyip
3d77d11e28 add traverse as pointer example 2021-03-24 16:51:12 +08:00
ylavic
2e6f761458 Tests for StdAllocator. 2021-03-16 01:03:04 +01:00
ylavic
49e4dd619f Provide StdAllocator, STL compatible, for use with STL types. 2021-03-16 01:03:04 +01:00
ylavic
50cb424c34 Test assignment from inner Value. 2021-03-15 23:57:42 +01:00
ylavic
c033292aea Safer GenericValue& operator=(GenericValue& rhs).
When rhs is a sub-Value of *this, destroying *this also destroys/frees
rhs, thus the following RawAssign(rhs) crashes.

Address this by saving/moving rhs to a temporary first, which clears rhs
and avoids its destruction with *this.

The crash can be reproduced in test Value.MergeDuplicateKey by using the
CrtAllocator instead of the default Document's MemoryPoolAllocator.
2021-03-15 23:57:42 +01:00
ylavic
d51dd2d0e9 RAPIDJSON_NOEXCEPT_ASSERT should assert regardless of RAPIDJSON_HAS_CXX11_NOEXCEPT. 2021-03-12 15:32:17 +01:00
ylavic
cdb2d4757d Provide RAPIDJSON_HAS_CXX11 and use it for RAPIDJSON_HAS_CXX11_RVALUE_REFS and RAPIDJSON_HAS_CXX11_NOEXCEPT. 2021-03-12 15:14:30 +01:00
Steve Hanson
bc026e3fb5 satisfy all compilers 3 2021-03-11 18:25:10 +00:00
Steve Hanson
24b9b7e276 satisfy all compilers 2 2021-03-11 18:16:24 +00:00
Steve Hanson
32722fa31d satisfy all compilers 2021-03-11 16:53:05 +00:00
Steve Hanson
8768b5b1d6 correct #defines in uri.h 2021-03-11 15:13:17 +00:00
Steve Hanson
6c9da69abf remove comma 2021-03-11 15:06:02 +00:00
Steve Hanson
6b57738e4a handle internal refs properly 2021-03-11 14:49:28 +00:00
miloyip
1c2c8e085a doc: fix incorrect template parameters in EncodedOutputStream example
Fix #1851
2021-03-02 11:15:31 +08:00
Steve Hanson
fe1a29ca69 fix platform-dependent compiler error with >> 2021-02-25 23:54:44 +00:00
Steve Hanson
ad73c032e7 fix compile errors 2021-02-25 22:51:35 +00:00
Steve Hanson
892f6e3fd3 fix bracket 2021-02-25 22:21:20 +00:00
Steve Hanson
cabc3d5aa1 merge 2021-02-25 22:12:05 +00:00
Steve Hanson
7698b3cd48 code and tests 2021-02-25 21:45:29 +00:00
Steve Hanson
dad85cab9d
Merge pull request #2 from smhdfdl/multiple-validation-failures-and-validation-messages
Multiple validation failures and validation messages
2021-02-25 21:01:50 +00:00
Milo Yip
b1a4d91a53
Merge pull request #1779 from pavel-pimenov/fix-1778-part-1
fix 1778  (part 1)
2021-02-23 10:23:34 +08:00
Milo Yip
8be64594f2
Merge pull request #1847 from stac47/fix_1846
Fix recursive operator== call in C++20 (#1846)
2021-02-23 10:21:11 +08:00
Laurent Stacul
24ebd51287 Fix recursive operator== call in C++20 (#1846) 2021-02-22 16:52:27 +00:00
Milo Yip
8bce684cda
Merge pull request #1844 from smhdfdl/multiple-validation-failures-and-validation-messages
After PR 1837, fix crash where simple type with sub-schema has a bad value
2021-02-22 00:01:56 +08:00
Steve Hanson
9bb81e20ff fix crash where simple type with sub-schema has a bad value 2021-02-12 17:36:55 +00:00
Milo Yip
13dfc96c9c
Merge pull request #1837 from smhdfdl/multiple-validation-failures-and-validation-messages
Fixes for issues #1835 & #1836 - Multiple validation failures and readable validation messages
2021-02-03 21:19:27 +08:00
Steve Hanson
167efb4fa0 work around issue 1089 2021-02-03 08:34:10 +00:00
Steve Hanson
28dc42d8d3 restore coverage 2021-01-29 19:20:01 +00:00
Steve Hanson
a3757456fe correct workaround for issue 1805 2021-01-29 16:43:12 +00:00
Steve Hanson
7fee368be3 Revert "revert perftest"
This reverts commit 221e8d5364d817f3ea89ec0e124e2fa68a696952.
2021-01-29 11:58:31 +00:00
Steve Hanson
221e8d5364 revert perftest 2021-01-29 11:38:33 +00:00
Steve Hanson
f89e75af75 remove C++ 11 std::string to_string() syntax 2021-01-29 11:08:01 +00:00
Steve Hanson
c491dd5213 remove C++ 11 enum syntax 2021-01-29 10:26:05 +00:00
Steve Hanson
6f3cccd6e1 remove debug std::cout, handle empty error object in example 2021-01-28 14:21:36 +00:00
Steve Hanson
05e7b33977 code and tests 2021-01-28 12:11:43 +00:00
Steve Hanson
5d17b24e53
Merge pull request #1 from Tencent/master
PR for commits 2021/01/12
2021-01-12 14:54:16 +00:00
Milo Yip
585042c02b
Merge pull request #1821 from slsyy/master
Add implicit conversion from Object and Array to Value (#1404)
2021-01-06 13:43:21 +08:00
Krystian Chmura
cbf62de55d Add implicit conversion from Object and Array to Value (#1404)
Allows resolution of JSON Pointer on Object and Array
2021-01-05 14:20:57 +01:00
Milo Yip
3cdd3c8370
Merge pull request #1817 from lukedan/lukedan_cpp20
Fix #1721
2020-12-28 10:32:35 +08:00
Xuanyi Zhou
5e50f27ed1 also initialize class member 2020-12-26 23:41:42 -05:00
Xuanyi Zhou
1e4f59d3ae add return statement & comment 2020-12-26 23:38:27 -05:00
Xuanyi Zhou
d742a030aa add body to private copy constructor & copy assignment 2020-12-26 23:27:43 -05:00
Xuanyi Zhou
3006926231 suppress enum bitwise operation warnings on msvc 2020-12-26 23:09:39 -05:00
Xuanyi Zhou
13f5ab4f44 fix schema test compile error 2020-12-26 22:58:13 -05:00
Milo Yip
56f215e5c3
Merge pull request #1568 from ericrannaud/ericrannaud/memberiterator-public
Make GenericMemberIterator::Iterator public again (RAPIDJSON_NOMEMBER…
2020-12-23 09:41:20 +08:00
Milo Yip
0ccdbf364c
Merge pull request #1786 from ssb22/master
Remove unnecessary wording from BSD license not needed for MIT license (fixes #528)
2020-10-13 09:54:06 +08:00
Silas S. Brown
b7734d97c0 Remove unnecessary wording from BSD license not needed for MIT license (fixes #528) 2020-10-09 10:04:27 +01:00
Pave Pimenov
3a65e2dd7f fix https://github.com/Tencent/rapidjson/issues/1778 (part 1) 2020-09-12 19:53:06 +03:00
Milo Yip
ce81bc9edf
Merge pull request #1760 from escherstair/fix_ce6_support
fix _BitScanReverse() usage for CE6
2020-08-07 10:12:21 +08:00
escherstair
5fbf8bf89c fix unit test 2020-08-06 15:55:42 +02:00
escherstair
7f559ec80a fix naive implementation for clzll() 2020-08-06 15:55:26 +02:00
escherstair
58e2964856 add unit test for clzll() 2020-08-06 14:57:39 +02:00
escherstair
aa5dd60865 fix naive version implementation 2020-08-04 14:39:19 +02:00
escherstair
91940e84b1 fallback to the naive version for CE6 2020-08-04 14:38:45 +02:00
escherstair
6364c8e5ab fix _BitScanReverse() usage for CE6 2020-08-04 10:01:44 +02:00
Milo Yip
f56928de85
Merge pull request #1744 from lklein53/improve-surrogate-handling
Improve surrogate handling (#1738)
2020-07-13 11:10:39 +08:00
Lars Klein
6694c996b9 Add test case for low surrogate handling 2020-07-04 14:48:55 +02:00
Lars Klein
ed73d7bdb4 Improve surrogate handling
Report a single low surrogate as kParseErrorStringUnicodeSurrogateInvalid.
2020-07-04 14:34:09 +02:00
Milo Yip
88bd956d66
Merge pull request #1453 from eidosmontreal/custom_malloc
Adding a single customization point that ensures all allocations within rapidjson can be performed with a custom memory allocator
2020-06-23 14:34:10 +08:00
Gaspard Petit
004e8e61a0 Merge branch 'master' into custom_malloc 2020-06-22 22:31:37 -04:00
Milo Yip
1a803826f1
Merge pull request #1720 from madeso/master
Fixes issue #1718
2020-05-19 00:25:35 +08:00
Gustav
ac0fc79c76 Fixes issue #1718 2020-05-18 14:06:39 +02:00
Milo Yip
8f4c021fa2
Merge pull request #1689 from g199209/master
Add CMake minimum version required.
2020-04-10 17:34:09 +08:00
Gao Mingfei
1ce28f454b Add CMake minimum version required.
Interface Libraries feature is not available before CMake 3.0

Signed-off-by: Gao Mingfei <mingfei.gao@ucloud.cn>
2020-04-10 14:50:51 +08:00
Matteo Settenvini
f376690822
Add a target to RapidJSONConfig.cmake.in (#1350)
This way, users can call target_link_libraries against the imported target, which is the recommended way of doing things.
2020-03-30 10:29:56 +08:00
Jun
234ff044f4
ci: upgrade distro to xenial and add arm64 test cases (#1662)
Start from xenial, Travis supports multiple CPU architectures.
To bump to this version allows expand test coverage for more
architectures.
See: https://docs.travis-ci.com/user/reference/overview/#virtualisation-environment-vs-operating-system
Add arm64 test cases to matrix.

Change-Id: If61e2d38223dad70b542d6ec0afcf4a433c9debf
Signed-off-by: Jun He <jun.he@arm.com>

Co-authored-by: Jun He <jun.he@arm.com>
2020-03-30 10:24:11 +08:00
ioannis-e
36481c30b3
Update Visual Studio Visualizer (#1665)
1. Determine the correct type of string based on encoding
2. Omit string pointer address
2020-03-30 10:22:52 +08:00
仓鼠
d4f03d0d04
Doc: Fix some typos. (#1675) 2020-03-30 10:21:37 +08:00
Nikolay
ebcbd04484
Three-way comparison for CLang 10 fix (#1679)
C++20 features must enable additional functionality, not to change interface completely
2020-03-30 10:20:35 +08:00
Romain Geissler @ Amadeus
2661a17c7e
Avoid warnings when using -std=c++20 and clang 10: use three way comparision for iterators when possible. (#1667)
/data/mwrep/res/osp/RapidJson/20-0-0-0/include/rapidjson/document.h:729:58: error: use of overloaded operator '!=' is ambiguous (with operand types 'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::MemberIterator' (aka 'rapidjson::GenericMemberIterator<false, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >') and 'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::MemberIterator')
                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
2020-03-20 13:39:48 +08:00
Jun
814bb27bf0
Replace RAPIDJSON_CLZLL with internal clzll (#1660)
RAPIDJSON_CLZLL is defined as macro of __builtin_clzll when
using gcc to compile. This introduces two issues:
1. in gcc __builtin_clzll returns int, not uint32_t.
2. __builtin_clzll return is undefined when input x is 0
See: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

This patch removes RAPIDJSON_CLZLL, merges __builtin_clzll to
internal clzll with input check and return value explicit cast.

Change-Id: Iac4b355dc5e5b4ed9b3f35a640b6b5537e76f22c
Signed-off-by: Jun He <jun.he@arm.com>

Co-authored-by: Jun He <jun.he@arm.com>
2020-03-11 15:11:25 +08:00
Milo Yip
563fe5bbbe
PrettyWriter constructor uninitialized member (#1654)
Fix #1653
2020-03-05 14:13:11 +08:00
Milo Yip
2bed293f48
Update biginteger.h (#1652)
Fix intel compiler macro
de6681e295 (commitcomment-37645051)
2020-03-05 11:06:01 +08:00
mdamle
b16cec1a1a
Closes #1643 (#1644)
This change comes up with compile time pre-processor directives to
tune the behavior of rapidjson wrt memory consumption. The idea is to
allow each module using this library to choose the right defaults based
on how it consumes memory and what performance it expects.

1. RAPIDJSON_DEFAULT_ALLOCATOR: If defined allows you to choose
	CrtAllocator over MemoryPoolAllocator. If it is not defined, chooses MemoryPoolAllocator by default.
2. RAPIDJSON_DEFAULT_STACK_ALLOCATOR: If defined allows you to choose
	MemoryPoolAllocator over CrtAllocator. If it is not defined, chooses CrtAllocator by default.
3. RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY and RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY: If defined and set to a
	value, uses that value for default number of objects/array elements to be pre-allocated. If not defined,
	uses value of 16: the current default.

Verified that all tests pass.
2020-02-25 11:34:28 +08:00
Tim Gates
98f52b6bb0
Fix simple typo: drived -> derived (#1646)
Closes #1645
2020-02-21 15:46:10 +08:00
xpahos
a895ce150f
Allow escaped apostrophe in values (#1639)
* Allow escaped apostrophe in values

* Allow escaped apostrophe in values

* Canonical flag name

* Add translation for escaped apostrophe

Co-authored-by: Milo Yip <miloyip@gmail.com>
2020-02-13 09:53:15 +08:00
Milo Yip
418331e99f
Merge pull request #1631 from PhoebeHui/dev/Phoebe/vcpkg_instructions
Add vcpkg installation instructions
2020-01-17 09:55:44 +08:00
PhoebeHui
b4cf6e7381 Add vcpkg installation instructions 2020-01-16 03:09:20 -08:00
Milo Yip
dfbe1db9da
Merge pull request #1502 from ylavic/compilation_fixes
Compilation fixes
2019-12-03 09:51:05 +08:00
Milo Yip
eeb9d553f8
Merge pull request #1617 from JPEWdev/master
Remove shadow typedef
2019-12-03 09:49:40 +08:00
Joshua Watt
134af9d811 Remove shadow typedef
Removes a duplicate and identical typedef that was causing a
'declaration shadows typedef' (-Wshadow) warning in clang.
2019-12-02 09:19:16 -06:00
Milo Yip
35e480fc4d
Merge pull request #1609 from piratf/readme_contributing
add contributing section in readme.md
2019-11-25 11:54:59 +08:00
piratf
6cadd4b2ca add contributing section in readme.md, introduced the basic cooperation process. 2019-11-24 12:28:34 +08:00
Milo Yip
6534506e82
Merge pull request #1603 from piratf/cmakelist_upgrade
fix CMake policy CMP0048 warning #1154
2019-11-11 18:03:54 +08:00
piratf
46d980b46a fix CMake policy CMP0048 warning #1154 2019-11-11 16:09:43 +08:00
Milo Yip
c4c6a65410
Merge pull request #1548 from TranslucentTB/master
Fix ARM NEON under MSVC
2019-11-01 10:53:00 +08:00
Charles Milette
e54aca7006
Merge branch 'master' of https://github.com/Tencent/rapidjson 2019-10-31 21:10:28 -04:00
Milo Yip
bb5f966b99
Merge pull request #1591 from veekxt/patch-1
fix a typo of doc
2019-10-21 21:19:59 +08:00
VeekXT
67b245e07d
doc: fix a typo 2019-10-18 18:49:15 +08:00
Milo Yip
1a825d24fa
Merge pull request #1529 from rkoshy/master
Fixed a build issue by initializing "index" in the header file
2019-10-15 09:49:27 +08:00
Milo Yip
6a6bed2759
Merge pull request #1582 from crazyscot/master
Use C++17 fallthrough tag instead of disabling compiler warning
2019-10-08 10:12:13 +08:00
Milo Yip
5592c2eed4
Merge pull request #1544 from fredgan/master
修复文档中的错误
2019-10-08 09:57:38 +08:00
fredgan
39db1177bf fix some misspellings 2019-10-08 09:25:51 +08:00
Ross Younger
4116912cde Use C++17 fallthrough tag instead of disabling warning
Signed-off-by: Ross Younger <crazyscot@gmail.com>
2019-10-01 20:12:54 +13:00
Milo Yip
d67a69a9cf
Merge pull request #1490 from MalcolmTyrrell/fixCompileErrorInPointerH
Fix vs2017 compile error C2105: '--' needs l-value
2019-09-26 10:08:13 +08:00
Milo Yip
5777291497
Merge pull request #1579 from Tencent/vs2010
Fix VS2010 build via disabling copy constructor in GenericMember
2019-09-26 10:07:46 +08:00
Milo Yip
88a1ba9e30 Provide default implementations for move constructor/assignment in GenericMember 2019-09-25 20:20:20 +08:00
Milo Yip
c36b713c47 Disable copy constructor in GenericMember 2019-09-25 18:02:17 +08:00
Milo Yip
6006d6b678
Merge pull request #1573 from esrrhs/master
fix travis build
2019-09-25 14:27:37 +08:00
zhao xin
02d4ae838c
Update travis-doxygen.sh 2019-09-25 11:17:28 +08:00
zhao xin
4c1d9edb35
Update travis-doxygen.sh 2019-09-25 11:16:55 +08:00
zhao xin
c136acf023
Update travis-doxygen.sh 2019-09-25 11:16:26 +08:00
zhao xin
b2861565aa
Update travis-doxygen.sh 2019-09-25 11:16:06 +08:00
zhao xin
ed234bf749
Update .travis.yml 2019-09-25 10:26:39 +08:00
zhao xin
d3c4b2b2b1
Update .travis.yml 2019-09-25 10:17:39 +08:00
Eric Rannaud
ebc003e205 Make GenericMemberIterator::Iterator public again (RAPIDJSON_NOMEMBERITERATORCLASS)
d87b698d0f made all definitions of GenericMemberIterator consistent as
classes (they were structs with RAPIDJSON_NOMEMBERITERATORCLASS
defined), but it didn't keep the member definitions public.

document.h:586:71: error: 'Iterator' is a private member of
      'rapidjson::GenericMemberIterator<false, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >'
    typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;  //!< Member iterator for i...
                                                                      ^
document.h:2124:32: note: in instantiation of template class
      'rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >' requested here
class GenericDocument : public GenericValue<Encoding, Allocator> {
2019-09-12 09:08:11 -07:00
Milo Yip
fcec7735dc
Merge pull request #1567 from AtnNn/master
Allow pointer tokens to have non-null-terminated strings
2019-09-12 17:40:00 +08:00
Etienne Laurin
123d7c89a4 add test for non-null-terminated token 2019-09-12 08:12:06 +01:00
Etienne Laurin
6102f0bd06 fix template parameter 2019-09-11 17:23:15 +01:00
Etienne Laurin
6fe99777e4 Allow pointer tokens to have non-null-terminated strings 2019-09-11 17:03:35 +01:00
Milo Yip
2648a732db
Merge pull request #1557 from MBoldyrev/doc/fix-uint-case
Documentation: fixed Uint case
2019-08-23 15:07:50 +08:00
Mikhail Boldyrev
8973b279cf fixed Uint case in docs 2019-08-23 07:44:29 +03:00
Charles Milette
02230fecbf
Change #ifdef to #if defined 2019-07-25 17:17:52 -04:00
Charles Milette
dfc0b35360
Update comment 2019-07-25 17:12:48 -04:00
Charles Milette
0d671a2e19
Fix signedness error 2019-07-25 17:11:20 -04:00
Charles Milette
07e1d7870a
Fix build error under non-Clang compilers 2019-07-25 16:55:34 -04:00
Charles Milette
d5d7171f6d
Fix ARM NEON under MSVC 2019-07-25 16:38:34 -04:00
FredGan
a133b16699
Merge pull request #1 from Tencent/master
Change all GenericMemberIterator from struct to class
2019-07-16 20:18:56 +08:00
Milo Yip
d87b698d0f Change all GenericMemberIterator from struct to class 2019-06-28 10:37:13 +08:00
Renny Koshy
c43697c16c - Fixed a build issue by initializing "index" in the header file 2019-06-21 23:55:32 -04:00
Milo Yip
4b3d7c2f42
Merge pull request #1506 from ylavic/CreatePattern
Add missing curly brackets in STDREGEX's CreatePattern().
2019-05-17 09:27:30 +08:00
ylavic
92f99bc2ee RAPIDJSON_NOEXCEPT_ASSERT() should never throw.
clang warns about throwing from RAPIDJSON_NOEXCEPT_ASSERT() in a nothrow
context.

If RAPIDJSON_ASSERT() throws it can never be used for _NOEXCEPT_ASSERT(),
so use C assert() instead.

Finally (and originally), since RAPIDJSON_ASSERT() in "unittest.h" throws,
make it define RAPIDJSON_ASSERT_THROWS for RAPIDJSON_NOEXCEPT_ASSERT() to
now do the right thing.
2019-05-09 13:37:49 +02:00
ylavic
b4538b5363 Fix compilation of sortkeys.cpp with MSVC 2013 (hopefully). 2019-05-09 13:37:49 +02:00
ylavic
94fc463801 Add missing curly brackets in STDREGEX's CreatePattern(). 2019-04-29 15:06:52 +02:00
Malcolm Tyrrell
c840a7ae15 Fix vs2017 compile error C2105: '--' needs l-value 2019-04-15 10:00:14 +01:00
Milo Yip
01950eb7ac
Merge pull request #1488 from somone23412/somone23412-fix-typo-1
Update pointer.zh-cn.md : fix typo
2019-04-15 09:25:18 +08:00
quyan
0798d5b26e
fix typo 2019-04-15 00:43:37 +08:00
Milo Yip
e80257a924
Merge pull request #1481 from liangdzou/patch-1
add missing header "ios"
2019-04-09 13:21:59 +08:00
Liang ZOU
13687a6e3e
add missing header "ios"
add missing header "ios" for symbol "std:: streamsize"
2019-04-09 10:55:57 +08:00
Milo Yip
e123f650a9
Merge pull request #1479 from MaxXSoft/patch-tutorial
doc/tutorial.zh-cn: fixed some typos
2019-04-09 09:42:14 +08:00
MaxXSoft
d5c5b87f0d doc/tutorial.zh-cn: fixed some typos 2019-04-08 19:20:06 +08:00
Milo Yip
55c3c241cf
Merge pull request #1477 from eisaev/patch-1
Fixed typo in allocators.h
2019-04-04 14:50:21 +08:00
eisaev
9264a9a7ef
Update allocators.h
Fixed typo
2019-04-03 22:10:30 +05:00
Milo Yip
091de040ed
Merge pull request #1462 from ra1u/master
Allow user to define custom RAPIDJSON_NOEXCEPT_ASSERT macro
2019-03-11 10:35:27 +08:00
Luka Rahne
40cae03b0d Allow user to define custom RAPIDJSON_NOEXCEPT_ASSERT macro 2019-03-10 20:07:59 +01:00
Milo Yip
3cf4f7c5a0
Merge pull request #727 from mapbox/silence-dereference-null-pointer
Silence false positive clang-tidy warning
2019-03-06 09:33:13 +08:00
Milo Yip
7484e06c58 Update doxygen download URL 2019-02-11 15:17:59 +08:00
Milo Yip
1ede098e90 Workaround of sortkeys example 2019-02-11 14:14:35 +08:00
Gaspard Petit
cef07fb1b3 Added parameters to RAPIDJSON_MALLOC, RAPIDJSON_REALLOC and RAPIDJSON_FREE
Signed-off-by: Gaspard Petit <gaspard.petit@eidosmontreal.com>
2019-02-10 01:15:35 -05:00
Gaspard Petit
ad2e5369b9 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.
Signed-off-by: Gaspard Petit <gaspard.petit@eidosmontreal.com>
2019-02-10 00:32:26 -05:00
Milo Yip
b94c2a1203 Adding swap() for GenericMember 2019-02-08 11:39:25 +08:00
Milo Yip
0739a3e88b Fix gcc compilation error in sortkeys 2019-02-06 20:35:20 +08:00
Milo Yip
f595f8a6a5 Update sortkeys.cpp 2019-02-06 19:59:09 +08:00
Milo Yip
1892013216
Merge pull request #1421 from HomeControlAS/sort_by_name_example
added example for sorting keys
2019-02-06 19:52:54 +08:00
Milo Yip
79a6dabd08
Merge pull request #1439 from ylavic/schema_pointer_allocator
Use the allocator of the Schema for its Pointer.
2019-02-06 19:31:03 +08:00
Milo Yip
93cb84a7bb
Merge pull request #1442 from rbilovol/cmake-fixup
CMake: remove hardcoded CMAKECONFIG_INSTALL_DIR path
2019-02-06 19:30:43 +08:00
Milo Yip
efad25970e
Merge pull request #1444 from leolchat/patch-1
Correct complexity claim
2019-02-06 19:30:11 +08:00
Léonard Gérard
bf09397285
Correct complexity claim 2019-01-31 22:29:07 -08:00
Ruslan Bilovol
8d272e53a4 CMake: remove hardcoded CMAKECONFIG_INSTALL_DIR path
Currently this path is hardcoded to lib/cmake.
Some distributions have different library path (like lib64).
So reuse LIB_INSTALL_DIR for that to make CMAKECONFIG_INSTALL_DIR
configurable and usable in such distros.

Signed-off-by: Ruslan Bilovol <rbilovol@cisco.com>
2019-01-24 18:38:14 +02:00
ylavic
dbb594bdb3 Use the allocator of the Schema for its Pointer.
The Pointer passed to construct the Schema can be from the stack or any
transient storage, so the copy stored in the Schema must have the same
lifetime/allocator as the Schema itself.
2019-01-10 18:42:16 +01:00
Milo Yip
bfdcf49110
Merge pull request #1426 from ylavic/pointer_less_than
Add "less than" operator to Pointer.
2018-12-19 16:25:09 +08:00
Milo Yip
b56eb28575
Merge branch 'master' into pointer_less_than 2018-12-18 09:32:09 +08:00
Milo Yip
8549e3db6a
Merge pull request #1431 from ylavic/pointer_swap
Allow to (std::)Swap two pointers.
2018-12-18 09:31:05 +08:00
ylavic
2ce91b823c Pointer tests now need <algorithm> (for std::swap), but no tabs. 2018-12-17 14:45:23 +01:00
ylavic
a66cf7924c Allow to (std::)Swap two pointers. 2018-12-17 14:33:32 +01:00
ylavic
eb6ee17d2d Speed up Pointer::operator<().
Speed is more important than alphabetical order (which makes few sense in
JSON in general, and with pointers especially). The use case is indexing
in std containers, i.e. O(log n) with rbtree, so the faster comparison
the better.
2018-12-12 22:32:56 +01:00
ylavic
0e34ed43f4 Rework Pointer::operator<() loop.
I must be too dumb to understand the mess MSVC (32bit only) did with the
previous loop, and to figure out how it might have make it never end.
Anyway, hopefully any compiler can grok this new loop...
2018-12-12 15:15:43 +01:00
ylavic
af17f196c6 Unit test for Pointer::operator<(). 2018-12-11 00:19:13 +01:00
ylavic
055f1fa61e Add less than operator to Pointer.
Allows to sort pointers in (std-)containers and/or index by them.
2018-12-10 22:02:25 +01:00
Milo Yip
66eb6067b1
Merge pull request #1425 from ylavic/filereadstream_peek4
Fix off by one in FileReadStream::Peek4()
2018-12-06 23:44:10 +08:00
Milo Yip
b4b0e13b4d
Merge pull request #1424 from ylavic/file_input_streams
Optimize FileReadStream and BasicIStreamWrapper.
2018-12-06 23:43:48 +08:00
Milo Yip
eea3e57bcf
Merge pull request #1416 from ylavic/regex_syntax_noassert
GenericRegex: don't throw/abort on syntax error (unclosed parenthesis).
2018-12-06 23:41:45 +08:00
ylavic
38d25d7458 Fix FileReadStream::Peek4().
Until Read() reaches EOF, Peek4() must not take off by one in
bufferLast_ into account; otherwise a buffer of size exactly 4 always
returns NULL.
2018-12-06 08:38:21 +01:00
ylavic
8aab3db129 Base buffered BasicIStreamWrapper on the original (better performing) FileReadStream algorithm. 2018-12-06 00:21:05 +01:00
ylavic
124e8b6079 Possibly std::ios::binary helps with streams on Windows 2018-12-05 18:35:45 +01:00
ylavic
2498c5776f Optimize FileReadStream and BasicIStreamWrapper.
On (my) linux, perftest reports:
- ~40% gain for FileReadStream (Take() loop),
- ~10% gain for ReaderParse_DummyHandler_FileReadStream.

With the same logic applied to BasicIStreamWrapper, which thus can now
also be created with a user buffer, performances align with those of
FileReadStream (same buffer size).

The "unbuffered" versions (added for FileReadStream) work solely with
the internal peekBuffer (Ch[4]) and are measured in perftest.  When
performances don't matter much, they can avoid the use of large
stack/heap buffers.
2018-12-05 16:43:54 +01:00
seky
d0188462d9 removed std::string and receiving const Value in printIt 2018-12-05 08:24:59 +01:00
seky
c9060b4a5c added example for sorting keys 2018-12-04 22:40:40 +01:00
ylavic
8c14787398 Unit test for invalid GenericRegex (unclosed parenthesis). 2018-12-03 11:49:34 +01:00
ylavic
be96f4d7fb GenericRegex: don't throw/abort on syntax error (unclosed parenthesis). 2018-12-03 11:42:29 +01:00
Milo Yip
30d92a6399
Merge pull request #1413 from ylavic/schema_regex_leak
Fix a memory leak for invalid std::regex in Schema.
2018-12-03 09:53:39 +08:00
Milo Yip
1c5b90f409
Merge pull request #1414 from ylavic/regex_allocator
Use passed in allocator for internal regex parser.
2018-12-03 09:51:50 +08:00
ylavic
3e6956767e Fix a memory leak for invalid std::regex in Schema. 2018-12-01 23:36:45 +01:00
ylavic
b0c96f9baf Use passed in allocator for internal regex parser. 2018-12-01 22:02:48 +01:00
Milo Yip
a63216054d
Merge pull request #1388 from yhager/yhager/clang-7
silence clang-7 self-assign-overloaded warning
2018-11-22 12:30:02 +08:00
Milo Yip
595ed48d54
Merge pull request #1403 from jcmonnin/fix-warning
Fix warning when NDEBUG is defined [-Wunused-variable]
2018-11-22 12:22:41 +08:00
Jean-Claude Monnin
51ca982aa1 Fix warning when NDEBUG is defined [-Wunused-variable]
Because `isPeek()` is side effect free this should not change anything.

The reason this warning is not shown in the unit tests is because the asserts
are always evaluated in the unit test:

#define RAPIDJSON_ASSERT(x) (!(x) ? throw AssertException(RAPIDJSON_STRINGIFY(x)) : (void)0u)
2018-11-21 13:24:06 +01:00
Philipp A. Hartmann
0cc44c82c9
Update test/unittest/pointertest.cpp
Co-Authored-By: yhager <yhager@users.noreply.github.com>
2018-10-31 20:31:04 -07:00
Yuval Hager
a77b49dcb8 silence clang-7 self-assign-overloaded warning 2018-10-26 14:58:57 -07:00
Milo Yip
67fac85e96
Merge pull request #1373 from lelit/issue1368
Add test case on kParseNumbersAsStringsFlag being able to load big ints
2018-10-09 00:20:35 +08:00
Lele Gaifax
91d50c849d Add test case on kParseNumbersAsStringsFlag being able to load big ints
See issue #1368.
2018-10-08 10:21:25 +02:00
Konstantin Käfer
16872af889 Avoid pointer arithmetic on null pointer to remove undefined behavior
The existing checks triggered undefined behavior when the stack was empty (null pointer). This change avoid this:
* If `stackTop_` and `stackEnd_` are null, it results in a `ptrdiff_t` of `0`
* If `stackTop_` and `stackEnd_` are valid pointers, they produce a `ptrdiff_t` with the remaining size on the stack
2018-10-05 09:26:20 +02:00
Milo Yip
663f076c7b
Merge pull request #1362 from jiapengwen/master
fix tutorial error
2018-09-19 12:58:56 +08:00
Milo Yip
2a5e733b6f
Merge pull request #1364 from jcourtat/fixfaq
faq: fix document insertion example
2018-09-19 12:58:14 +08:00
Julien Courtat
68349ed914 faq: fix document insertion example
GenericDocument contructor requires a pointer to an Allocator, but GetAllocator() only
returns a reference.

Signed-off-by: Julien Courtat <julien.courtat@aqsacom.com>
2018-09-18 14:51:12 +02:00
jiapeng.wen
1cfa861d4c fix tutorial error 2018-09-18 10:51:16 +08:00
Milo Yip
c0ca05f6dd
Merge pull request #1329 from pah/fix-noexcept
Add RAPIDJSON_NOEXCEPT_ASSERT
2018-09-11 10:13:09 +08:00
Milo Yip
c2aa79dc88
Merge pull request #1356 from gongminmin/AppVeyor2017
Update appveyor rule to support VS2017.
2018-09-10 16:59:39 +08:00
Milo Yip
783b819e67
Update rapidjson.h 2018-09-10 13:11:17 +08:00
Minmin Gong
a6be583efa Update appveyor rule to support VS2017. 2018-09-09 20:58:02 -07:00
Milo Yip
8a96a95de2
Merge branch 'master' into fix-noexcept 2018-09-10 11:27:45 +08:00
Milo Yip
f5f6052c56
Merge pull request #1327 from gongminmin/FixCompileInVS
Fix the compiling problems in VS
2018-09-10 11:23:26 +08:00
Milo Yip
08b1a8a41e
Merge pull request #1302 from chwarr/min-max-guard
Guard against min/max being macros in reader.h
2018-09-10 11:22:28 +08:00
Milo Yip
81af404b7f
Merge pull request #1284 from mobileben/noexcept-assert
Handle non-throwing exception specifications that can still throw #1280
2018-09-10 11:21:34 +08:00
Milo Yip
73063f5002
Merge pull request #1340 from lelit/issue1336
Wrap all WriteXxx() calls within EndValue()
2018-08-05 19:01:46 +08:00
Lele Gaifax
c9eabf9e13 Extend the test on issue #1336 to cover all basic types 2018-08-05 09:44:15 +02:00
Lele Gaifax
3fc9299b84 Add simple test for issue #1336 2018-08-03 12:34:03 +02:00
Lele Gaifax
11defb7aa4 Wrap all WriteXxx() calls within EndValue(), to ensure a flush after root-level scalar value
This attempts to fix issue #1336.
2018-08-03 12:17:29 +02:00
Milo Yip
6a905f9311
Merge pull request #1331 from JPEWdev/mem-alignment-fix
Fix SIGBUS due to unaligned access
2018-08-01 11:56:25 +08:00
Milo Yip
91df56313b
Merge pull request #1335 from IceTrailer/master
Fixed parentheses in reader.h which were required to prevent the using of max macro
2018-08-01 11:55:44 +08:00
IceTrailer
cd28248611 Fixed parentheses in reader.h which were required to prevent the using of max macro 2018-07-31 22:23:53 +02:00
Veselin Georgiev
748a652f04 Fix SIGBUS due to unaligned access
Update RAPIDJSON_ALIGN() to always align on an 8-byte boundary
unless otherwise overridden.

On some platforms (such as ARM), 64-bit items (such as doubles and
64-bit integers) must be aligned to an 8 byte address, even though the
architecture is only 32-bits. On these platforms, MemoryPoolAllocator
must match the malloc() behavior and return a 8 byte aligned allocation.
This eliminates any alignment issues that may occur at the expense of
additional memory overhead.

Failure to do so caused a SIGBUS signal when calling
GenericValue::SetNull(). The size of the data_ member of the
GenericValue class is 16 bytes in 32-bit mode and its constructor
requires an 8-byte aligned access.

While parsing a JSON formatted string using Document::ParseStream(), a
stack object containing GenericValue items was constructed. Since the
stack was 8-byte aligned, the constructor calls would succeed. When the
lifetime of the object ends, SetObjectRaw() is invoked. This triggered
an allocation with 4-byte alignment to which the previously 8-byte
aligned GenericValue array was copied. After this, any call to a
GenericValue API that triggered the constructor and thus the placement
new operation on the Data type member would trigger a SIGBUS.

Signed-off-by: Veselin Georgiev <veselin.georgiev@garmin.com>
Signed-off-by: Joshua Watt <Joshua.Watt@garmin.com>
2018-07-31 09:02:26 -05:00
Philipp A Hartmann
f54f6b5aa9 Add RAPIDJSON_NOEXCEPT_ASSERT
This is an alternative implementation to #1284 to handle
asserts in noexcept contexts.

Closes #1280.
2018-07-18 12:02:24 +02:00
Minmin Gong
ff76343336 Update the code to adapt the new gtest. 2018-07-16 20:36:20 -07:00
Milo Yip
2bbd33b332
Merge pull request #1323 from pah/fix-memaccess
Fix warnings/errors on GCC 7/8 (-Wclass-memaccess, -Wsign-conversion, -Wformat-overflow)
2018-07-16 12:22:46 +08:00
Philipp A Hartmann
152511689b Suppress -Wformat-overflow warning/error
GCC 7 and later warn about overflow/truncation when using
sprintf and related functions with fixed-size buffers.

Suppress the warning in schematest.cpp.
2018-07-15 16:02:03 +02:00
Philipp A Hartmann
a26267d16d Fix -Wsign-conversion warnings/errors
GCC 8 (incorrectly) warns about sign conversions in (constant)
array size expressions:

error: conversion to 'long unsigned int' from 'int' may
change the sign of the result [-Werror=sign-conversion]
     char schemaBuffer_[128 * 1024];

Make these expressions unsigned by adding a 'u' suffix to
the first operands.
2018-07-15 16:01:02 +02:00
Philipp A Hartmann
fa5963a2f5 Fix -Wclass-memaccess warnings/errors
Recent GCC versions warn about using memcpy/memmove to
write to a class pointer (-Wclass-memaccess).

Avoid the warnings by casting to void* first.

Closes #1086.
Closes #1205.
Closes #1246.
2018-07-15 14:20:38 +02:00
Milo Yip
4b4583bdbe
Merge pull request #1320 from AnomalRoil/master
Removing always true if condition
2018-07-12 23:31:19 +08:00
Yolan Romailler
93331cb0cd Removing always true if condition 2018-07-12 15:13:19 +02:00
Christopher Warrington
960b9cfd19 Guard against min/max being macros in reader.h
Sometimes, particularly when Microsoft's windows.h is included, min/max
are defined as macros, interfering with use of
std::numeric_limits::min() and the like.

To guard against this, the function name is wrapped in an extra set of
parenthesis, which inhibits function-style macro expansion.

This is a similar commit to 6e38649ec6, but fixes uses of
std::numeric_limits added after that commit, like those introduced in
2ea43433e2.
2018-07-10 11:08:41 -07:00
Milo Yip
129d19ba7f
Merge pull request #1312 from erikfroseth/issue-1308
Detect C++11 features for Developer Studio
2018-07-03 20:28:24 +08:00
Erik Froseth
3e255af03a Detect C++11 features for Developer Studio
This patch enables various C++11 features if the code is compiled with
Developer Studio compiler version 5.14 or higher.
2018-07-03 13:02:45 +02:00
Milo Yip
b81438ea96
Merge pull request #1307 from moretromain/preprocessor_cleanup
Rename a few internal preprocessor macros to avoid naming conflicts
2018-07-03 10:34:32 +08:00
Tim Miller
fdd2db930f Updated google test to latest commit 2018-07-02 08:30:17 -04:00
Romain Moret
4595cc488e Rename a few internal preprocessor macros to avoid potential naming conflicts 2018-07-02 13:24:18 +02:00
Milo Yip
7e68aa0a21
Merge pull request #1252 from StilesCrisis/issue-1251-test
Unit Test: Parsing "128.74836467836484838364836483643636483648e-336" causes a crash
2018-06-19 12:43:54 +08:00
Milo Yip
c511ce303f
Merge pull request #1250 from StilesCrisis/issue-1249-test
Unit Test: Parsing "0e100" in full precision mode causes UB
2018-06-18 23:54:53 +08:00
Milo Yip
6cc3910a10
Merge pull request #1290 from abolz/fix-strtod
Fix strtod
2018-06-17 23:20:45 +08:00
abolz
7101911d9b Run all the new tests in full-precision mode only
until I know what the normal-precision algorithm really does...
2018-06-16 15:23:44 +02:00
abolz
319944a11a Disable failing test for now 2018-06-16 14:55:07 +02:00
abolz
a757a2aeb8 Add more tests
Some more need to be fixed.
2018-06-16 14:31:48 +02:00
abolz
179277817d Add a test for BigInteger::operator<< 2018-06-16 13:48:33 +02:00
abolz
a0f9c5fc46 [Debug - clean up] 2018-06-16 12:32:17 +02:00
abolz
879ae853fe Fix offset computation in BigInteger::operator<< 2018-06-16 09:41:04 +02:00
abolz
8b98f4a782 Workaround incorrect rounding in MSVC 2018-06-16 09:40:40 +02:00
abolz
a2813b6739 Limit exponents 2018-06-15 17:10:36 +02:00
abolz
6cd5cd7b94 [Debug - Initialize variable] 2018-06-15 16:01:52 +02:00
abolz
292f787c04 [Debug] 2018-06-15 15:10:50 +02:00
abolz
695c9cb976 Use C macros with the correct header instead of std::numeric_limits and static_cast
=D
2018-06-15 14:06:14 +02:00
abolz
1d636de81e Fix another signed/unsigned warning 2018-06-15 13:53:48 +02:00
abolz
a2a7d97b3b Use std::numeric_limits instead of macros 2018-06-15 13:50:19 +02:00
abolz
fc85fbeef0 Fix implicit signed/unsigned conversion and a small glitch in the error computation - part 2 2018-06-15 13:44:43 +02:00
abolz
16c97cd7c5 Fix implicit signed/unsigned conversion and a small glitch in the error computation 2018-06-15 13:44:15 +02:00
abolz
2ea43433e2 Fix bogus gcc warning 2018-06-15 13:41:44 +02:00
abolz
a78c8e3a4f Add more tests (which need to be fixed) 2018-06-15 12:59:39 +02:00
abolz
cb009f3050 Return infinity if binary exponent is too large 2018-06-15 12:59:05 +02:00
abolz
7acbb87c2b Some more tests 2018-06-15 11:39:45 +02:00
abolz
4e9b4f6d6a Return 0 if binary exponent is too small 2018-06-15 11:32:32 +02:00
abolz
f5e5d47fac Properly test for overflow
Do not use an approximation to do this. Instead check if the result is Inf.
2018-06-15 11:29:48 +02:00
abolz
d83d2ba260 Trim all zeros from input
If the buffer only contains zeros, return 0.
2018-06-15 10:46:45 +02:00
abolz
c59ecc857d Replace unsigned with signed integer arithmetic in strtod 2018-06-15 10:44:10 +02:00
abolz
29b6c9b7dc Add assertions to check preconditions of functions and unsigned integer arithmetic 2018-06-15 10:35:31 +02:00
abolz
80dba56aca Add tests for issues with string-to-double conversions (#849, #1249, #1251, #1253, #1256, #1259) 2018-06-15 10:15:45 +02:00
Milo Yip
01c71740cd
Merge pull request #1287 from Nekto89/msvc_config
MSVC: Autodetect RAPIDJSON_HAS_CXX11_NOEXCEPT, RAPIDJSON_HAS_CXX11_TYPETRAITS
2018-06-14 11:04:15 +08:00
Marian Klymov
2b0843037e Autodetect RAPIDJSON_HAS_CXX11_NOEXCEPT and RAPIDJSON_HAS_CXX11_TYPETRAITS for Visual Studio 2018-06-13 20:43:16 +03:00
Benjamin Lee
5b0610a74f Handle non-throwing exception specifications that can still throw #1280 2018-06-06 23:34:51 -07:00
Milo Yip
c0daf75475
Merge pull request #1279 from bogaotory/master
Avoid `MissingProperty` Error from `SchemaValidator` when a none-zero length value is given as `default` for the property
2018-06-02 15:20:05 +08:00
bogaotory
6f7dcb30d9 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 2018-06-01 21:16:26 +01:00
bogaotory
fa98b5b4b6 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 2018-06-01 11:07:53 +01:00
Milo Yip
af223d44f4
Merge pull request #1261 from fmalita/exponent-underflow
Prevent int underflow when parsing exponents
2018-05-20 13:42:13 +08:00
Florin Malita
8269bc2bc2 Prevent int underflow when parsing exponents
When parsing negative exponents, the current implementation takes
precautions for |exp| to not underflow int.

But that is not sufficient: later on [1], |exp + expFrac| is also
stored to an int - so we must ensure that the sum stays within int
representable values.

Update the exp clamping logic to take expFrac into account.

[1] https://github.com/Tencent/rapidjson/blob/master/include/rapidjson/reader.h#L1690
2018-05-15 22:48:07 -04:00
John Stiles
1329cdecce Added test for issue #1251 2018-05-11 15:57:11 -07:00
John Stiles
cad3805737
Update readertest.cpp 2018-05-11 15:19:11 -07:00
John Stiles
f7d2cd2228 added test for parsing 0e100 2018-05-11 15:16:46 -07:00
John Stiles
532cba1422
Merge pull request #4 from Tencent/master
Merge
2018-05-11 14:26:21 -07:00
Milo Yip
a091035846
Merge pull request #1240 from ksergey/FIX_Reader
Added const for Reader methods
2018-05-04 10:11:59 +08:00
Sergey Kovalevich
d0a78bf56e Added const for Reader methods 2018-05-03 15:11:16 +03:00
Milo Yip
b32cd9421c
Merge pull request #1217 from tresorit/win-clang-fix
Fix compilation on windows with clang
2018-04-25 10:13:55 +08:00
Milo Yip
ed72564e31
Merge pull request #1231 from steveire/patch-1
Use rvalue refs with clang-cl
2018-04-25 10:13:19 +08:00
Stephen Kelly
73b8774ab1
Use rvalue refs with clang-cl 2018-04-24 22:55:47 +01:00
Milo Yip
5fd779d91f
Merge pull request #1222 from DynonAvionics/adjustable_default_chunk_capacity
Allow user configuration of default chunk capacity.
2018-04-18 11:35:00 +08:00
Ryan Morris
6f587466a1 Added macro RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY to allow default chunk capacity to be lowered for embedded devices with < 64k stack sizes 2018-04-17 12:53:23 -07:00
Zoltan Kovago
0fdd8040ce fix compilation on windows with clang 2018-04-09 15:47:17 +02:00
Milo Yip
8022a5f79c
Merge pull request #1210 from foxtacles/fix-missing-remote-ref-p
add remote ref pointer to schemaMap_
2018-03-27 10:37:09 +08:00
Christian Semmler
9640209f78 remove superfluous typename 2018-03-26 13:29:52 +02:00
Christian Semmler
f8c8c32b42 fix C++03 compatibility 2018-03-26 13:16:31 +02:00
Christian Semmler
c8530d022f add test case for remote ref issue 2018-03-26 13:04:35 +02:00
Christian Semmler
8a6c345bcc add remote ref to schemaMap_ 2018-03-23 23:33:20 +01:00
Milo Yip
67a17cfdbc
Merge pull request #1207 from vim2meta/master
Ensure a preprocessor directive is only applied to MSVC.
2018-03-20 14:46:33 +08:00
John
de6681e295 ensure the pragma is only applied to MSVC 2018-03-19 15:18:08 -04:00
Milo Yip
f0177eb936
Merge pull request #1203 from KuangLei/doc_AddingWriter
Adding a few missing includes in the doc
2018-03-17 00:01:42 +08:00
KLsz
f9c9339761 Adding a few missing includes 2018-03-16 23:50:17 +08:00
Milo Yip
0f96b5605a
Merge pull request #1202 from Sumoren/msc_long_part2
Change long/ulong as int/uint on MSC unit tests to be more inline wit…
2018-03-15 10:10:58 +08:00
MaximeBF
27424d5c09 Change long/ulong as int/uint on MSC unit tests to be more inline with other templated functions unit tests 2018-03-14 08:44:00 -04:00
Milo Yip
d79533c65a
Merge pull request #1199 from kachanovskiy/master
Fixes #1198
2018-03-13 10:43:18 +08:00
sergey kachanovskiy
2e5dcceda0 Fixes #1198 2018-03-12 16:11:09 +01:00
Milo Yip
3b638e6715
Merge pull request #1191 from Sumoren/msc_long
Support long and unsined long as int and unsigned on Microsft platforms
2018-03-09 11:33:12 +08:00
MaximeBF
a37f9d1ecd Fix unsigned long as unsigned unit test 2018-03-08 07:33:26 -05:00
MaximeBF
a040fc3347 Add unittest for long as int in MSC platforms 2018-03-08 07:28:51 -05:00
MaximeBF
294a5aca8f Support long and unsined long as int and unsigned on Microsft platforms 2018-03-06 11:17:04 -05:00
Milo Yip
8bf4f7b97c
Merge pull request #1188 from Martinfx/master
Fix warnings: dereference of null pointer
2018-03-04 17:59:45 +08:00
maficccc@gmail.com
72481d5a04 Fix warnings Dereference of null pointer 2018-03-03 00:08:11 +01:00
Milo Yip
9dfc437477
Merge pull request #1182 from Romain-Geissler-1A/ignore-gcc-8-warnings
Ignore GCC 8 warnings.
2018-02-22 09:24:02 +08:00
Milo Yip
91cd123137
Merge pull request #1181 from luzpaz/misc-typos
Misc. typos
2018-02-22 09:23:00 +08:00
Romain Geissler
54dab1eebb Ignore GCC 8 warnings. 2018-02-19 12:52:16 +01:00
luz.paz
915218878a Misc. typos
Found via `codespell -q 3` in  downstream https://github.com/BlueBrain/Brayns
2018-02-19 06:42:52 -05:00
Milo Yip
49562271be Fix Windows build 2018-02-13 15:08:20 +08:00
Milo Yip
59181a052f Revert "Fix API constness"
This reverts commit 0d2580f1f0a24d24c0e015d01fc9567a7365ce7e.
2018-02-13 12:27:25 +08:00
Milo Yip
0d2580f1f0 Fix API constness
Fix #1014
2018-02-13 12:20:08 +08:00
Milo Yip
a1909a9427
Merge pull request #1179 from Tencent/issue1153_rawvalueencoding
Add transcoding/validation to Writer::RawValue()
2018-02-13 12:20:34 +08:00
Milo Yip
966987625c Add transcoding/validation to Writer::RawValue()
Fix #1152
2018-02-13 10:58:41 +08:00
Milo Yip
e2d0437a9c Fix false alarm from clang-tidy
Fix #1174
2018-02-12 17:38:46 +08:00
Milo Yip
82b5c42567 Fix Compile error because of -Werror=effc++ is on
Fix #1170
Also fixed C++03 problem for using nullptr.
2018-02-12 13:14:59 +08:00
Milo Yip
672e7dd373 Fix invalid type in Pointer
Fixed https://github.com/miloyip/rapidjson-gitbook/issues/1
2018-02-12 10:16:27 +08:00
Milo Yip
daabb88e00
Merge pull request #1068 from yurikhan/violationDetails
Schema violation details
2018-01-26 11:26:27 +08:00
Milo Yip
7641af690e
Merge pull request #1122 from svart-riddare/issue-1108
Suggestion for issue #1108
2018-01-26 10:59:11 +08:00
Milo Yip
cdc899a3f3
Merge pull request #1124 from DerDakon/CMake-cleanup
CMake cleanups
2018-01-26 10:33:30 +08:00
Milo Yip
fc7cda78a9 Fix -Werror=effc++
#1164
2018-01-16 10:35:25 +08:00
Milo Yip
b1e556d713
Merge branch 'master' into violationDetails 2018-01-13 22:34:58 +08:00
Milo Yip
03f5de9d7e
Merge pull request #1065 from yurikhan/invalidSchemaPointer
Fix reported violated schema pointer when that schema is remote
2018-01-13 21:17:56 +08:00
Milo Yip
9338148f5f
Merge pull request #1161 from xiaoPierre/master
Bug when switching to std regex
2018-01-13 21:13:50 +08:00
Milo Yip
a735badbd0
Merge pull request #1162 from Tencent/travis
Fix Travis build due to clang noexcept issue in unittest
Fix #1159
2018-01-13 13:15:54 +08:00
Milo Yip
d48290e387 Another try to fix travis build 2018-01-13 12:51:24 +08:00
Milo Yip
62e785babf Merge branch 'master' into travis 2018-01-13 12:44:22 +08:00
Milo Yip
0d95d58f8b Try to fix travis build 2018-01-13 12:37:01 +08:00
xiaoPierre
b8c12c9ccd Bug when switching to std regex
I could not switch to std regex after defining the two variables as in documents. Then I try to fix it in schema.h.
2018-01-11 17:45:35 +01:00
Milo Yip
6043ad8688
Merge pull request #1138 from Tencent/archiver_example
Add archiver example
2018-01-10 10:46:19 +08:00
Milo Yip
83f149e70e
Merge pull request #1148 from lelit/fix-filewritestream-doc
Fix FileWriteStream doc
2018-01-03 17:15:00 +08:00
Milo Yip
a7f687fdf8
Merge pull request #1153 from Haffon/master
GetParseOffset
2017-12-30 23:59:31 +08:00
Haffon
7dfeee862d
GetParseOffset to GetErrorOffset 2017-12-28 16:32:26 +08:00
Haffon
53eadd218d
GetParseOffset to GetErrorOffset 2017-12-28 16:31:26 +08:00
Lele Gaifax
20d44d9c44 Fix FileWriteStream doc 2017-12-22 19:24:15 +01:00
Milo Yip
802ece6d7c
Merge pull request #1147 from DrumMeister/master
Fix uninitilized member Reader::state_
2017-12-22 11:05:20 +08:00
sjaques
9bfa0bb567 Fix uninitilized member Reader::state_ 2017-12-21 13:40:28 +01:00
Milo Yip
f2a28ee472 Add archiver example
A simple (de)serialization framework using DOM and SAX API
2017-12-13 21:53:18 +08:00
Milo Yip
87d4e07ffd
Merge pull request #1137 from pah/fixes/1131-iterator-deprecation
Avoid inheritance from std::iterator
2017-12-13 10:52:20 +08:00
Philipp A. Hartmann
d75bb90a5d Avoid inheritance from std::iterator
Instead of inheriting from the deprecated std::iterator
template, define the member typedefs needed for
std::iterator_traits directly.

Closes #1131.
2017-12-12 21:16:07 +01:00
Milo Yip
7caa4b2165
Merge pull request #1129 from thorade/patch-1
ignore DS_Store files
2017-12-05 11:08:09 +08:00
Matthis Thorade
79d5e23673
Delete .DS_Store 2017-12-04 13:19:14 +01:00
Matthis Thorade
80079f1fae
Delete .DS_Store 2017-12-04 13:19:05 +01:00
Matthis Thorade
195dc90d27
Delete .DS_Store 2017-12-04 13:18:51 +01:00
Matthis Thorade
25c1b78f3c
ignore DS_Store files 2017-12-04 13:15:01 +01:00
Étienne Dupuis
44f2f9aa53 Added relevant unit tests for issue #1108 suggested improvement. 2017-11-27 10:38:01 +01:00
Rolf Eike Beer
ff59b6179d CMake: automatically handle C++11 settings if possible 2017-11-24 17:00:53 +01:00
Rolf Eike Beer
4c9a28a28e CMake: do not pass -march=native or -mcpu=native when crosscompiling 2017-11-24 16:58:42 +01:00
Rolf Eike Beer
4e1c7363cc CMake: avoid neeless variable expansion
CMake will automatically expand strings that are variable names in if().
2017-11-24 16:58:42 +01:00
Étienne Dupuis
86e280f636 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. 2017-11-23 09:16:20 +01:00
Milo Yip
17ae6ffa85
Merge pull request #1110 from martinlindhe/master
fix some typos
2017-11-04 22:32:21 +08:00
Martin Lindhe
8684c9960d fix some typos 2017-11-04 10:32:02 +01:00
Milo Yip
5aa79b7272 Merge pull request #1105 from clach04/issue_1104_solaris_fread
Fix issue #1104 Solaris compilation errors fread()/fwrite()
2017-10-27 17:12:55 +08:00
clach04
1be14d04a0 Fix issue #1104 Solaris compilation errors fread()/fwrite()
Explicit std name space for fread() and fwrite().
2017-10-26 21:19:54 -07:00
Milo Yip
75a71441d9 Merge pull request #1102 from m-tayel/1019-proposed-fix
Fixed typo in CMake file
2017-10-26 16:25:27 +08:00
M.Tayel
f4b1f761f3 Fixed typo in CMake file 2017-10-24 12:25:47 +02:00
Milo Yip
7dddd05462 Merge pull request #1070 from KaitoHH/line-col
Add feature of locating line and column number of error
2017-10-20 17:50:48 +08:00
Milo Yip
93f6cf4e8c Merge pull request #1081 from datatypevoid/patch-1
chore: correct spelling
2017-10-20 17:47:41 +08:00
Milo Yip
bf822593ee Merge pull request #1083 from piotr-kaminski-intel/master
Removing Klocwork issues from schema.h
2017-10-20 17:47:13 +08:00
Milo Yip
3c07cecdb8 Add anchors to Schema.md 2017-10-20 11:16:44 +08:00
Milo Yip
db305dcf21 Fix schema.md TOC 2017-10-20 10:33:37 +08:00
Milo Yip
4db8c3da11 Merge pull request #1098 from h46incon/MemberCapacity
Add MemberCapacity() and MemberReserve() interface for object type.
2017-10-20 10:27:23 +08:00
h46incon
a8e9990603 Add MemberCapacity() and MemberReserve() interface for object type. 2017-10-19 20:41:27 +08:00
Milo Yip
7d424c0bbc Merge pull request #1092 from m-tayel/1019-proposed-fix
enable cross compiling by adding option to remove -march/-cpu
2017-10-17 10:38:07 +08:00
M.Tayel
7bd9b5a1ad enable cross compiling by adding option to remove -march/-cpu 2017-10-16 15:01:27 +02:00
piotr-kaminski-intel
bb99ccb030 Init variable in the constructor
line 358:
'this->notValidatorIndex_' might not be initialized in this constructor.
2017-10-10 14:09:23 +02:00
Milo Yip
d71ad00643 Merge pull request #1079 from captaincrutches/cmake-include-dir
Make RapidJSON_INCLUDE_DIR non-blank in Config.cmake
2017-10-09 12:44:25 +08:00
Captain Crutches
495266271f Use SOURCE_DIR instead of CMAKE_DIR for build tree 2017-10-08 23:43:18 -04:00
Milo Yip
f64b773007 Partially fix #1077 2017-10-09 11:33:55 +08:00
Milo Yip
d5c1be5a0f Merge pull request #1082 from svart-riddare/regex-allocator
Use schema allocator for regex
2017-10-09 11:17:30 +08:00
piotr-kaminski-intel
b217cc640c Removing Klocwork issues from schema.h
Removing Klocwork static code analysis critical issues:

line 358:
'this->notValidatorIndex_' might not be initialized in this constructor.
line :412
Pointer 'schemaDocument' checked for NULL at line 412 may be passed to function and may be dereferenced there by passing argument this to function 'CreateSchema' at line 419. Also there are 7 similar errors on lines 467 479 511 523 533 538 549.
2017-10-07 00:50:55 +02:00
Étienne Dupuis
6e08e29425 Initialized regex with schema allocator. 2017-10-05 11:39:21 +02:00
David Newman
f0391747e6 chore: correct spelling 2017-10-03 23:26:19 -04:00
Captain Crutches
84ca485e51 Make RapidJSON_INCLUDE_DIR non-blank in Config.cmake 2017-10-02 20:39:40 -04:00
Yuri Khan
8c182e51e7 Flatten allOf keyword violations 2017-09-30 20:16:03 +07:00
Yuri Khan
8353e868d5 Move schema violation docs into Schema chapter 2017-09-30 19:44:54 +07:00
Yuri Khan
1f75402704 refactor Schema: Keep ErrorHandler reference in Context 2017-09-30 19:05:25 +07:00
KaitoHH
473553bd5a fix gcc & cl warning 2017-09-29 19:13:29 +08:00
KaitoHH
9394b84440 remove unnecessary code 2017-09-29 18:19:41 +08:00
KaitoHH
66541b8926 add unit test for cursorstreamwrapper 2017-09-29 17:24:07 +08:00
KaitoHH
799fdea9fc add cursor wrapper 2017-09-29 15:26:24 +08:00
KaitoHH
143641c75a suppress C4512, C4702 warning 2017-09-29 15:26:18 +08:00
KaitoHH
79d9c71f98 fix stream wrapper initializer
fix initialization warning

add special wrapper for AutoUTFInputStream
2017-09-29 15:24:27 +08:00
KaitoHH
b16ff281f8 Add feature of locating line and column number of error 2017-09-29 15:24:27 +08:00
Milo Yip
2a0bc6062b Update gitbook zh-cn link 2017-09-29 09:53:00 +08:00
Milo Yip
0b8adabab7 Fix #1071 gitbook link 2017-09-29 09:44:05 +08:00
Yuri Khan
a4b62ff61b Update schemavalidator example to demonstrate GetError() 2017-09-24 12:56:55 +07:00
Yuri Khan
384df14e6d Document schema violation format 2017-09-24 12:56:55 +07:00
Yuri Khan
0566716802 Extend schema validation tests to compare error object 2017-09-24 12:56:55 +07:00
Yuri Khan
f716c3bfb5 Report schema violation details (#619) 2017-09-24 12:56:55 +07:00
Yuri Khan
c2371584a0 Keep schema URI in GenericSchemaDocument and internal::Schema 2017-09-23 21:36:07 +07:00
Yuri Khan
2bfd0cc6c7 internal::Schema: Keep pointer for future use 2017-09-23 20:42:39 +07:00
Yuri Khan
379b337444 Add failing test for the case when a remote schema is violated (#1064) 2017-09-16 17:09:08 +07:00
Milo Yip
4c0f0036b5 Update appveyor badge and link 2017-09-14 11:55:31 +08:00
Milo Yip
4a2f2729f1 Change from miloyip/rapidjson to Tencent/rapidjson 2017-09-13 17:03:23 +08:00
Milo Yip
2a53253e72 Merge pull request #1056 from chwarr/assert-enum-lower
Assert Type enum lower bound as well
2017-09-07 10:07:19 +08:00
Christopher Warrington
a683902b2c Assert Type enum lower bound as well 2017-09-06 15:13:20 -07:00
Milo Yip
5db5dd552a Merge pull request #1057 from chwarr/paren-minmax
Guard against min/max being macros in a cross-compiler way
2017-09-06 13:03:52 +08:00
Milo Yip
4bb4926c9b Merge pull request #1055 from chwarr/fix-doc-build-windows
Fix Windows doc build MSBuild error MSB6001
2017-09-06 11:33:45 +08:00
Christopher Warrington
e4c0ecf86b Guard against min/max macros in tests too 2017-09-05 18:27:02 -07:00
Christopher Warrington
6e38649ec6 Guard against min/max being macros in document.h
Sometimes, particularly when Microsoft's windows.h is included, min/max
are defined as macros, interfering with use of
std::numeric_limits::min() and the like.

To guard against this, the function name is wrapped in an extra set of
parenthesis, which inhibits function-style macro expansion.
2017-09-05 18:26:47 -07:00
Christopher Warrington
bbdf5d1d4b Fix Windows doc build MSBuild error MSB6001
When using a MSBuild-based CMake generator like 'Visual Studio 15 2017
Win64', the doc build was failing with the error 'MSB6001: Invalid
command line switch for "cmd.exe". Illegal characters in path.'

This was due to the dependency on Doxyfile*, which wasn't expanded by
CMake.

The fix is to expand this glob in CMake before specifying the custom
command's dependencies.

Partial fix for https://github.com/miloyip/rapidjson/issues/622
2017-09-05 16:58:09 -07:00
Milo Yip
1e46091009 Merge pull request #1051 from gongminmin/master
Specifies the endian of msvc ARM64 configuration.
2017-09-04 10:50:04 +08:00
Milo Yip
e9373fc130 Merge pull request #1052 from Crunkle/master
Fix cross-compilation on certain toolchains
2017-09-04 10:32:55 +08:00
Crunkle
9ce6a7ebb8 Fix processor check when empty 2017-09-02 21:05:00 +01:00
Minmin Gong
f91405801f Specifies the endian of msvc ARM64 configuration. 2017-08-31 23:16:59 -07:00
Milo Yip
f05edc9296 Merge pull request #1034 from bluehero/master
Allow Swap with ValueType
2017-08-07 16:46:52 +08:00
bluehero
f9004b90c5 modify 2017-08-07 13:09:22 +08:00
bluehero
c831675026 modify 2017-08-07 11:58:37 +08:00
bluehero
5fb06596a9 modify 2017-08-07 11:44:27 +08:00
bluehero
8ba1f84f47 modify unittest 2017-08-05 20:39:31 +08:00
bluehero
9eb7bf895c add unittest 2017-08-05 18:12:44 +08:00
bluehero
7c1f208253 modify 2017-08-05 16:53:45 +08:00
bluehero
f7dd496cdd Merge pull request #1 from miloyip/master
Update
2017-08-05 14:06:44 +08:00
Milo Yip
d6305514ff Merge pull request #1030 from bmuzzin/issue1028_natvis
Issue #1028: Visual Studio natvis file.
2017-07-28 10:32:40 +08:00
Bart Muzzin
707fd36afa Issue #1028: Visual Studio natvis file. 2017-07-27 22:17:31 -04:00
Milo Yip
c34e3dfc72 Merge pull request #1018 from miloyip/issue1017_allOfHandler
Fix #1017 allOf keyword fail with Writer handler
2017-07-13 16:57:56 +08:00
Milo Yip
fcd2e1f60c Fix #1017 allOf keyword fail with Writer handler
Gave up using static binding for null handler, because it cannot be
used with arbitrary handler type. Change `OutputHandler handler_` to
pointer type.
2017-07-13 16:07:36 +08:00
Milo Yip
1a77513e6d Merge pull request #1013 from pah/fixes/1010-assert-stringref
GenericStringRef: move assert out of expression
2017-07-11 10:25:47 +08:00
Milo Yip
2d27ce46bc Merge pull request #1012 from pah/fixes/993-doxygen-internals
travis-doxygen.sh: upgrade to Doxygen 1.8.13
2017-07-11 10:24:55 +08:00
Philipp A. Hartmann
70171f9790 GenericStringRef: move assert out of expression 2017-07-10 22:32:18 +02:00
Philipp A. Hartmann
7161894f40 travis-doxygen.sh: upgrade to Doxygen 1.8.13
* Upgrade to the latest Doxygen version 1.8.13
 * Drop unused variable DOXYGEN_BIN
 * Reenable --single-branch (travis-ci/travis-ci#5225 is closed)
2017-07-10 21:32:16 +02:00
Milo Yip
37ea16df9d Merge pull request #1009 from pah/setup/travis-trusty
Travis: Switch to Ubuntu 14.04 (Trusty)
2017-07-10 10:08:51 +08:00
Milo Yip
f624a3037c Merge pull request #1010 from pah/fixes/817-stringref-null
Improve handling of NULL strings
2017-07-10 10:08:21 +08:00
Milo Yip
73df6c9325 Merge pull request #1008 from pah/fixes/989-parseresult
ParseResult: improve bool conversion and add operator!=
2017-07-10 10:07:50 +08:00
Milo Yip
4da20e21c6 Merge pull request #1002 from FluxLemur/patch-1
Tutorial: fix typos in examples and broken links
2017-07-10 10:07:02 +08:00
Philipp A. Hartmann
47c3c1ec9f Improved handling of NULL strings
* Safely assert upon passing NULL string without length
   (requires usage of RAPIDJSON_ASSERT within an expression)
 * Allow using a NULL string together with an explicit length 0
   (GenericStringRef, GenericValue::SetString, ...), see #817
 * Add GenericValue::SetString(StringRefType, Allocator&) overload
 * Add tests for the various cases
2017-07-09 14:46:59 +02:00
Philipp A. Hartmann
f1ba61c7ba unittest.h: change RAPIDJSON_ASSERT to allow usage in expressions 2017-07-09 14:31:29 +02:00
Philipp A. Hartmann
eefb618ec9 Travis: Switch to Ubuntu 14.04 (Trusty) 2017-07-09 11:40:56 +02:00
Philipp A. Hartmann
14218aeb0a ParseResult: improve bool conversion and add operator!=
* Use safe-bool idiom for boolean conversion to avoid accidental
   misuse of ParseResult values (closes #989)
 * Add operator!= to support more comparison expressions
   (previously silently/erroneously used operator bool)
2017-07-09 11:13:31 +02:00
Leo Mehr
3aafe12c91 undo changes to links and some minor changes to make the readme more easily readable 2017-06-30 12:42:06 -04:00
Leo Mehr
0d62f5cd35 Tutorial: fix typos in examples and broken links
In the move example, the code uses `contacts` when the diagrams use
`contact` (no 's')

The code in the example:
```    Value contacts(kArrayType);
    // adding elements to contacts array.
    // ...
    o.AddMember("contacts", contacts, d.GetAllocator());  // deep clone contacts (may be with lots of allocations)
    // destruct contacts.
```
2017-06-29 20:27:23 -04:00
Milo Yip
2f45319b4e Merge pull request #968 from TomaszNo/icc-preprocessor-guard
Intel C++ Compiler preprocessor guard for #pragma intrinsic - diyfp.h
2017-06-28 11:36:55 +08:00
Milo Yip
77ae0b9795 Merge pull request #987 from sledgeh/master
Fixed #985 : Unittest failed with MinGWx64. And few small improvement…
2017-06-28 11:36:06 +08:00
Milo Yip
6a8f672ca1 Merge pull request #994 from Chocobo1/svg
Improve readme.md
2017-06-21 17:01:54 +08:00
Chocobo1
a31a380cb8 Improve readme.md
Add alt text for images
Use https whenever possible
Update URLs
Use tools.ietf.org for RFC7159
Correct indent for sublists
Trim trailing whitespaces
2017-06-21 14:40:46 +08:00
kyb
6e81d49b33 Fixed #985 : Unittest failed with MinGWx64. And few small improvement were done while looking for mistakes.
Problem was because of Windows uses backslashes '\', not Unix '/'
2017-06-15 13:24:01 +03:00
Milo Yip
b596f4e990 Merge pull request #977 from miloyip/issue825_patternProperties
Fix patternProperties & additionalProperties lead to ASSERT
2017-06-09 15:06:11 +08:00
Milo Yip
df6362d450 Fix patternProperties & additionalProperties lead to ASSERT
Fix #825
2017-06-09 10:16:24 +08:00
Milo Yip
342a616a7f Merge pull request #969 from pah/fixes/962-copy-const-strings
Fixup #964 by forwarding copyConstStrings recursively
2017-05-28 14:49:15 +08:00
Philipp A. Hartmann
68c96e987b Fixup #964 by forwarding copyConstStrings recursively
As reported by @Llerd in #962, the `copyConstStrings` parameter
has not been forwarded recursively to the constructors of
object members and array elements.
2017-05-27 10:26:35 +02:00
Milo Yip
33443e63a9 Merge pull request #967 from TomaszNo/storage-class-first
Storage class is not first - encodings.h
2017-05-26 06:25:12 +08:00
Tomasz Noczynski (Linux)
294ad93e30 To avoid Intel C++ Compiler #1879 warnings:
warning #1879: unimplemented pragma ignored: #pragma intrinsic(_BitScanReverse64)
warning #1879: unimplemented pragma ignored: #pragma intrinsic(_umul128)
2017-05-25 14:14:16 +02:00
Tomasz Noczynski (Linux)
77d2fadfb6 If storage class is not specified as first in declaration then Intel C++ Compiler 2017 generates message:
message #82: storage class is not first
2017-05-25 13:21:57 +02:00
Milo Yip
3202b0a3dd Merge pull request #964 from pah/fixes/962-copy-const-strings
GenericValue::CopyFrom: add option to force copying of strings
2017-05-19 09:47:15 +08:00
Philipp A. Hartmann
4ef1ff4fba GenericValue::CopyFrom: add option to force copying of strings
Copying the result of an in-situ parsing into another value/document
currently requires that the original buffer - still holding the strings
from the parsing, outlives the  destination object as well.

In order to obtain a "full" copy of a GenericValue, this commit adds
an optional flag `copyConstStrings` to `CopyFrom`, which then forces
to take a copy of all embedded strings in the source value.

This solves the problem discussed in #962.
2017-05-18 19:11:04 +02:00
Milo Yip
0033268c11 Update tutorial.zh-cn.md
typo
2017-05-12 17:30:33 +08:00
Milo Yip
56b7216efe Fix #949 about -Werror=conversion 2017-05-12 10:32:41 +08:00
Milo Yip
f8eb7bae89 Remove -Weverything
See #930
2017-05-12 10:32:06 +08:00
Milo Yip
b61bbbfe37 Fix #947 -Weffc++ warning 2017-05-11 16:41:26 +08:00
Milo Yip
67b062b3c6 Merge pull request #946 from hwiesmann/master
Add convenience method Key(std::basic_string<Ch> const&) to Writer
2017-05-11 10:04:29 +08:00
Hartwig
568107e178 Add convenience method Key(std::basic_string<Ch> const&) to Writer 2017-05-10 22:56:01 +02:00
Milo Yip
fe2b3603e7 Merge pull request #941 from harrywong/master
Add fallthrough attribute to suppress GCC 7.1 warning
2017-05-04 17:23:38 +08:00
Harry Wong
cba45fe9de Onley apply to GCC 7 2017-05-04 10:32:45 +08:00
Harry Wong
fe19b7b601 Supress implicit fallthrough in GCC 2017-05-04 10:08:48 +08:00
Milo Yip
a13acda972 Merge pull request #937 from bytePro17124/patch-1
typo
2017-04-30 13:37:52 +08:00
Matthew Early
4fe02e15f9 typo 2017-04-29 16:07:23 -04:00
Milo Yip
b45c5408d1 Merge pull request #932 from JunHe77/master
Added ARM-Neon support for SIMD.SkipWhitespace*
2017-04-24 16:22:14 +08:00
Milo Yip
d2fce92438 Merge pull request #933 from OlegHahm/minor_fixes
Minor fixes
2017-04-22 10:58:02 +08:00
Oliver Hahm
885b5cd2f9 common notation of empty if/else case 2017-04-21 14:49:30 +02:00
Oliver Hahm
63423eb6f8 fix return values 2017-04-21 14:49:12 +02:00
Alejandro Martinez
2291258bb8 Added ARM-Neon support for SIMD.SkipWhitespace*
Change-Id: Iaf210d029758723a7eeb7f28fc10cab7467889a9
Signed-off-by: Jun He <jun.he@arm.com>
2017-04-21 07:33:17 +00:00
Milo Yip
e6d7247ed9 Merge pull request #924 from lichray/fix-gcc7-warning
Fix a non-type template parameter type mismatch
2017-04-17 14:44:08 +08:00
Milo Yip
c6aec19ed8 Merge pull request #930 from pah/feature/cxx11-static_assert
RAPIDJSON_STATIC_ASSERT: use C++11 static_assert, if available
2017-04-16 17:48:45 +08:00
Philipp A. Hartmann
f93a29bec2 RAPIDJSON_STATIC_ASSERT: use C++11 static_assert, if available 2017-04-14 20:19:16 +02:00
Zhihao Yuan
ec90588c72
Fix a non-type template parameter type mismatch
This issues a warning in gcc7.
2017-04-08 22:51:15 -05:00
Milo Yip
fcd263c61a Merge pull request #923 from miloyip/issue910_casting
Fix #910 incorrect casting
2017-04-07 15:05:47 +08:00
Milo Yip
77f643dc51 Fix #910 incorrect casting 2017-04-07 10:23:30 +08:00
Milo Yip
5d9d0f78b5 Merge pull request #909 from miloyip/issue905_PrettyWriterWriteFlags
Fix #905 unable to set writeFlags for PrettyWriter
2017-03-27 18:26:17 +08:00
Milo Yip
d88be8ef16 Fix #905 unable to set writeFlags for PrettyWriter 2017-03-27 14:05:03 +08:00
Milo Yip
b8f0414b9a Merge pull request #907 from almavi/master
Fixed bug on space hexadecimal encoding
2017-03-25 11:10:48 +08:00
Alejandro Martinez
85500e8c8f Changed error code for invalid special ascii chars, fixed writer tests 2017-03-24 13:37:23 +00:00
Alejandro Martinez
3c6e2cf030 Added unittests for invalid ascii control chars 2017-03-23 10:14:17 +00:00
Alejandro Martinez
da4fd6794c Fixed bug on space hexadecimal encoding 2017-03-22 10:19:54 +00:00
Milo Yip
430e8d4c9b Update schema.zh-cn.md 2017-03-20 11:20:04 +08:00
Milo Yip
3f78a026c7 Merge pull request #903 from shadeware/patch-1
fix typos in doc code
2017-03-20 11:18:56 +08:00
shadeware
a38104a165 fix typos in doc code 2017-03-19 03:03:36 +03:00
John Stiles
1391e42579 Merge pull request #3 from miloyip/master
Merge back
2017-03-17 10:26:47 -07:00
Milo Yip
e5635fb27f Fix #899 2017-03-16 10:46:48 +08:00
Milo Yip
0bc856a747 Merge pull request #894 from belveder79/master
update to create config file which is independent from actual install…
2017-03-16 10:37:07 +08:00
Milo Yip
bba388b4fa Merge pull request #896 from StilesCrisis/writer-flush-api
Writer flush api
2017-03-16 10:36:25 +08:00
Milo Yip
465fab45c1 Merge pull request #897 from StilesCrisis/issue-889-pretty-writer
Issue 889 pretty writer
2017-03-16 10:35:26 +08:00
John Stiles
d5d18cf694 Fix template length optimization issue in PrettyWriter
Missed PrettyWriter in the initial fix for Issue #889
2017-03-14 23:48:41 -07:00
John Stiles
31c6c50ac6 Provide a Flush() API within Writer
This is helpful if you’re writing code that needs to control flush
behavior and you don’t want to pass around your buffer object to each
handler function alongside the writer. Seems like an easy convenience
to add.
2017-03-14 23:28:59 -07:00
John Stiles
c7703f8313 Merge branch 'lookahead-parser-improvements' into writer-flush-api 2017-03-14 23:23:18 -07:00
John Stiles
5b593bba19 Merge pull request #2 from miloyip/master
Merge back
2017-03-14 15:41:53 -07:00
Clemens Arth
b91c515afe update to create config file which is independent from actual install location 2017-03-14 10:27:36 +01:00
John Stiles
f0c108b5c9 Remove all switch 2017-03-13 07:53:37 -07:00
John Stiles
6723e3296a Initialize v_ to placate GCC
v_ has a value assigned to it as part of ParseNext() which happens in
the constructor, but that’s not soon enough for GCC
2017-03-13 07:43:26 -07:00
John Stiles
bf19c1a0be Remove switch
GCC and Clang cannot agree on what constitutes a good switch statement.
2017-03-13 07:40:51 -07:00
Milo Yip
266870df8e Merge pull request #890 from StilesCrisis/issue-889
Issue 889
2017-03-13 15:41:06 +08:00
John Stiles
e7fd707698 Improve LookaheadParser
Fix clang -Wswitch-enum warnings.
Made NextArrayValue() more robust—now handles error state correctly,
will enter error state if an unexpected state is reached.
Made separate states for each value type to simplify getters.
Simplified implementation of skipping arrays and objects.
Skipping an object now works whether you’ve retrieved the key or not.
2017-03-13 00:33:10 -07:00
John Stiles
55f8a32020 Remove broken templatized string length optimization
It did not support char arrays.
2017-03-12 23:47:59 -07:00
John Stiles
84a0356608 Add unit test for Issue 889 2017-03-12 23:40:54 -07:00
StilesCrisis
33a9f58509 Merge remote-tracking branch 'miloyip/master' 2017-03-08 23:55:03 -08:00
Milo Yip
5de06bfa37 Merge pull request #882 from StilesCrisis/lookaheadparser
Lookahead Parser
2017-03-09 09:32:15 +08:00
John Stiles
260e2f372e Merge remote-tracking branch 'refs/remotes/origin/lookaheadparser' 2017-03-08 15:18:53 -08:00
John Stiles
036f300210 Merge remote-tracking branch 'refs/remotes/miloyip/master' 2017-03-08 14:59:11 -08:00
Milo Yip
2df32fbfa0 Merge pull request #881 from TedLyngmo/issue_874_Werror_effcplusplus
Fix -Werror=effc++ errors with GNU 6.3.1
2017-03-08 17:31:45 +08:00
StilesCrisis
8da89f54bd Fix GCC warning 2017-03-08 01:16:19 -08:00
StilesCrisis
d4669bbc8e Add lookahead parser example 2017-03-08 01:08:41 -08:00
Ted Lyngmo
ef22ca1732 Fix -Werror=effc++ errors with GNU 6.3.1
Fix "'MyHandler::type’ should be initialized in the member
initialization list [-Werror=effc++]" errors.

https://github.com/miloyip/rapidjson/issues/874
2017-03-08 09:47:38 +01:00
Ted Lyngmo
c64f378f16 Fix -Werror=effc++ errors with GNU 6.3.1
Fix "'MyHandler::type’ should be initialized in the member
initialization list [-Werror=effc++]" errors.

https://github.com/miloyip/rapidjson/issues/874
2017-03-08 06:25:41 +01:00
John Stiles
237d2f2ea3 Merge remote-tracking branch 'miloyip/master' 2017-03-05 21:27:54 -08:00
Milo Yip
a1fac159d7 Merge pull request #872 from StilesCrisis/issue845_native_strlen
Use native strlen
2017-03-06 09:50:43 +08:00
John Stiles
c4e3d6243c Fix msvc x64 compilation issue
Disambiguate by putting the ENABLEIF on the return value instead of in
the argument list.
2017-03-05 09:50:03 -08:00
John Stiles
cdea825a0b Assert that String() and Key() are given null-terminated strings
Assert in case users attempt to pass a char array to String() or Key()
that is not null terminated; that is not the intended use of the API.
Null terminate your string buffers.
2017-03-05 09:23:03 -08:00
John Stiles
61f8c4ef0d Quoted strings to String() or Key() are auto-sized by template
Same fix as previous commit, to prettywriter
2017-03-05 00:38:34 -08:00
John Stiles
dd97ede84d Quoted strings to String() or Key() are auto-sized by template
No strlen call needs to be made when templates can auto-deduce the
string length. No strlen = faster!

Unfortunately this needs a touch of  SFINAE to allow multiple overrides
to coexist cleanly.
2017-03-05 00:27:08 -08:00
John Stiles
7116c355df Merge remote-tracking branch 'miloyip/master' into issue845_native_strlen 2017-03-05 00:19:19 -08:00
Milo Yip
02de69892c Merge pull request #876 from erikfroseth/issue-875
Remove executable bit
2017-03-03 17:46:07 +08:00
Erik Froseth
d6e9cf5d54 Remove executable bit
Remove the executable bit for various .json files
2017-03-03 09:48:41 +01:00
John Stiles
66b564f385 Remove unneeded change 2017-03-03 00:42:21 -08:00
John Stiles
db8d3bb4d6 Remove unneeded change 2017-03-03 00:42:00 -08:00
John Stiles
6ae50ad6e3 Once again 2017-03-03 00:27:47 -08:00
John Stiles
534f135261 Try again to suppress Valgrind 2017-03-03 00:21:10 -08:00
John Stiles
3f9ebfe9e9 Trivial change to trigger Travis CI 2017-03-02 21:24:03 -08:00
John Stiles
13e99d8d5f Trivial change to re-trigger Travis CI
No-op blank line
2017-02-28 22:58:24 -08:00
Milo Yip
9ae349c622 Merge pull request #871 from StilesCrisis/token-by-token-doc
Token-by-token parser documentation
2017-03-01 14:51:12 +08:00
John Stiles
4b822a41af Attempt to suppress valgrind wcslen error 2017-02-28 19:31:21 -08:00
StilesCrisis
6e2e5c7dbe Specialize StrLen for char/wchar_t
Compilers generally provide a much smarter strlen than ours.
2017-02-28 01:11:30 -08:00
StilesCrisis
f349456bc5 Merge remote-tracking branch 'miloyip/master' into issue845_native_strlen 2017-02-28 01:09:58 -08:00
StilesCrisis
0f3bf99d58 Tiny fix
Make example code var names match API above for consistency
2017-02-28 00:08:30 -08:00
StilesCrisis
5c2bb18772 Add IterativeParse docs 2017-02-28 00:06:02 -08:00
Milo Yip
e6b192a75c Merge pull request #869 from StilesCrisis/writer-key-fix
Writer EndObject missing-value fix
2017-02-28 16:02:52 +08:00
Milo Yip
9cabd6372d Merge pull request #870 from StilesCrisis/null-handler-fix
Null handler fix
2017-02-28 16:02:22 +08:00
StilesCrisis
4643104b8a Fix null handler construction
We should not malloc the null-handler object and cast to OutputHandler;
we need to actually invoke the constructor via placement new.
2017-02-27 23:28:25 -08:00
StilesCrisis
0ec4e86f14 Unit test
Add unit test for Issue 848 (segfault in ~Document)
2017-02-27 23:06:05 -08:00
StilesCrisis
fa84cd18f4 Add matching fix for PrettyWriter
PrettyWriter EndObject will now also assert if called when a key is
missing its matching value.
2017-02-27 22:53:59 -08:00
StilesCrisis
2e9b7b1ae6 Added assertion
Documented existing assertions in EndObject
Added new assertion in EndObject to catch error condition where objects
are ended with a key but no matching value.
2017-02-27 22:44:13 -08:00
StilesCrisis
595b114216 Unit test
Add unit tests expecting an assertion when writing an object with a key
but no value.
2017-02-27 22:36:48 -08:00
StilesCrisis
26e089b9a2 Merge remote-tracking branch 'miloyip/master' 2017-02-27 21:37:20 -08:00
Milo Yip
97e2f7f16f Try fixing Error compilation Ubuntu 14.04 #834 2017-02-28 09:48:36 +08:00
Milo Yip
7f753fe76b Merge pull request #867 from oviradoi/issue858
Fix creating the nuget package with Raggles' fork of CoApp
2017-02-26 22:38:23 +08:00
Milo Yip
82295b1f4d Merge pull request #842 from StilesCrisis/token-by-token-parsing
Token-by-token pull parsing
2017-02-26 22:36:04 +08:00
Milo Yip
a677b85706 Merge pull request #866 from ylavic/patch-1
Missing "internal" namespace for StrLen
2017-02-26 22:32:40 +08:00
oviradoi
5f92c3926b Fix creating the nuget package with Raggles' fork of CoApp 2017-02-24 19:50:36 +02:00
ylavic
b977fd3c9d Missing "internal" namespace for StrLen
include/rapidjson/pointer.h:243:40: error: 'StrLen' was not declared in this scope
         return Append(name, StrLen(name), allocator);
2017-02-24 16:46:53 +01:00
Milo Yip
0eaa0d288c Merge pull request #862 from StilesCrisis/nan-inf-parse-fix
NaN/Inf parse fix
2017-02-24 09:47:11 +08:00
StilesCrisis
ecf3d64293 Merge branch 'nan-inf-parse-fix' into token-by-token-parsing 2017-02-23 00:19:07 -08:00
StilesCrisis
5e785d3db2 Fix parsing of NaN/Inf
A failed half-consume of “NaN” now returns “value invalid” instead of
attempting to consume an “Inf”.
2017-02-23 00:11:12 -08:00
StilesCrisis
c4117c68cc Put in unit tests to catch parser failure
Noticed that the reader could over-consume “NaN” if token terminated in
the middle.
2017-02-22 21:54:31 -08:00
John Stiles
bd4c282d77 Test coverage up
Add more tests! Good for coverage.
2017-02-07 01:08:51 -08:00
John Stiles
0f8389e787 Restored original IterativeParse implementation
Runs about 1-2% faster (original speed) by running in a tight loop, at
the expense of slight code duplication with IterativeParseNext.
2017-02-07 00:02:08 -08:00
John Stiles
488252eca2 Merge remote-tracking branch 'miloyip/master' into token-by-token-parsing 2017-02-06 21:12:52 -08:00
John Stiles
933eb839d9 Merge remote-tracking branch 'miloyip/master' 2017-02-06 21:11:55 -08:00
Milo Yip
0163a53f4a Merge pull request #841 from StilesCrisis/improve-unit-test-reporting
Improved reporting
2017-02-06 09:15:05 +08:00
StilesCrisis
a11ec69796 More C++98 fixes 2017-02-04 01:18:46 -08:00
StilesCrisis
6288d95d1e SimplePullReader C++98 support
std::to_string can’t be used because it requires C++11.
2017-02-04 01:07:00 -08:00
StilesCrisis
4232e407f4 Clean up example code 2017-02-04 00:47:43 -08:00
StilesCrisis
d84d5fe055 Add example SimplePullHandler code
Example code to demonstrate how the token-pulling reader can be used.
2017-02-04 00:41:34 -08:00
StilesCrisis
4394b3bac7 Add LIKELY and UNLIKELY hints
Doesn’t seem to affect timings in perftest on my machine, but it may
help others.
2017-02-04 00:05:34 -08:00
StilesCrisis
82a423db7d Added unit test for pull parsing
New unit test which ensures that IterativeParseNext always generates
exactly one element at a time, and that calling IterativeParseNext on a
complete document is harmless and generates zero events.
2017-02-03 21:12:53 -08:00
StilesCrisis
116f65994b Improve coverage and performance
Further improvement to perftest and hoping to make coveralls happy.
2017-02-03 18:58:37 -08:00
StilesCrisis
5de7258478 Improve performance
Slight performance improvement over previous submission
2017-02-03 17:14:14 -08:00
StilesCrisis
1a7c5ea517 Fix Dev Studio bool-conversion warning 2017-02-03 00:29:43 -08:00
StilesCrisis
20f5caa8f6 Token-by-token pull parsing
Refactored the iterative parser so that users can parse a single JSON
element at a time (invoking the handler one time) and then return
control to the calling code. Call IterativeParseInit to start, and then
call IterativeParseNext to retrieve one JSON element. Use
IterativeParseComplete to check for JSON document completion.
2017-02-02 23:25:29 -08:00
StilesCrisis
6769f3e33e Improved reporting
Add “filename” to the error message when JsonChecker reports an error.
2017-02-02 23:18:07 -08:00
Milo Yip
738864c53c Remove non-ASCII character
Fix #824
2017-01-24 15:08:38 +08:00
Milo Yip
3693e942b7 Fix output character type in writers 2017-01-24 14:54:50 +08:00
Milo Yip
942bb46088 Merge pull request #827 from lichray/fix-signed
Treat signed-unsigned conversions as errors.
2017-01-24 14:35:17 +08:00
Milo Yip
265fb6ee88 Fix #831 RAPIDJSON_HAS_CXX11_RANGE_FOR is error defined 2017-01-24 09:28:52 +08:00
Zhihao Yuan
3cc77d5d63
Treat signed-unsigned conversions as errors. 2017-01-18 18:09:18 -06:00
Milo Yip
835f2f4a79 Update Doxyfile.zh-cn.in
Change internals from English to Chinese
2016-12-31 14:51:07 +08:00
Milo Yip
e61b66c38a Merge pull request #816 from SuperSodaSea/master
Translate doc/internals.md into Chinese
2016-12-31 14:49:51 +08:00
SuperSodaSea
dba9816009 Translate doc/internals.md Part 2 2016-12-31 11:23:05 +08:00
SuperSodaSea
af4ec9b7e9 Translate doc/internals.md Part 1 2016-12-30 23:12:41 +08:00
Milo Yip
03a7391049 Merge pull request #757 from patcheng/feature/fix_clang_warning
added assertion to help suppress clang warnings
2016-12-23 10:00:30 +08:00
Milo Yip
369e07d1c9 Merge pull request #811 from glebov-andrey/improved_new_macro
Improved customization of RAPIDJSON_NEW macro
2016-12-23 09:59:31 +08:00
Andrey Glebov
41ceb8624f - replaced RAPIDJSON_NEW with C++98 compatible version 2016-12-21 14:03:53 +03:00
Andrey Glebov
3f120caeef - replaced RAPIDJSON_NEW calls in fwdtest.cpp 2016-12-21 10:41:06 +03:00
Andrey Glebov
9fe93bb984 - replaced RAPIDJSON_NEW macro with variadic varient 2016-12-21 10:17:25 +03:00
Milo Yip
014097e51a Merge pull request #800 from ivankravets/patch-3
Update version to 1.1.0
2016-11-28 20:18:54 +08:00
Ivan Kravets
ba34c94533 Update version to 1.1.0 2016-11-28 12:53:24 +02:00
Milo Yip
0024592c23 Update sax.zh-cn.md 2016-11-21 09:50:59 +08:00
Milo Yip
bff326fb24 Update sax.md 2016-11-21 09:37:02 +08:00
Milo Yip
eb6831a4c2 Merge pull request #790 from SuperSodaSea/master
修复拼写错误
2016-11-05 14:07:45 +08:00
SuperSodaSea
a077baa9c3 修复拼写错误 2016-11-05 11:55:12 +08:00
Milo Yip
fbcd7acfd3 Merge pull request #788 from miloyip/issue786_CopyFrom
Refactor GenericValue deep-clone constructor
2016-10-31 19:49:47 +08:00
Milo Yip
e07d0e9438 Move GenericValue deep-clone constructor into the class declaration. 2016-10-31 18:28:53 +08:00
Milo Yip
95b346c3ca Refactor GenericValue deep-clone constructor 2016-10-31 18:24:17 +08:00
Milo Yip
d57944fc2b Merge pull request #783 from FrozenGene/master
[POWER][XL Compiler] support IBM PowerPC / ppc64 / ppc64le and XL compiler
2016-10-26 20:27:09 +08:00
Wu Zhao
c4db88a314 support IBM PowerPC / ppc64 / ppc64le and XL compiler
Avoid POWER platform compiling error and support IBM XL C++ compiler on
Linux / AIX.
2016-10-26 17:27:54 +08:00
Milo Yip
381d8f85e7 Merge pull request #782 from miloyip/issue781_aix
Remove empty NumberStream::~NumberStream()
2016-10-26 09:28:38 +08:00
Milo Yip
d7dd4106ea Remove empty NumberStream::~NumberStream()
Fix #781
2016-10-25 18:21:01 +08:00
Milo Yip
d6c8b378d4 Merge pull request #777 from miloyip/issue728_threadsafe
Fix nullHandler allocation bug
2016-10-21 17:35:53 +08:00
Milo Yip
992b7f5f8e Fix nullHandler allocation bug 2016-10-21 12:25:37 +08:00
Milo Yip
fba9ebd9bc Merge pull request #776 from miloyip/issue728_threadsafe
Remove singletons in schema classes
2016-10-20 14:01:32 +08:00
Milo Yip
59bcebbf3d Merge pull request #773 from bluehero/master
use _mm_cmpistri
2016-10-18 14:38:39 +08:00
Milo Yip
bf0cc7bea8 Fixed a bug for SchemaDocument move constructor 2016-10-18 13:53:00 +08:00
bluehero
31ace3b767 use _mm_cmpistri 2016-10-18 12:54:42 +08:00
Milo Yip
7c4e511eb0 Change Schema::GetTypeless() from singleton to instance
Now owned by SchemaDocument::typeless_, and be shared to its
Schema::typeless_
2016-10-18 11:37:15 +08:00
Milo Yip
ddbd2ef05d Restore missing deallocation of GenericSchemaValidator::nullHandler_ 2016-10-18 10:14:00 +08:00
Milo Yip
b963eb447b Change SchemaValidator::GetNullHandler() from singleton to instance. 2016-10-17 18:30:18 +08:00
Milo Yip
97fb9bc85b Merge pull request #770 from miloyip/issue728_threadsafe
Fixed another crash bug in #728
2016-10-17 15:35:01 +08:00
Milo Yip
3b1a037499 Merge pull request #748 from sfinktah/sfinktah-minwindef-fix
Fix for winmindef.h defining min/max macros
2016-10-17 14:29:10 +08:00
Milo Yip
517dd4dbb8 Fix failing to resolve $ref in allOf causes crash in SchemaValidator::StartObject() 2016-10-17 14:25:24 +08:00
Milo Yip
9b6af55525 Merge branch 'master' into issue728_threadsafe 2016-10-17 09:50:18 +08:00
Milo Yip
2363227974 Add Value::Value(float) and static_cast for suppressing clang warning 2016-10-14 22:03:54 +08:00
Milo Yip
8eaa122c27 Update dom.zh-cn.md 2016-10-06 13:32:16 +08:00
Milo Yip
94b36dc97e Merge pull request #763 from miloyip/issue762_move
Remove unncessary std::move()
2016-10-05 17:32:16 +08:00
Milo Yip
3f23397596 Remove unncessary std::move()
Fixes #762
2016-10-05 15:02:31 +08:00
Milo Yip
11df748a3b Revert "Another try for fixing schema.md"
This reverts commit c490d880a3e18d315af0afbe5e8b54c7179d6df0.
2016-10-05 10:21:45 +08:00
Milo Yip
c490d880a3 Another try for fixing schema.md 2016-10-05 09:41:56 +08:00
Milo Yip
a3300bf4b1 Fix schema.zh-cn.md 2016-10-05 09:21:06 +08:00
Milo Yip
ba56498d10 Merge pull request #760 from icechen1/patch-1
FIx typo in documentation
2016-10-05 09:19:38 +08:00
Yu Chen Hou
48f8364f65 FIx typo in documentation
The use of the vertical bar seems to break the rendering of the table in the documentation here:
http://rapidjson.org/md_doc_schema.html

Seems like we can fix it by using html encoding for the vertical bars as described in this post:
http://stackoverflow.com/questions/17319940/how-to-escape-a-pipe-char-in-a-code-statement-in-a-markdown-table/17320389#17320389
2016-10-04 14:07:50 -07:00
Milo Yip
b4dae2b77d Merge pull request #755 from AdamMajer/fix_old_gcc
Fix compilation with older GCC versions
2016-10-01 15:46:21 +08:00
Patrick Cheng
95224aff7d When length is 0, the code does nothing, so skip it completely.
Previously, os.Push(0) would do nothing as well. But with the newly added assertion, is the stack is empty, it will fail the assertion.
2016-09-30 13:44:15 -07:00
Patrick Cheng
91a803d463 Reserve() is sometimes called when stackTop_ is null. The assert is invalid. 2016-09-30 11:12:23 -07:00
Patrick Cheng
9d8df28c1d added assertion to help suppress clang warnings 2016-09-30 10:47:00 -07:00
Adam Majer
cb017cbf5e Fix compilation with older GCC versions
Older GCC versions fail compiling RapidJSON due to a warning

include/rapidjson/reader.h:578: error: suggest a space before ';' or explicit braces around empty body in 'while' statement
: warnings being treated as errors
2016-09-30 17:10:04 +02:00
Milo Yip
ffc7942857 Merge pull request #750 from bennyyip/master
fix #749
2016-09-25 21:30:39 +08:00
BennyYip
6a15e40b6e fix #749 2016-09-25 21:16:26 +08:00
Sfinktah Bungholio
51a31ce006 Fix for winmindef.h defining min/max macros 2016-09-25 20:36:33 +10:00
Milo Yip
7a39172771 Merge pull request #746 from miloyip/issue744_stringbuffergetlength
Add StringBuffer::GetLength()
2016-09-22 19:04:35 +08:00
Milo Yip
5cd62c235d Add StringBuffer::GetLength()
Fix #744
2016-09-22 18:11:22 +08:00
Milo Yip
0761ac126b Remove lambda expression in (pretty)writertest 2016-09-21 21:49:49 +08:00
Milo Yip
f28203c7a1 Fix #741 2016-09-21 11:09:04 +08:00
Milo Yip
185a7cc210 Merge pull request #740 from CreoValis/writer-move-ctor
Move constructor support for Writer
2016-09-20 09:35:33 +08:00
Tallódi Mihály
1a64cd0997 Tests for Writer, PrettyWriter move constructors 2016-09-19 22:13:33 +02:00
Tall??di Mih??ly
62dc1077eb Move constructor support for PrettyWriter 2016-09-19 21:47:27 +02:00
Tall??di Mih??ly
307e021606 Move constructor support for Writer
This also requires turning off the c++98 compatibility checks when building
with clang.
2016-09-19 21:47:27 +02:00
Milo Yip
52682115fb Merge pull request #739 from miloyip/issue728_threadsafe
Refactor regex
2016-09-16 13:36:36 +08:00
Milo Yip
769185d68b Refactor regex
Remove mutable which causes reentrant issue
2016-09-16 12:13:02 +08:00
Milo Yip
328ead0e17 Merge pull request #732 from miloyip/issue731_writerstringassert
Add preconditions in writer and string functions
2016-09-03 23:53:40 +08:00
Milo Yip
3e2172bd52 Add preconditions in writer and string functions 2016-09-03 23:37:00 +08:00
Milo Yip
8979c14fb6 Merge branch 'master' into issue716_parsebyparts 2016-09-03 23:24:56 +08:00
Milo Yip
9f66882898 Merge pull request #730 from myd7349/master
Fix typo in doc
2016-09-02 17:49:20 +08:00
myd7349
6023ed3a0c Fix typo in doc 2016-09-02 17:35:40 +08:00
Milo Yip
cdb3454283 Merge pull request #723 from niukuo/master
fix wrong length in remote schema
2016-09-01 10:04:35 +08:00
niukuo
250cf666d3 fix wrong length in remote schema
Change-Id: Ia96ddf5746f1c18968e9e086f17fe4a24b8480d7
2016-08-31 16:26:27 +08:00
Milo Yip
9bd618f545 Merge pull request #719 from yachoor/remove_broken_assignment
Remove non-compiling assignment operator
2016-08-29 10:30:04 +08:00
Milo Yip
0f9dbe0a9c Defer thread creation in parsebypart example 2016-08-29 10:17:57 +08:00
Janusz Chorko
862c39be37 Explicitly disable copy assignment operator 2016-08-26 21:26:50 +02:00
Janusz Chorko
3b2441b87f Removed non-compiling assignment operator. Fixed #718 2016-08-26 21:17:38 +02:00
150 changed files with 14362 additions and 2388 deletions

4
.gitignore vendored
View File

@ -3,6 +3,7 @@
!/bin/encodings
!/bin/jsonchecker
!/bin/types
!/bin/unittestschema
/build
/doc/html
/doc/doxygen_*.db
@ -23,3 +24,6 @@ Doxyfile
Doxyfile.zh-cn
DartConfiguration.tcl
*.nupkg
# Files created by OS
*.DS_Store

View File

@ -1,10 +1,18 @@
sudo: required
dist: precise
dist: xenial
language: cpp
cache:
- ccache
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- cmake
- valgrind
- clang-8
env:
global:
- USE_CCACHE=1
@ -13,49 +21,96 @@ env:
- CCACHE_MAXSIZE=100M
- ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit
- ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit
- GITHUB_REPO='miloyip/rapidjson'
- ARCH_FLAGS_aarch64='-march=armv8-a'
- GITHUB_REPO='Tencent/rapidjson'
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
before_install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386
matrix:
include:
# gcc
- env: CONF=release ARCH=x86 CXX11=ON
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
- env: CONF=release ARCH=x86_64 CXX11=ON
arch: amd64
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
- env: CONF=debug ARCH=x86 CXX11=OFF
arch: amd64
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON
compiler: gcc
- env: CONF=debug ARCH=x86_64 CXX11=OFF
arch: amd64
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
arch: amd64
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
arch: amd64
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
compiler: gcc
arch: amd64
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG'
compiler: gcc
arch: amd64
- env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
arch: arm64
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=OFF
compiler: gcc
arch: arm64
- env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=ON
compiler: gcc
arch: arm64
# clang
- env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes
- env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
arch: amd64
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes
arch: amd64
- env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
- env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes
arch: amd64
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes
arch: amd64
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
- env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
arch: amd64
- env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
arch: amd64
- env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
arch: amd64
- env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
arch: arm64
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF CXX20=OFF MEMBERSMAP=ON CCACHE_CPP2=yes
compiler: clang
arch: arm64
- env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON CXX20=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes
compiler: clang
arch: arm64
# coverage report
- env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage'
- env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF CXX20=OFF
compiler: gcc
arch: amd64
cache:
- ccache
- pip
after_success:
- pip install --user cpp-coveralls
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage'
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF CXX20=OFF MEMBERSMAP=ON
compiler: gcc
arch: amd64
cache:
- ccache
- pip
after_success:
- pip install --user cpp-coveralls
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
- env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON CXX20=OFF
compiler: gcc
arch: arm64
cache:
- ccache
- pip
@ -72,13 +127,24 @@ matrix:
packages:
- doxygen
before_install:
- if [ "x86_64" = "$(arch)" ]; then sudo apt-get install -y g++-multilib libc6-dbg:i386 --allow-unauthenticated; fi
before_script:
- ccache -s
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
# exposed by merging PR#163 (using -march=native)
# TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
- sed -i "s/-march=native//" CMakeLists.txt
- mkdir build
# travis provides clang-7 for amd64 and clang-3.8 for arm64
# here use clang-8 to all architectures as clang-7 is not available for arm64
- if [ -f /usr/bin/clang++-8 ]; then
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 1000;
sudo update-alternatives --config clang++;
export PATH=/usr/bin:$PATH;
fi
- if [ "$CXX" = "clang++" ]; then export CCACHE_CPP2=yes; fi
- ccache -s
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
# exposed by merging PR#163 (using -march=native)
# TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
- sed -i "s/-march=native//" CMakeLists.txt
- mkdir build
script:
- if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi
@ -86,10 +152,13 @@ script:
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
(cd build && cmake
-DRAPIDJSON_HAS_STDSTRING=ON
-DRAPIDJSON_USE_MEMBERSMAP=$MEMBERSMAP
-DRAPIDJSON_BUILD_CXX11=$CXX11
-DRAPIDJSON_BUILD_CXX17=$CXX17
-DRAPIDJSON_BUILD_CXX20=$CXX20
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=$CONF
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS"
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS $CXX_FLAGS"
-DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS
..)
- cd build

View File

@ -109,7 +109,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [1.0.0] - 2015-04-22
### Added
* 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage.
* 100% [Coverall](https://coveralls.io/r/Tencent/rapidjson?branch=master) coverage.
* Version macros (#311)
### Fixed
@ -140,7 +140,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
* Redo all documentation (English, Simplified Chinese)
### Changed
* Copyright ownership transfered to THL A29 Limited (a Tencent company).
* Copyright ownership transferred to THL A29 Limited (a Tencent company).
* Migrating from Premake to CMAKE (#192)
* Resolve all warning reports
@ -151,8 +151,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## 0.1 - 2011-11-18
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/miloyip/rapidjson/compare/v1.0.2...v1.1.0
[1.0.2]: https://github.com/miloyip/rapidjson/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0
[Unreleased]: https://github.com/Tencent/rapidjson/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/Tencent/rapidjson/compare/v1.0.2...v1.1.0
[1.0.2]: https://github.com/Tencent/rapidjson/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/Tencent/rapidjson/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/Tencent/rapidjson/compare/v1.0-beta...v1.0.0

View File

@ -1,21 +1,14 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
if(POLICY CMP0025)
# detect Apple's Clang
cmake_policy(SET CMP0025 NEW)
endif()
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
PROJECT(RapidJSON CXX)
set(LIB_MAJOR_VERSION "1")
set(LIB_MINOR_VERSION "1")
set(LIB_PATCH_VERSION "0")
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
PROJECT(RapidJSON VERSION "${LIB_VERSION_STRING}" LANGUAGES CXX)
# compile in release with debug info mode by default
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
@ -30,16 +23,29 @@ option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON)
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
"Use gtest installation in `thirdparty/gtest` by default if available" OFF)
option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON)
option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11" ON)
option(RAPIDJSON_BUILD_CXX17 "Build rapidjson with C++17" OFF)
option(RAPIDJSON_BUILD_CXX20 "Build rapidjson with C++20" OFF)
if(RAPIDJSON_BUILD_CXX11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
endif()
option(RAPIDJSON_BUILD_ASAN "Build rapidjson with address sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_BUILD_UBSAN "Build rapidjson with undefined behavior sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT "Build rapidjson with -march or -mcpu options" ON)
option(RAPIDJSON_HAS_STDSTRING "" OFF)
if(RAPIDJSON_HAS_STDSTRING)
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
endif()
option(RAPIDJSON_USE_MEMBERSMAP "" OFF)
if(RAPIDJSON_USE_MEMBERSMAP)
add_definitions(-DRAPIDJSON_USE_MEMBERSMAP=1)
endif()
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
@ -49,14 +55,29 @@ if(CCACHE_FOUND)
endif()
endif(CCACHE_FOUND)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror")
if (RAPIDJSON_BUILD_CXX11)
find_program(VALGRIND_FOUND valgrind)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT AND NOT CMAKE_CROSSCOMPILING)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion)
if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")
endif()
if (RAPIDJSON_BUILD_ASAN)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0")
@ -73,9 +94,22 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif()
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers")
if (RAPIDJSON_BUILD_CXX11)
if(NOT CMAKE_CROSSCOMPILING)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native")
else()
#FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-missing-field-initializers")
set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough)
if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")
endif()
if (RAPIDJSON_BUILD_ASAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@ -87,9 +121,26 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
endif()
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
add_definitions(-DNOMINMAX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
# CMake >= 3.10 should handle the above CMAKE_CXX_STANDARD fine, otherwise use /std:c++XX with MSVC >= 19.10
if (RAPIDJSON_BUILD_CXX11 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.10")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11")
elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
elseif (RAPIDJSON_BUILD_CXX20 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.29")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++20")
endif()
# Always compile with /WX
if(CMAKE_CXX_FLAGS MATCHES "/WX-")
string(REGEX REPLACE "/WX-" "/WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qarch=auto")
endif()
#add extra search paths for libraries and includes
@ -102,7 +153,7 @@ IF(UNIX OR CYGWIN)
ELSEIF(WIN32)
SET(_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cmake")
ENDIF()
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in")
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake files are installed in")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
@ -141,6 +192,11 @@ install(FILES readme.md
DESTINATION "${DOC_INSTALL_DIR}"
COMPONENT doc)
# Add an interface target to export it
add_library(RapidJSON INTERFACE)
target_include_directories(RapidJSON INTERFACE $<INSTALL_INTERFACE:include>)
install(DIRECTORY include/rapidjson
DESTINATION "${INCLUDE_INSTALL_DIR}"
COMPONENT dev)
@ -157,17 +213,45 @@ install(DIRECTORY example/
# Provide config and version files to be used by other applications
# ===============================
export(PACKAGE ${PROJECT_NAME})
################################################################################
# Export package for use from the build tree
EXPORT( PACKAGE ${PROJECT_NAME} )
# cmake-modules
CONFIGURE_FILE(${PROJECT_NAME}Config.cmake.in
${PROJECT_NAME}Config.cmake
@ONLY)
CONFIGURE_FILE(${PROJECT_NAME}ConfigVersion.cmake.in
${PROJECT_NAME}ConfigVersion.cmake
@ONLY)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION "${CMAKE_INSTALL_DIR}"
COMPONENT dev)
# Create the RapidJSONConfig.cmake file for other cmake projects.
# ... for the build tree
SET( CONFIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET( CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_SOURCE_DIR}/include" )
INCLUDE(CMakePackageConfigHelpers)
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY )
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake @ONLY)
# ... for the install tree
SET( CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME} )
FILE( RELATIVE_PATH REL_INCLUDE_DIR
"${CMAKECONFIG_INSTALL_DIR}"
"${CMAKE_INSTALL_PREFIX}/include" )
SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_CMAKE_DIR}/${REL_INCLUDE_DIR}" )
SET( CONFIG_SOURCE_DIR )
SET( CONFIG_DIR )
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake @ONLY )
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake"
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
# Install files
IF(CMAKE_INSTALL_DIR)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION "${CMAKE_INSTALL_DIR}"
COMPONENT dev)
INSTALL(TARGETS RapidJSON EXPORT RapidJSON-targets)
INSTALL(EXPORT RapidJSON-targets DESTINATION ${CMAKE_INSTALL_DIR})
ENDIF()

View File

@ -3,5 +3,5 @@ includedir=@INCLUDE_INSTALL_DIR@
Name: @PROJECT_NAME@
Description: A fast JSON parser/generator for C++ with both SAX/DOM style API
Version: @LIB_VERSION_STRING@
URL: https://github.com/miloyip/rapidjson
URL: https://github.com/Tencent/rapidjson
Cflags: -I${includedir}

View File

@ -1,3 +1,23 @@
get_filename_component(RAPIDJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(RAPIDJSON_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@")
message(STATUS "RapidJSON found. Headers: ${RAPIDJSON_INCLUDE_DIRS}")
@PACKAGE_INIT@
include ("${CMAKE_CURRENT_LIST_DIR}/RapidJSON-targets.cmake")
################################################################################
# RapidJSON source dir
set( RapidJSON_SOURCE_DIR "@CONFIG_SOURCE_DIR@")
################################################################################
# RapidJSON build dir
set( RapidJSON_DIR "@CONFIG_DIR@")
################################################################################
# Compute paths
get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_target_property(RapidJSON_INCLUDE_DIR RapidJSON INTERFACE_INCLUDE_DIRECTORIES)
set( RapidJSON_INCLUDE_DIRS ${RapidJSON_INCLUDE_DIR} )
if(NOT TARGET rapidjson)
add_library(rapidjson ALIAS RapidJSON)
endif()

View File

@ -1,4 +1,3 @@
os: Visual Studio 2015 CTP
version: 1.1.0.{build}
configuration:
@ -11,26 +10,101 @@ environment:
# VS_PLATFORM: win32
# - VS_VERSION: 9 2008
# VS_PLATFORM: x64
- VS_VERSION: 10 2010
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 10 2010
VS_PLATFORM: win32
- VS_VERSION: 10 2010
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 10 2010
VS_PLATFORM: x64
- VS_VERSION: 11 2012
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 11 2012
VS_PLATFORM: win32
- VS_VERSION: 11 2012
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 11 2012
VS_PLATFORM: x64
- VS_VERSION: 12 2013
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 12 2013
VS_PLATFORM: win32
- VS_VERSION: 12 2013
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION: 12 2013
VS_PLATFORM: x64
- VS_VERSION: 14 2015
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_VERSION: 14 2015
VS_PLATFORM: win32
- VS_VERSION: 14 2015
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_VERSION: 14 2015
VS_PLATFORM: x64
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: win32
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: x64
CXX11: OFF
CXX17: OFF
CXX20: OFF
MEMBERSMAP: ON
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: x64
CXX11: ON
CXX17: OFF
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION: 15 2017
VS_PLATFORM: x64
CXX11: OFF
CXX17: ON
CXX20: OFF
MEMBERSMAP: OFF
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VS_VERSION: 16 2019
VS_PLATFORM: x64
CXX11: OFF
CXX17: ON
CXX20: OFF
MEMBERSMAP: ON
before_build:
- git submodule update --init --recursive
- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -Wno-dev
- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -DRAPIDJSON_BUILD_CXX20=%CXX20% -DRAPIDJSON_USE_MEMBERSMAP=%MEMBERSMAP% -Wno-dev
build:
project: Build\VS\RapidJSON.sln

1
bin/data/abcde.txt Normal file
View File

@ -0,0 +1 @@
abcde

Binary file not shown.

Binary file not shown.

Binary file not shown.

502
bin/types/alotofkeys.json Normal file
View File

@ -0,0 +1,502 @@
{
"4BABQZ5SZJSO3KFKBOG36EIXXTOF34HVFCELHA2DWOMIL44K": null,
"RSZNOTRIJFCHRKG4IKNOW4ZEBMVXPDBYBXBGDGNWTSVLMJ2U": null,
"AOGQPY32FQ7T7WZWQPON3X6GU74GOYI6HHVNPATDTBXRUQ4G": null,
"3PMTZEGLZNHSOWWJ23BE6PWOXD2VZRDN7MMLUMQ4EIRERVCG": null,
"PD2FMQGI5HTGK6MT76OYS2ER2LXFBON44WOMELDY5MRKQI6I": null,
"6L6QMMVSE4UQLB4OGX3LVDRNGAL6MOJ6S3RBBUSQ3F5PPHYR": null,
"LYVVXT7U7WN7PGGUHCLFXVOBJBSSR6ES2P7AY7XGBXEBLTDD": null,
"G5RWOLHDDZOXYEFGGSVWG3C2UHYDW6UOFVBQQLQJVZNCF4TB": null,
"3QPIK2M3ZPICZQFQTX22A7VDCAFIGAX2PXIXKDOZX7XUM32R": null,
"JR75L2BXOA5LVLNKT4EEZO2P45OHWRPMMWMFENTFFIY7A2V3": null,
"TESL546MN7IR7AT3C5HRSESIFHZ5NW6TNRWZXZ43OSRYOZKP": null,
"62EJKIAFWGFGPUS6YP2X6E26AV2TZCTCAJMZNWBBNFRPCCRN": null,
"5ZDD3KPTPGE2CAWR3MTFUSBMGQAS4ZP5WZKXJTXUNFSYABD6": null,
"XQ7TMN5YMQLAND54B4VIVWJAHU3TNZKT2S4SVRW6WKHNJBX2": null,
"O456GV3HBAWFDQRCECX6HY3PBTP6WNQIDSKVP2MZIPV3TCBL": null,
"WXCN25EBQH5WWN2JBHWNFNDUTYSFDLIAOWO5AE6D5HDO7VNE": null,
"THO3I3KDRIMTD6DKNIETIOWDY7FXQ5GJ3P2KUQJWYAEL3LXV": null,
"7OMI7VIOKFRZATMNLGIWH7ZBDARZ6ARXIAH5S3GPG5KV52IC": null,
"ESUPY3ELKCEGFRSYFGPGFBJOAUGXMYZ6XCWXDFOKHBJHNGVR": null,
"TNXSJIEFJLUFUDTR2S5LV73PD6ACFYNHOCRZPUSDPXDD3B7M": null,
"T6TISG6P4W66F37634QU4BNJY4RZ77QXXNPGTYH5LCCRDSX6": null,
"QTVAA56JKNDYTMV7DXAIL4QVLZPW3UHGLTKDI2BED6S3MGDQ": null,
"DTJREAQBCS6I2AJ6MOGTPIXK3ADB4BPNDIHI2YSQP6Y2BMH7": null,
"XDGH2OYCTAJ75IEMZ32O644YLT73PRYDORFKBLYEMCHOQ7Q6": null,
"4KDDQZRBLNS33DRHZHDMENCWGMNFEJGBZJXSGIQW7VBWOTHT": null,
"5KSH3GKWFNXV55KI2FPUDSD57O25N52UTZAAYDFVMFUSEE6O": null,
"7AGEUBM5FQZ2JCMUSKTEI6COA3Q5CE5WYB7TP2F5OX3ETMTK": null,
"HFHZ5ZE5TC45W4WIF6H7ONTHXKAVWRY2LXN2GN2TXZPIP6PQ": null,
"S3U2JJBPKZHZNOM3SWVFQ7OMS7F5M2KDJHHHZKXHZXQRNUSE": null,
"YHJBGJ6T6A7PMK5AYXDITDV37BJJIM4TP7I2XHSVYN76724O": null,
"TH42A7M3645OUKC54JQMDB5BTGS3URFUCYJ2VOEM6IAGZ5QQ": null,
"OYBKULFLWL2MER745QTDL2X2HJNR77QGH2M2P6TSCHVGUJLV": null,
"JDU37GHQUOCYA5I5LFS3WAEKKR6C55XJCCLJCCCQJEGUJEP6": null,
"CB5HEJZNJ2SWZM426TWIWLHTWAPWPT2AVVHBILEVGFD6NPHI": null,
"D4A5SJA2VRB4JGJFC7PHT35S7XAMHPZZ2PZC5YYVV7RLKSUQ": null,
"BBVT6NRRU55KNRK5G745FNMZVIFHVZJICEMODF4ZBJFQ3EGL": null,
"XBV57OEMT4GYPTTH56A6XKF2ZPMXSMHY7L3LUIS5ZZWRP2OB": null,
"GTFJ3NP4VJR6HG2DRNTDKVIWTMIALYUQIQTBJMKVM2I3QKGE": null,
"77BMBFMRGASXE5XXT6BRH2DRBNJMIAUDDMEXIJT3RMHTUPI4": null,
"FWZZMG7I2JWAHX4LBYAK2G4L4TZYLHXMJWIDGT6JC5TEBCPJ": null,
"J3324OXU2BG2NGFMSOYMVKXE6OEJNGENI7EESHDSEWSUVDVV": null,
"C636AVNC5C5EKILXT2AQPXYLSNH7LCAJKVDHP67MVHULFSQN": null,
"OXTDOQG2VIEVYFC23SKOBSSPGE55AVZZADK6PIHP3APVPHND": null,
"JLQVKV4Q2BQHK355NQXZVX4WJBPFOWSD7WIJX2P433KYO4SO": null,
"E4XHPOPWH3PRCV5MGQHR3BCTKZMOK46OH4Q6STZDPF2FG6SD": null,
"J5IP4A3DV3BHGGU3J72JVVTWNIQOLNC6GQES22MVATK5H7BZ": null,
"HHCCDMLNGOU2ABP57ION5TC33UF3NUHL2L3WUYCGZDWLDNTL": null,
"54Q67RURG4THOANPT3RAVF72TGKJE425GC5GD3EOKPY6MKVW": null,
"TG3BH3HBKFEXAUM5O67VVDTXZA6MHWSVNNLXLXIL2SE2ZEDO": null,
"Q5KJ25G2A4CWNGPPYXBZM6QVYA466MQX3HCUMUO5Z24D5JX3": null,
"QQZET7VFHGJROUQZSWSRDI5ADXVH26KEPDVL6PZ36ISHOKMQ": null,
"KWNJME4V365ZIC7SA7BYCVQUAG6URC2T6MHSO3OVDBJAUPFB": null,
"XHQYKGYVLE2PFNXQPD4OUWBASZO5OFVZISCVEFTU6K6KDKHS": null,
"Z4SPXMJIAMYD2H4U4F23FALBDZP6NRLUBDFU4PRGZ4SXGTI2": null,
"HSCK3PEXH3I3XMMEMIHTM7SDJD3GOKXUMCGOL6UXJXLCSCGN": null,
"BIUYMIDY4EVGRLZ6OLJK2CE2FS5TTELIWSEA6UHKUDUYX5LM": null,
"IJJDLN5ANXTMX54P6GW2J2EJGGWG257YEAOZMXUSWK7D76LH": null,
"CLMTO3VSAOBAOBSA5IGOO4W7KEMLOFUOIR564IBKMJA7RWEY": null,
"JU5DNSHLUW34DT3IQ36JBV6M7EPILLMBALURDAB2KJXF6HQB": null,
"VXZXWLNQZFJPNQVPTOFWUPLORZD2XRAFXRVRNLUYTPBO22U5": null,
"HNACM55ZSGJ2FGRMOTXLVVLA32BC333QGC4HFCDSZ335YA4N": null,
"6J5GIOVKU4PKHHU35DWL3D7GTJFF75FF4FKSP2HPGJ7SQ2DP": null,
"O3NJM537IQSKKWM3K7EOQSNQDTR6XKUA7ZR7CWYHYYLHKH63": null,
"B4QMXK2EAR5E7KGHLODCP56DX5HW7IQVXWHFFCZ4SPSSNGJK": null,
"A5AUZBXKF67OXO34ZSEGVXI5PAIG6W2VG3U5C2Q72SNWYNEI": null,
"ZGDQ2AA2IFBSU3APKAFL5AO4C4DXY2YBEHXE5UPPVCTFZ36K": null,
"N3XZ5FYZEO3ZX37OMUJX3PIWEEV7TVEXX64KKEZEJICKXMTB": null,
"3EVOEEWTD7OABLQJIJYLOSVHBS4SB6QGX7GPDFGWI2DGAWKR": null,
"HNAEL3D7E2S7IYLKLIK4CGI56DRGAXA5S6KG3RX75PMJ6BVI": null,
"VGVW32CIRX3M45J2CPCUPPHNRGNG55MKAU7YF3CDNMGONW2T": null,
"QV5MW2W6WQSHNC6OYMWJAWEQM7LHXRMGWCJ7RI5WQ3JGHARW": null,
"IND2PUTLFWXTEUY4MMEXCFJA7JN7DODE5HVWC5CL5ED5IEUB": null,
"W2IA75XHJRBRKXLHGB7LXD7ECYEZI4V5N5I37UFXJMFWQMYR": null,
"AWTZO6OG6TCOUVYYJCWVP2JYEXRXZ7S7F7QKUKZS7JLPKN3H": null,
"TCARJATK42Y66SPMGOZ2LHLT2ZPZW7MHGXL5IVTS272FJV4U": null,
"XVHBOY5WQDOTWXVFZYQKZ6GNRWMITJDDLXSJ2T3UWF6PFOHL": null,
"CY5FGDYLB4UFR4AJRGLGPQT3W3OERGCXC4JHYKJ4HKSFTGK6": null,
"B3SJGD67GKIEAOZISX7HWENPDBYJHNJ47JCREGXQ6G2RXPUZ": null,
"LWVJYH7M5KXMLPFAHTMF6FKT3PSIW2GRC37AHF65PQY7OUE4": null,
"UUFKWC2DOV4ZQHPDPQPRCBEYNAX6OFZ7ZVJNYGW5YZCMSQIS": null,
"K5EC26CUN365DZ3LE2NHOINGZHXQ752A3VTPN5IMSRYSTOMT": null,
"22RV6RSSZIAFXOZIRAWJAIMMVHYWGL2TY42U3TG2SPFN3I6P": null,
"Q7VEOUC52OLXL53CR4XQSGGR5QZ2QXZTRCBACHQFP2HKN4SZ": null,
"OZ2ZBCTBC32VOHHBDABY2U462OHUEUS724RUS7Z6TW5K5ZFQ": null,
"EYXYWTX2UYI6MUK5L65WSTX2FDOJASIMG6ER22NLABNGAEMI": null,
"U4FJU7RQMXXDMHG7B5WFLXCZBNE5PMV43CE5X4RJSJUABT3U": null,
"K3T56AL7IXTAGTVIWZHYRKVPHLLD7UVHV4UNU76F764VGY75": null,
"U2BRKWY2RBYV5S3XVZTUZXT55CXMB45KDMNFMVY6LENW2DH5": null,
"YKLPZ7SDAG2O6NSJFLVGFVCYMY4WZKXQGHH7OO2BKGGVLQNP": null,
"WSC2BHA7H6Q62HJIIGQFX2OU64QX4AEU2RZQVIC7LSIO2JSJ": null,
"QIFNFKPJJCYPITMAYDAOEXBVEDAKBBR3DV5ZB7DAVBIAWI5K": null,
"NMBGIDIK3BMS5ZPZS6ATTID5BOAXZAH2VUED52JSC5XGI42P": null,
"LTSG7BGZVBLLXM5U2QDW5LNNPM3B5EQZPHES7JXU2EAQG266": null,
"5MZMVLLM7YHR4PTQCGDGWFQQLNN532WMTFGX5CFTDURBYEOH": null,
"UOMT2ERDBVXC3LRYKCVVUNROBWPGFHFWKFCW65HAPXN2H4FD": null,
"RFYZPAIVYHTITTR5AKOBAMYKOA3VSKRTK4P4ZOS7JFSVEY53": null,
"QQJGQV6BSW6PL4DZGQDWWVTF7U5MEVPQABOA4IRP7NOD4V4V": null,
"EFOSJBHVPSGTB3O374JFJW6MVW47ODOZQNKYSWHR5W6UZECP": null,
"YTL42MLIGIUD6Q3AMVMJ6ZMWNSXSUWCKV4ZUQWSGTEOATQC4": null,
"F5IL5OV3Y6E4QEE7JMQTKV6ULJ5AQQKQPZ23VXK72AV2P7XG": null,
"AZEV37T65EWVWQJSISCHTYHLWRXWCR6XD4LJ4KFLJ6RAOPF5": null,
"T5TAAFPNZLVDYHSNNHIJW4KBZWNFT5CMIPIWW3EFKPU4REYG": null,
"W326OLSKXRLU6MEIVUTKFFHFGXEH3VM43F353L3NHQP6HE2Q": null,
"MIIUZQ4KGTLA66VIE7WPN4T43SR6Q42YUKWEP6467AYWKU62": null,
"AXSJHLTL4FXCMLLJTQS4HIBRGUY6ATR3GZPV4MGXLWNFHDYU": null,
"MC2CMWSKD2HMTVIWCMSPZWHEGW73RWEZKU3IFZJM33IW3VI6": null,
"ZGOZHC22WZN6LSY3KK4HK6RF6F73VWSB7U47KZSLTYOQZAVH": null,
"HU26VJYM5YNEXCOCWCVEQNNZ2WAPFEVYK67JZOHMSZIOUWJN": null,
"6ZA46O27SWCAX5MQUHZYFV5UNQUDLZG4LDA6VILK6YRQMMZ5": null,
"LMGGW3CAN4T6DSVJZB46LOBI6KTZN7CKHNZ6BMWRBL5PVYXX": null,
"RZKIP3F5SY2P4NWANAQZJHPH34CU3GMQ4VCN4QXMP7ZBSQ43": null,
"CMUAX53FME5Y62VC7T7ZOUZMOPHBDFVLMVVMHYDDBZEHMOOA": null,
"ORTA47K5MLIHEUXQTFFTQNW2RMYQSTVDJXUNIF334SAJJYMC": null,
"XEGLAWIOOPE25FDXHN65P4FYJVB46M4NGGXFAWZ5VDWBBMU4": null,
"WZGXOCCN6GENKYYAYCH6UQD45BIPSYMQOZYAYRU3S2JNJLU3": null,
"MXDDSZA6VTTYU56ONDE4QZMB3L2D7A5SCRCIVBYYVIKFDFLU": null,
"JJMW475CTRXRR4R3GEZ77STHMKHTQZYFZHFUFXEB77SV2W3H": null,
"J3TNJVNF7QSTIJDEEZMLTQECNOES4PXQALSR5ZPYDTIVVKUB": null,
"Q5EHPI6GHPPZBATKHYYEXNDSYMW6QVAVKKHC2XO7RU7XXKQ3": null,
"B6WGKJEZH7XBZ4VFFRCBFYKC2Z2ZQXMY2HJQUH4LVI3EDMMU": null,
"NZ737IT3LUIMH56R66WFETEHFDOZSNVPTHMQTW3JHVTN562C": null,
"B52PWLRNPFN73AA63O6JFLEYSPFQEIHQ6AI6YC7KWOYFE5OW": null,
"7UTTRFE2I5WB2XZA37L6F7RWCII6S6HLXZRTLSJYFOENAYPI": null,
"TJJDGG7R4RNVAOXWRZRZB5K7W2Y6XB7LUYBDOY6H5IDRM3ML": null,
"TOG35JU7ULNRY3DE2XYDZ25WZETRSO5WSFFYSZT5IIALO3ZP": null,
"2QZKK4CMZNIKUWZZB22ASDR2BYNRAMTNS7MVLBA7Z7RDKZDV": null,
"US4C6FXHKR4GCRU6IJQHSAJXLNQGUDCDEPEQDU5C5D76I6XX": null,
"QOPUXM3ZKXTPVGMVVDMUZZ75KH2S7DKYXSFCQ3R5RYO5WP2J": null,
"GZ2T37SKRE3ZX7FARFWWF3WG443LVP5X6ENDLDHO7GBWYHHM": null,
"VSOOUSBMGIPEVAPYAGWZOLDUW5HSTRMTBRTUYLQNHKVUBLJ7": null,
"45HJFJQ3YKDBFDZPNDO46YT7DLG754XZWMGJQ7YPJXQ4G4N4": null,
"4KY77KV2OWWFEVIBSUZRGZF2V47BEFFHIHNMAQVK65E34ZF3": null,
"NB334WI2DNPLWHGXBNHSU4436ZYDQ4D2S3JMLDOM35QINZTR": null,
"7K23M4FJGIQFWUMPRDZIK32MF7HZULYYSS5Z7N7QTEJGET3D": null,
"ZBMNFKSEG2PXKJZIXIK2MHJQ2ONRJUJVCDBOCHNERPGMN2NQ": null,
"YMCOX2NMBDL4J6Z7JBEWHFSCWON4ZSBSBU2WONEYYOYRA75K": null,
"GDOVKPAWZFHLAPQ5YHCFWL4NAMC5G2DDXFWUTR27XQ7LEOOQ": null,
"CYBYK7ESXTUUHYQVPMDI7VWAZO5TVGLIB3GB7NYRYVDLMYKG": null,
"4IYLX3IDNUJ2DWT4RM3QJ3IMVE22X67EW5KWSMZHIU4W2W5B": null,
"EBWXJZ3PX7LE4JNB2XWJJNXL5QBVSJQSXAUJMJ34YJKR3JJU": null,
"LEKOXMXHU57JTRZUKMCW4WDCAKEOXPHJ34ULXN5P6DIEOYLL": null,
"BESPMR4LBE3G4MTWR22CVBYH6NW43HO4ILTSV3P543JZUBD7": null,
"5SYIBXIHGJGE4WHL2HYUNK3X4JUGOJOUMKVJMMXSQDKJZHFJ": null,
"XN42HP3QOV34GMJA5VINVW3O7KWW2GV7VDKAZDFBCC6SSHNQ": null,
"326BDEDWGYW3IMEHP63I6LVGSRMS6DUUNMPY3YVWXCH3YA67": null,
"FYNTVFBPC37FYGOXFIXJP57FNX5MYDGUWIMUYMFOJSOXRRDS": null,
"7DRCBIQP4EXAVNEMWOZHAEZ2W2EIMKD77PH6JJWP2BDN6NFN": null,
"7Z7LWVFB2Z26EVYZPLQAOQ7LXLADTHUA7QGKDRFLXRQ3ZJUX": null,
"EOZ2S4T75U62LD4QUZNTOHP7SNVJUNNSE7WWGHCMC75O4XPW": null,
"TVG4ZY3YVNQV7WPZ2CEW26QTGWUBVJV7FTRF4TE54446J5SI": null,
"MQ62OHPXMGGASRXKOH5MEVGLYHKNWBT3DC7XSXPXFHFXFO5C": null,
"MBRTEJLOZ6U43EOO2IS3AHNDCT7WUEK4XN5ZRMTPBKUFXUWU": null,
"24WJGDPNT4E7SQT2IBSTHJGYBMEBKS7VPGJYBRRAT5YXNBC4": null,
"3KD7I6FOTRB4U2JBT7CIJOPD5XHFWHESYJJQTQVUQ3IGIPVZ": null,
"25XHQ7A3DWKVDBX2ZFNIHKOGJCXY73N4Q6PUBEWGH2I55XVP": null,
"GE3YTUBPOT5CFJU2LQVMZVC67NFNLXVWNTV4ERN6BHVGCGYL": null,
"VXE2WHW6UWRE4WYTAVFAQ75IBYUPNZVMHJC44DGDPIAEOVVE": null,
"5JRWFOAEX5TNCAMYGF44C72EWF5NTXIRSVST5J3N6N5SLGFF": null,
"TYNIMWTDY2D565BJUNMFXTJHBUMWOTD4YSAFILKXPKX6FKRO": null,
"RDUDIY6N4RRUA6YEBBBFPBNYFZQUWRVURNYGJPEU6EHJA64H": null,
"MMRLX63PFJLWBJUTXCSLALIGK5YOHTLAY64WFQIYQJCX4QID": null,
"P4T7UPQNUAFMAJ3G4KBRHOQP5GCJP46XXYKPTTENUI36YQEP": null,
"VNAKVK3A4TN7WEZAJBJVMUVIKIUWCNH7B373DP7WAM7ZXYDD": null,
"VAPNA5BJL7OF7VRVSUEFAG6RZWENO5VOGMFVN6AB4A7H4VU3": null,
"TLVHDKN7326OHNXMBBJIVQW5FFFGPXSUR2IVTMPLOLPPJQW2": null,
"LD4OK3CY7MQGHUMQOMPAJY2NZUASJLSLWVSIIKIYYYAFYHIK": null,
"DXHC3XJCJJG2SMU4O2HDPMJHO4PNNYGIMLB5KSCQPNLBAJER": null,
"SANGKO55HOXMBC627JYHVBE3FH6KJL74ITOVF5GYODRRMEMP": null,
"TOQW7HYYWSFH3NKL7SITPX5H4HLAH7BKL35ECCAILLJ5B4TA": null,
"WUKAWAQHSBKAUAYEQ4UA5PKFB4676VQNQFLXUIX6UCDFZ472": null,
"BDU5VYNLNHR6HOLMZI4XSDERPTMVJ4LBUX5XP6W2BQWH3NLR": null,
"R6BT3RGKODHZN2AEX26XHNSLCHGPGMQ7IS2ONRTZEPJECW7A": null,
"E7Z4FLW3UW2ALRLPSMHQWJWBK7VWS63H3AUZZL6LHCIG3Q5B": null,
"FUZAITDO5EH4BU3ZAN55R2RQZ75LRAYI4X3MEJKJD44VHOT7": null,
"7SZ7VZ5O2OFPJL3K5JJKH3C2ZYAJCWW5GYXSLVFHRRATZDFA": null,
"6H7VKVPSP4MHB6P7H5KLQQN3Q6ZSS65OMK6GJ3JIUMHQINMC": null,
"QNCN75MNVAVH2OQR3JE53SGCKLXPSB2XBTZ55J3AX37AV5HT": null,
"JCSYRKMHDGVUVZO65VQVAV5SGQS5IRS4UGFNFKMYP6CXMHXN": null,
"JXX5VCQU2Q73TK5ICSFX3QIGA6E4IFRTGKPZZY32UTB2RY2Z": null,
"BMUAPYFGRJO7ZQAMMSSEADU2RC3LPAAXTORXLSIUCXCSSC2P": null,
"3SPFCAR2V2PQA3RWOY5ZZXI2V6UEUCZWL6SNCGEAGNR2JQZV": null,
"KUW7Z4ZHRUX6DI6Y3ME7A33SXUAQPXFAHRG4IEU32ETMGTLC": null,
"64F67UZGQHZUXLN6HCATAAX2FUQNK2WVOEJGBQ27H5DVZFC3": null,
"GHMJSW2TE6E3JLFDD7T6FI67HBDHNDVLGEKATAO5G33TID57": null,
"6BZEOJR372ZLNXUMEQQUKHHDCAOE5W4YDT3VWGI3YYPYDC5R": null,
"62JOKD5O25I7DBDFMM2BRQP4HI2VJTUHMEF3G3C7JFJF2VNL": null,
"NEF5ANHSBNEXLOP7FFH7ZVHPDOCHQQ6EYOG64JDZNIHBT44L": null,
"ZKLJACJIQT6M7KUY3VWTMQ4WD7RETAWN7LDUB7UQA3NZHZLC": null,
"VBZVHDFHE464JTYWCLYNAA65RDMVURJHVZHWRL3IKTNT6AH6": null,
"FHBYZO5SUBQ56J72DWYOUZSDKXE3SKDRWBEGLQPHWUGVSW5B": null,
"HHWRIAY52UXIOIKQOL3PBERZFDCQXAAUIDT4RTZF2VETEY3Q": null,
"JALKMRCQEIXX3JPLOACUZ2DKA5I2RWSSSIYDVSURW475XHR7": null,
"IMQUFG6JBGWA7R3D3NRMJNOF5MKE2NU4H2LAI6UPIHUEY2ZD": null,
"GWSUUFLKG23Z4BXTLB2HJHYVRWAWHKV5MA5RVOEE77Z65ILK": null,
"ILKEEWZSHVZSQ5M5VAZH6MJPBVQVV63SCQSX73YGTOQZBFKB": null,
"TBU3SS7AG7QISWIK2KKNE77ISJUEVH3ZV7QZJAEHLMAOUCEZ": null,
"EPN2PRVPXZGZ6WRX5ZMG6UPIM2V2NEA4BBC7ZDAIVCEKMHR5": null,
"Z7GJAUSWDAH2JUMVX6IZB2PRSIUHYUKXGKJDM7FXVFDJNDUU": null,
"APOEQP3DLJGKFU7424CJJBFDTWODGF45H7HSXT3GO2UC3VCI": null,
"LCYBWI4HYCSVGBSWWDJYDCWQZGJP2KVSXUUJBO3XFUWOS4SA": null,
"KOTWM653HSOQ2JHNAZGZZA5FGBBJCCBYPDVDE7WDXXIHTULF": null,
"TIPJO4GHBUJQKWKVHK5RF2NI5Z6FAIEBGFPR5L4SSCLS6IE6": null,
"QJZMGE4B6UPJ35KTTNIAHWTFV7DFQZ2QMF6DLHB2AHZQ45CD": null,
"SDV2RDMAXCYWHJJRPTEIZVE6SJST7KQJB57AXCWFVO54E2GX": null,
"4NW6WJDWXCXG2TS24H4I7WF2IGROPO4UBN2HJ64M3CWBU2M7": null,
"GJPMFWNBHZ63VB5XWIM52UO22ANEXDYLHTF24LGBC7XXI4SH": null,
"I3TPFLVZ47TOOMM2G35JFQAYHLAIU3OXV4SXZEP67DNGYXN3": null,
"QMPKHHYWWSV32R2LHCWFKBFDXUDUXTZ7FRZK3TCF25CSFNWD": null,
"J3C6XZSMIXH2SQMBUEVWEI6UZVX2GJZCAYSPD74BBUUK45RS": null,
"WHK5HZ42VH6IJ4U4EUKKVLRAID2FH2YISR7IV6FMNHQPPSH7": null,
"C62NUQB2FUJTY5VRNI6ND26FXCUVACSUTTR6NZMNQPYK6357": null,
"2JXXJE7WN7QWO6X3ESQCSDDBTZXOY43L5AODQUIR5P6Y4PZB": null,
"FQVJ4Y4GES3RGRABQCJIDIYEUNTIGETQ5EOXW25SZSYNJENT": null,
"IH2YJNGRU5Y3ODZHMWNV3TIU2MGCNLIPV75QL3JL4I7PH5ZI": null,
"RYUBMVYE4PL6JJOSBM57NE2RFKCY2EB3EQR3QU45MJHEX5IN": null,
"KRVCQJ6VSHM52MLDNS65PKDYHNBJAHCONQCNLXBD76LDCOFY": null,
"W7MB2FYKYWXDXNOKVWJW7TSUANZIGE25NABNIAK7VLPLKQQH": null,
"QUJNQSAHDXMNHKHHIRBEFONX6NRV4NA7NKFRDI72ZKVZXR32": null,
"SRQAJHTEQYVNHCJDTYHA72VSYS4FPTHXGPFYP6CQRTEUIWVN": null,
"GYQMORZKT4JGWGOD4KBEMUB3XZNUM7H4G5IRA6SYDZOGAPVF": null,
"73P37OKSAJ5SWM5NJ2QWCTKPTFNLORRRGBNJWR7BTCRLKNCO": null,
"D7YVGR63MRZ5YS3UTCUZ7REPWGB6EMGNI3LXZUDAYBSZVGHZ": null,
"JNUZON5EE4CF5UIPXIAU5HKQSBN6O2C3OXJ5IT6HPZMUBXRK": null,
"3UMKRHCWRV2WNUWPF4WKESLI6EOHPFC6FOXF2MGP6E7GPKF7": null,
"ZPWCDBHEOCZRBAVIQNGRQ4WNKSE4XCXWH3PQSBJWVTMLP6AD": null,
"RCOP6UXD6CG5XYUXFXT7HDAWQA2LRA52R2NVABFBB574N62D": null,
"6EHQW3VGWSY5MQKBQ4PWU2YD4KKXPBUFJCBEEY6GKOGGGT4P": null,
"V72EUDLMYSS47DCO7XIEYQO4S6KK7ME4C6VN6IWLZALPDIR2": null,
"EX6JHHNN4R7BQVBTVXYRD54J6BLOJTRHM64QBK3DHUWW37KF": null,
"6GGFMOEZN5PBE67AJM6XJKDL7V6X26X3TH2WVOO4X2MEQJKO": null,
"LYM2NDKVFTJ2IJV2G5HTDDXFDAAHVHVMVTNGBAOABW4JLB7V": null,
"5GPR3EHGCAFLKH4CTOZK3JBHCJSEEFD2Y5GS5Y3B5FPXAK6H": null,
"3TVZ6BP47YPHI4HKRIK43AJPRVM5UO736FF7WEXI6FJMTKY7": null,
"XDL7LZWG4CIO574WINYHCXMGRRZV5BMZQH6GPTTVPBWGV4MD": null,
"OHDX42IVKOGGQVXFE7Q3DKX2HNXGIZRAZ5TVVKQ34BO7UKPB": null,
"QHSOVA5SCRL5AK65IALQZWLHPSMLOOHHS6JN3LHDCN7DEHJ7": null,
"EI2J32TUZKPKSWOYH7EPPKHISCJ5SPTUFJXENKZJFAPEFQJL": null,
"3FFPGZBSH57RTBR326VUSL4G3DELAIPWCCHB77LFG5CBS2YU": null,
"VOLJPHGJOQKGKQ3PQGRLYJBZCIF3T355GXCQQKV34USNOXNX": null,
"ZASYP4G3K3DX6MMU2CK2P6GJ2PKRQFQGFVEZGTMIRAZBDMOC": null,
"MSLOXTCY6MPU6XRGIJ7ZGFBB5J4RTGTEC2UW2LO5MIKPXFJO": null,
"DM3ZAC4JV4IDN7ZZ2OLHAUCUEWYTMLZSQQEARJF4JVBUTE2D": null,
"KWIXQOXXGHTUPBDCHXV6ET4YZXIDCYZEQTFIRHD7DTMSGZ3X": null,
"SOF4BRIWEU5XLSXVFE6IHVVDYG73RK5HJACKPUNFRNEDHRWS": null,
"4FECMJE2AGQGN54LFXTIQFZC6ZVJN3LY62YCS4E65PMW2K5J": null,
"VDCWL2B5OEDDB2YGM7Y23WLJPJBFESITFU5AWDPUKDUMFPBO": null,
"W6VC6MV4GBWJ7IDAX4DQHWJSBUJHJN7ADFJ53NBVND3TXUCZ": null,
"Z3TTBMVW3FCTJPLHXITOVK4LPLUFJJY3CIYKJ4QY2DANJ53R": null,
"O6N3PZGXI5B6NBTOFPB5WWIRJ66O4FYLSGHDIJLVPT25YPWK": null,
"RXCNDGG7CDEMAOGCALTPXWLUL7A67D3JSKOZSZEQBLDW2F3S": null,
"XVKBWW7HRXDBW3YXSBMO7WVEUPVQ7LRZ44RVFI27PYZO3NTS": null,
"XUSRB4YQDOYJALL7CK2OYFPL7GKI6XOFYHP7HTW5H3PF333V": null,
"PCCHIGPV6SWW2O4YRPMFMNF5YVW6QY5IF7JPYAULF5WPTYKB": null,
"MHRU7JFEPHHUAULYL34RAEAGBU2ARZG63TGIIS7MHEQUKWPY": null,
"Y6EDYRAB7V6NAP57DRIKQ3SB57XBPN7MAWD7F3DM4DKWIAMA": null,
"JQXEFOTP5HPBTKL4VAXYCMJFZVGSAM3JVLFJPQ6KHVLCRXFI": null,
"U53PDNGH4IKMP4PW6AJV6K5Q43PYB6VUZ3IJVEKZK32IR5WJ": null,
"52CB2E7VQJ3JJ2SXPHQZZMER64TM2JQBSW3JMX7XITCNSWDT": null,
"3JLBHZFBPZQTO3MLCW6S5N3RIR42N6RGDHMP4U6IO6STOOVT": null,
"YTFVKDUY6LHHBY5JBBTT75RYI73Y2Y2DFT5PBMOLEVBJEN4Y": null,
"TAHMINQIUDTCEBCJ4UH2PUXO5TYMIIZTH4BX26S4NRMPFD6Q": null,
"4VJIQ6FLWV6ONBHRWDR34KXCTHL7HIXSQAF3FAKOMZ2C7QV7": null,
"IQWFFVGP6CPSAQWMKA3SWYOXAUL2YCD3EJYRQ56S3VXWAMUF": null,
"J2FABCRQ7HZFV4FKZKY2UOXRUO4FYXANTTWL27ANRYY6XZC2": null,
"G3TOY5CIOYIELRC2S35CGAS2E36TDLTO5XYXHFVKZNDFQC6F": null,
"SDKQB4B47LL6CAFDDYJWDS4X7COKTZOCQ6ELJBL2YF6RHZJC": null,
"L76D3LKKTUAWNPDXKTWE7JCFCRFVI4UX6NKQS3CAA2OWVF4K": null,
"QVYYK2GQF7DHSJACSOZPOQUCWWIYTRGEWMBIR5RRCV2EPQ5X": null,
"UM3PJVMZNDU2GJ6KVY5VQ2HPGMSJKVAQBDRKZKHBPBRCU5SO": null,
"RDIJQSPXHAUB7XSQQPOL3CNUR5AJAJEWAFYFSDO5G4QWZQCV": null,
"3CAVVDQOCSMOPC54JWKI5ITUIHAOV6SKAIIAAPAAJLBDTXEM": null,
"JHLSLTDSRVKDHWRGT55OZ5NC6YHGD35WHW4GPK77VZWPNVKN": null,
"6K266T5MHDGFA2XECSFBMTQDEE2C4S45S53XBODESR4ERZQ2": null,
"VJVWAFFKWR2KSTFIWGAKDUG5VQTO3BPTI7YFYZWZSBMMQOIN": null,
"LBSXWCQNCHYUG5M255T3W72NBPR5MBEPO7DFBCD277HSH4DU": null,
"WHJGXILLMK23VGXI2OY76SYJQOQHQOM6OSLT4BWU2KSD3OAD": null,
"DVNEV7ANOMDRQDHTEMD6CXCTO7NOY2MQQOLI47U4DDOJ2A2M": null,
"TV752NASHG7FG2JOGS5P6QLJ7E4W5NX7F3OYYRPOEFZ2NREE": null,
"S4DHHYVQ4RQ7HBAXW5ZKISZMULMLCFTSBFICXNLI2OD7YNF6": null,
"HSRHOS56TX6EEDHUZX7K4K6Y3R2UNHRINXWVK5WBWHDPE5HF": null,
"I67YQZJ4PXHFWHNHMK5SKUEFIL4EEP5B4BH3TJNHZPQOUXDM": null,
"5AJTMUDFBWW3EGM2TH2YAJYXIR6GKM7RPBYBRV6KEQPDDLM6": null,
"6V3SAQQC44I3CSDERRKA2533GYIWWHUZVR67JAWIBPJJBDBI": null,
"5I6EFWIWLDNJQAZNZN326TUHCUY5YOD4ITIT6NL7LWIK6RP4": null,
"NVT5LE35FIT6LKWBI5XZO2Q7CTQBFJ3IOIAFNXI7PGVHEE5W": null,
"E5I534XUV7GRNCMHBVFI7FMTSPYBGXKOFVXXSEQYYLVGCASL": null,
"3XDVU325YQTEXC7HFJKKKH7CTCCNNJZMV6VRT5GVED7HFKMZ": null,
"3UJYDR6QUVSSCRHJT6WWNEHC5OMYXOPL3EF26PU2A5HESFG5": null,
"UPRVTQXNXYCZG4JZIR7GZCCYTXR5VTUR2OKAJXEWGATCSIOH": null,
"2QLXXZPU57ZXMLJHEYDS6IHFLQHOKANOE5URI2TRNFNSIFUG": null,
"JFL3SN7LZ7M4RUZXRTYFQTUMYWYHO4P3ZKBGFDC2GGWZBPEA": null,
"SBLHOHHAOCNEVQI3UPBY5S4UKTTIH3DEJEDJHWMJ6VEWWTCL": null,
"TIE3GNWA2BE2WGFA7Y3KEHF4IF77M5XHZB3DIQLOE3GG4VQM": null,
"BB7XBWIYV33TZGTKHTBL4PDPH5ZQ6X7ZCMHS3KIQEJOLOXVH": null,
"6WO2JPOCRLCUSXS7BHNKFBDGFSEXCWYUFPK5SDZJTFJAEJRV": null,
"RCJUMHWKL3IBJ4ZVWHK4RCZ4RCVVTMG5ZO2KWZOIVZLJTSMT": null,
"YIXCNMIMZBA7NK2A5QOCLE77QFF6QDS7NGIHKMILIUB37EMH": null,
"ZSI25IY4L2U7CRPBLOYY5TCSAVG22XHHZFC7JZCRAVY46BWH": null,
"HUSGTJENHNIBJ7VSWZPOWFHHKKYH7H2YSP32LLQ2N7CWKRME": null,
"WTIJK6LZPBOCIJFBZEG26BETKTY5PJKQK5D3M5WVPWVSV7LN": null,
"ITSWONDXALFBD4WMGSMRKQXCVTL7JRKVFEHOAOODRQEFFSWC": null,
"IY3RQGYC2ME2TEUBYAQG5WJ7WOAJV5GTO6P3FKXWOLSJWGCD": null,
"MDSHVZ5WHCTCYB34ZABEUJJRXHQDKO5MSC5YVTGPMNJRXQK7": null,
"KHNSXQTOSCRSTX63S7OVO2LGMD7OVR6PZIGEKL5ZDYPCEKK6": null,
"LECVNJKLFT6P2HWX3H7ZC5DKJSSRZ7PWZVBN735K7I45SOX4": null,
"HFEO55KM3XH34UWCRYM5CFNQ6OFRAKM3U6TABNQDP74DT4JQ": null,
"QZOWC3TAAU67PVSBRJOOVZCBSRIOZCMLPB3FH4GS37WOSTEZ": null,
"TSB72AJ4HHOBEYK4CGFX3W4RW3SIECQYJMYISHTPPCGQNLFD": null,
"6AB4YKYVMU2PXRABAUBBBF4BJ3IOFKYWBJ2IMFMRVLCBI4S4": null,
"E3TI3V725PEP7U2CYZUUKJEBPAHOEI5SYCR3YZCMGD5EGYHF": null,
"APKJUBCO5NHY6QBYNA2ADB5TTPLCNZMHG7HGXXOLRBOZD46Y": null,
"QKL26OQG6L54OCKFPLMXI6M3EG2HI4EG34D7BNI5SBZG6OF7": null,
"W4KKIH4RPYXL4JZY24JWLHOATFNENBMSEQQ3DI7WW4PQIJQ3": null,
"4XJPWCDQXS6MSKI4EMFPENOX5FV7KMKKZ77LV6GJ6S7ZBVB2": null,
"LWMCTL5CEAVQDT5PEXFKRK7Q264CNVV6AU657OQ3SSPCDGSQ": null,
"CBMCT6STEYDOVXT6OW34OXGZBN2A77OGBPDRN5AZK4RXNEV5": null,
"OUGRMVL7PTQ3GJNWQ5WP7XXNYBIMVWKSNQ2QZH5RZRDEGUND": null,
"XKVAYVNQL7KW5EHGEWYRPSWDXNUEKP3YC3OXGEHKG7PGNZHL": null,
"ZLO6BOTXUEEW7UOENY2NVIFLSG37YPUETQBYYCQBJM5VXNG4": null,
"QMZJWAJYYE6WZQX3OKY34BPU7ZZN6ECDNIZOIXREE6AP3WJF": null,
"B5FU7VNVUSA3ODDEUDVTKE7GWPU3JQXWHRWYGLT6VFKSFYAA": null,
"HLHSAJUSHU5EY26UTR2UDJAM3BIHYYHF46MNLTQZJWDAUCDO": null,
"N73SLU2EDTPQ54MY5NWT7KPSVTO3TOGPO3DGX4HQYPZMFYJV": null,
"7B47MDGTJA3P2WX3KWLLESWTC7RJUSVUSBI42SATEYZVPL5K": null,
"YYLWTHMS5POBP3WVX5Q4NXQ77STWJTAHE6QK7GYMBIJU3TSX": null,
"JI7Q6GUWUTSJPHKUII5IVOUZ2QQ53EWNWCUM4PKECXWSVSEK": null,
"XR4W6GZYNYIDAFU7MWMIGFGF63OLKU4FWQZ4RAN3HWNXUINB": null,
"3KX2TVZZAQSYQHLDSWMVZVF4UAXYONTXXFWSGI6CJ56DXU6O": null,
"UR6JGWK36D4CU63DYI722UFUKLB2S52ZI4OAVZM7CVGGY3SW": null,
"VGQOGZH3H5IAFESOYWHOQGU5FHP4BJAUUK2B7AKDCJX3PUE5": null,
"Y5GO3VITRDTHWTMUULEA44BVX3GHVLIWFMTNUY2APWRL3JLD": null,
"F7U4AV4VU7YAEDK6SI64JJUNEHG2MEFLKNOI77IVDQS7BGJK": null,
"D77762UIMSS52GNAPWFCEEFPWGYLBPKWMBN75S3HCOI2SYCL": null,
"NNRBK2PM7FI7MVFBSUUCZVFTDOKXLNVK6I4MMUXU4AKDPTCK": null,
"YSGZXEZQRGZ3DSMNCNH6GSWGCRWQSIRD3IOR5E3XEUH5RORJ": null,
"P6KRZXZTESTNZHYLZFTDLZMIGIN5H74H2KYUTNRIC3JWCNJ2": null,
"QK36OWDC6RHQIASJXU2HZVIBARNIESSCWKICTRQ4B3OFUB6D": null,
"JQBWWRLDDMH3HACHKR7EKXFCAAR5E62DX3ALK22Y5AFA4JDZ": null,
"WWOLYDEZIQARIEC65MFSVB5RH3236B3E2YSGNEN2QY6A2G54": null,
"QT5UVU5QUPEY7VCTTW26JTO2FBUUBCRBYZORWGTYQZ2JZSCH": null,
"PJQFD75BGF35X4N33WD423KSDLIAWJNAZUBXQTUGHOW4PTXJ": null,
"A5VRG2DRN3CKKTP2DN5YNILXVCZRTKFXWILKWLZ6PNVKJTM5": null,
"TY4YPLWS4MDSKPG2HHIRSAWK37LFVB357RGGBRFP2P332HJL": null,
"SUC7ZGB6YKDYNAP6NTUZVEVNDL22KBCRZIGAWSOBUAL55LDE": null,
"Z5I7WKVA6754S4G7QWWXYTRZ3SGEG4B3KG5MLHP3GJDI3H7M": null,
"VLGCWOT665AT2R6EMOAVHNKVM2NKPSV4KI4CMNEUZ2YMI3UP": null,
"YJMQW3C2NIIZKTJY34XRL4HQ5A7EUMLMXTJFHHRE3NR3QGZF": null,
"TOEB56GVW7OQ7QLL25ZY3ABP4ZQS2ZZMIJRNTILE5CWA2IZB": null,
"5RGLCKE6D2MM5YH74OJBDHTOZIM7LN3EIYBLXVF4PGNBZON4": null,
"QMQPPFLB6NCEBYCQ5U2YWVYWRKZSFJLCDAAPYSPURDLXAU6G": null,
"UTAFBURT6XHHZV3Y5OZJBJJQT4342SSCOLWT35GZIJUPWTTM": null,
"XCIXTAB5SB5EMQLZW7GCBUS2N3XU44YELMLSYIFAJHHGP3VS": null,
"LWL5AM7Q4JPEDEORTLNDWUF5X4AIUI4QC5S4CWUXKXIWP6FP": null,
"M4RONO5HAPE25Q46SSRBVQLEXPCVQLKOKX2NYQWX2SNNGEVB": null,
"UVSHBLSXOHEF3AGG5PDTTDFVXNQPRHCNUTXYDEXJVXI7JCPL": null,
"C3PB24XOHCI52DU64XQL2V2OKZZYG5B4T6PUU44DZCH4DMSS": null,
"VGACAPDUB2J7KLW5PA474JQZWZ6QCDYYB2I32ZFYGXR64M2Y": null,
"NNDVFWEC2OE56D5PLJWEEVG25TMXCXISOUOYDOUEMUZRMZK4": null,
"57TIZBR3DXRX74YXCSJ2RXLZRXKX3K7H6WPS7DVONX7DOJY3": null,
"RFSCST6ITGG53EAZEBXD2VFQTJ53ATEOORQV6SQG5OSDR3FM": null,
"YLIXTKYNMODZNBM3L2EL435GD2LRJ5XAJBDZSYCU3OPZ4N4V": null,
"FBEPPECF3L4RB6QBQLGL44JDBCQCTQ5MOFYFCUQVNL4DCQYV": null,
"PAJST32KEXY6I2Y57OASSUFLF2BLPQQ7NZMVN6EVR7JS5LY3": null,
"76MHL43MEQWH6R552TULI3TLBOR22YDMJC5ZYQVWCNI4BWF2": null,
"A6KZM4OXBKW2NJ7X545F4LIDSC7LIAFYJ4CJSWW2BWSIRWUY": null,
"VND76C7TCKQT6R4X56OD4UYSOBZGC5BQ3LR6RXOX6LA3I5F6": null,
"CE2NODHXCRS4ML26HTI77Q57R7ZXKZO433LHHA66I5U3Y5GP": null,
"3DGAXWQDLZBPUYZPBGMRZG5DOBPTIHKAXFSCBLMEQHZ2A4W2": null,
"NAOTRV3ZNB2PK6RZJZ4UEQVF5M3YISGJNFZQQWPV2S5RL7XM": null,
"HLCSR65OBO7BJQPOA65Q6BRDVFPOL7FJII2LOANRJNUM2DDU": null,
"YCBI6X4JLTHKGAFR7XYKELWE7JW6VHLMFJIWF2ZC7BPCQFFR": null,
"QEF3LB5GFEMHAUDKPPNYGRKUUV6PAWU5XXYCFIHXI7PLGVGW": null,
"ABBQK5JKJZLMX4KGFODWSEHOPDTRHGDZCBO3ULBVOGUIAAGI": null,
"HZLWUQNBAZJSDZEB6IPXQIUMVWUPYVMVP2N72NJ4MOZFUKGT": null,
"7SQCYMGSMYW47TXUWC2J5674L4CRDIAO34D342D7IJ6OE23F": null,
"YAQCDYBXIOY3KZGFJCPS5VD7YQBPBFFFYEA4DPWFWJCWCJXA": null,
"HCZ7SSO422NW6O3ARCBUGNBCMUVEAHXMVKAJSDBHAQSFXIMV": null,
"DPX2FNJNMFQT34DLAOEIN4KMWJYLOEGV7U4VDH635AG6UA5T": null,
"QUO6FPOFFXUUKAZXYRN7N2MMT7IOJEG6NLFIH7B5JI5V2Y44": null,
"UJ6G5JMOINYVRLVISHWTGQDDDWA6X3QDFICKY4QQIHG3QMF4": null,
"ZR3VRUOZMQE4EMVT2WDB45TJ7KB5AGU5UBBPNL2A2D255MOL": null,
"2AFEUH4R6YAJZEODKJBMLDM4ANLCKRU2C33HFSVU2LLXZW5Y": null,
"3S4PV2VOBFB6GFRPG5SB3EHMZE5M7VAAFRJ3JQYHZEFTEKFX": null,
"6EFK4THSCBEG4LDSVE5N5FXSQJTYB5SQ7LKJRBL6IYIREWTN": null,
"HHYCWLKLIII7MJ4MYU7CJZ4YPOOUVWOKLXHZV5NT6LU7WWGX": null,
"XYRSXFI6XRY3YACAIVIZJAVKFTZPRH5FXD7E4P4LYUGX6I5U": null,
"6W72FMK5AP56TNCZ3LE5OTYZ3WYPARBB5AOXDVHGCBOTWZTO": null,
"7YNUW4DUCHUDJSSAWSYOYM2QXWTVSJWGDPIG2EAABTU4QLU5": null,
"HNVXP5XULHDT666ND2M3X2APGXOBCB7SCQB2D7MFQKKNVOS4": null,
"MLCMV4777C55OEVW3SFO4VHH56O7BSIDLZFYYTY3JXNN4DWG": null,
"MSNRSOCYC3HQCUXRLCBYFYQOMJFBDOSHJ3HYYYOHEPODETEE": null,
"BJB2U3W5ZF7WQVTL6R2F542WSS6FQDSVDMXNYWIC5PHED4HH": null,
"E26RFAVZYOV5WZ6WQDVINCGNG6ZYU2XCV4FPEKR45IASGARQ": null,
"4BK33GLSBFLRZHOHECAVVYT3LJHSQ5RFBSMKLMGTK4Z5RGZO": null,
"5I3526BP3QPLNDBEIPVQL2GOAMRBAYWOMILMQK5IT7RES3EV": null,
"IBHOZ4VNFYMLMUNOZIGK743IVASI3DXHCY2RH6SO4EKNGR4A": null,
"CCZT4EOMTISCMIVGMB2ZRUGFIR3R6WKU3ISSJ3VZVA6SBLFC": null,
"OGJUH7B3WKG3W2UFEBL63KLQGPSPRNIHUUKWTKQMBN5QG42E": null,
"Y6JCIA2AYVA3RDOUQFYWI4EMF64H5FIFNAHSKZ6LXCRXCFGW": null,
"VX3OCLLJZPGXWTLGERIMK5IS4OXKU65SMC4YS5JZND6VEPO7": null,
"UXWF26BRES53JKXYXEG5DWJXCR6USGPBWQBDJEVEBA2PPUAI": null,
"IB5SSNMYSFCNB4ODT5OQ2GAGPIVDWOBEI3P3EBWI7AUGC7BR": null,
"ASIAQKC3VSFJE7ZW472ZOAXX2T7JTCLZBN5BYEOAE7E67F5Z": null,
"BKQ3GY255BDDVZ52IIR5K3NFIEKV6GXBVTX3ROY3IN7XDAHA": null,
"JTV5ULWFJJOSFTX32FA6DJWADX5UL3NV4RZZS3Z64IPXDZNK": null,
"GSZ7MZXCFKAWFBXKRVYUDULPJEH3WSI2K634LAAA36M2FRF3": null,
"HSPTZMNCONTGJGIUWP7ZR277AYWTDIKPAWO4RODOIHQGEUF3": null,
"4ABCWRBBUAO5TVOSOZDF3KMCUCKIUCRJSBGH4WGKDHWH3LLN": null,
"K3BK4XFUTDJLS7KY4WJBS7RTZ65HY4N5NJ6AMKNKGO3K6DXG": null,
"S4VZEKYRNOXUITHJENCBKJN6CC6QV7Y4MIHQ6NLN24OJFMBP": null,
"MRM4HMHS2KAISLXU2XYFQCQH7XRVVC3EXSP6JU7FIM2DJHVV": null,
"QMNCR2JQYOST5MD3HI2I4MCTSJDFCAGUTEE6XKM2THC4WXI3": null,
"ANIF4DT5IA4IY7M5OISD4IW4J2TDVHHFIPEONUU4CV75LOFZ": null,
"TQHJIX3NKO5CMVRNOG4WP3YDSGPLTTCRBA3RDBPECWO6EN5U": null,
"6KI4L4RRXZ6WL3TRMCZLAA2W7AQRXDCC43O6AGYJ75NUEQO6": null,
"VL57QTQMHQOAX5MFQTX7GUWOECHVTLYJHIBRKMWIRF4QMN6M": null,
"JFTGBEP2LSZGDDFGV6IV2JAS3J3HB7BDRB6WEYHSC5EIFNA3": null,
"WLEZIN5PPCJE4W2LGEPW4N6AWQ4RLE2AOGFBTETY5HNRSZCY": null,
"LUJRHNRDNK7YOKST7KRVQGVE2ERU3LUVPZLC5YYLCUAX2EEU": null,
"F2OOXAP3FFVMQMJP5IVDLRVV6IP2NUTGT5MGZCJMR2IFNA55": null,
"SVL525L4TVBTLMH22DTXVCNECAZVUTMMYDTA3UQGV7U6P3YU": null,
"546BD77L33PUPQ7TW3GJJVVJTYKHIIKF7YOO4SSGIIIOIJ2Z": null,
"FCZRNOURTDJI2BE7HJ3P4MMY4WYAPFFBCTVFXVTYSK4UB4JK": null,
"S2U5XQEC7I4HOUUR6HFXUF2PR2CLNF5UEIPJHTNF2JM5BZUJ": null,
"JTQGSOTIPVYKGYJBUQC3Y44RWE372S7MPMFDETMH6OEGUJWA": null,
"W3DTWDN6YOEPVUJVUDNPWCLQMXXCLXQPVYU27675LZM4ONDF": null,
"LJ7P7AJNNHJE24PNWQDK7J4VGGNZKKR3OPVRFV5A4U6LRFRW": null,
"I4QO3SZC4455G5PQIJPUUNI4A2BPJKTH5MBA7LN3HRIW6EFZ": null,
"NNR3EXDDDPBTOKTRBPR5SO4OFPXU376ZIEHA6YHEJK57ZRGH": null,
"4MBIV5HD4ZMXY5NIKZQIFKFO7S642PC7CWVX7ATXAXWQWNGU": null,
"A6S5KTN66UWYBWG5CZXJVCJ2F2EA22BCZDFQMM523DU7VFBG": null,
"AOAPML4IEVJZSZUOONTTDYSEN465IHW7MZXHSQ55E47TJ2NW": null,
"ZIW5DXTPGQLTTRHPRQB7SADQPCSTXQRMKHZIXA6T6YW2BMRS": null,
"OUHF6P7JPB5Z2C2E5MEPNQ5R3NY56KNQFHG3RYGWXBYKRRI7": null,
"M3JXOC3CTIEMVHTQW7HB2WQ7L7Q54AWFY6F2UBTSZMDXHTDI": null,
"WQQA7JW5NTSAI73WVQMMAJ4IO6OKZR32GTQTMUWE2HLC7DRH": null,
"WGDVRLD5YWTXFOFTGBBEFCG455EK3BZCZEE2POAX56O3EOQW": null,
"6KAR3LTBYTJ6WRGOUQ2TEPZKWVVBPGCO4OVAN2ADNDNLTOSM": null,
"VEWL2DORBATRWF5HJ7LG66NYWMXH37JJU6XWVGJNDVL3OSAM": null,
"B4HXCGMG5S3VEOZR5IUYOZAEFL6WPRLXB26SLWZHRY3WL3ZU": null,
"REKI5EIO6TNXBWJIENJDQ5CAYEYZC2GXVPAOIWGVXKN2K3OE": null,
"RBOY2SVFDRIKJZWTWVEGSJLHGIMAZXIF5HNBZAKPVRTEFR3A": null,
"SIOSHIHS52CHIB73RFONJOM2HJBTRLGGDFW6JAWTR6UPJBVB": null,
"ZGHKTW43CXC3CBOLSENIMDQUIR22VNXSE6HFBT6ZUA3TPODL": null,
"XA576OGJNZK3AXE3FJLSSGN5MGRK4FJJ2XX3UHHFI6NO7P25": null,
"22VL7B7ZI53VMYEYHKBI7XYNKRQW634B6RLBRXRJN4CQJA6G": null,
"YVHEMU6OLF3FI2MTMZ25QKT5F2OUO3H6CX4WRNEXVH4BO3WZ": null,
"3VJOBPUJI5DUFHNRM456UWSAHIZYXICY7ZFYMECCUHDTG444": null,
"BXLYOEBYW7R4MWPNTOZ2ZJPDDXBHV7JMH75NCD26VGS2VRH7": null,
"GCZOZTTLMHTAKVUQ4TSDOOPHEGK6PH4JQ3ULKZCUIEDW2HLX": null,
"TE6B4JOPAY2CEQ46KJV7N6MY7OAI4VA3UBBXGPOELN7KY5T7": null,
"62BPAKDHZ7ZRJOMVZ2SX2WAKFQATUQLKDQ7YGACJPL2NP4UR": null,
"6U3MTBST24MIPS3HSZJPTBSZJ54T63GMZGZQPGFBS7JGBUVX": null,
"SXBYC5BKXYT4DFNVSS4OVRYLNA5JY4TXMVTIFSCRT6Q5C265": null,
"TAMMZOCU5GDDOIRG6U53NW3UUEUGI3QWW6YY6GWNE7WIHRNE": null,
"O37BSKPNGDUUN24XFSCR2IQHWFYUZJBPWSNC4L43MH5HV272": null,
"AZFWV3I3DANXV3HJB66QMCFJ3UTVJGS3R3IP7VROF2D5JF6U": null,
"W2BLY5MU4PA7HSENYW4MO6VHHPBXUFCFMSBWTCL5F3BIPBFT": null,
"ILFL3JG2XQGZCFBJHZFQRZMLGHZWVRBX3M5Z3HXW2A4GDMNK": null,
"O7VDC3EDG5I567RK5BKXMKA2R6XPHQQPDXQTCZP7BHKV5BK6": null,
"5ZMIJOTL3NPRKBEPS7542ICCNHHUJ2BNOZ7LSL2ICTCUFGSC": null,
"FCTKLPX7PYRSVVBH4KN46HEYLJEYSRTQ3PCUU5RY3BROUZKU": null,
"7EAMJ4C7NUA3XMDDOF3YRJA7Q2BFXFCI4J24ZXSVE7REBRFU": null,
"NOQ6OL6G7QD4ILQ3FAEMEMROBCK4OK3LX3CRMHMA6GG5YIYK": null,
"N3XXFRDRYPWGZ3LDGLIXGLLJYKEHPW4565BUUL67OLMXP554": null,
"GFHEEY3HHESZDI2YHTDDCBKGE3ZPWPXW2WE5AKNL2Y2TJCNJ": null,
"JTUQIEPPBM2QC6XBY3KP2NSDM6WUCJMORCBXNU6ZPXPOHEIW": null,
"V5VTVJ36JZDDO5FIOEZNAKYWPRQSUSTEZAKARDOHQEIFLACE": null,
"KUTOUNOS2QL4O6HF266ANCBNYUSIT66TANXCGYALCPZXULQH": null,
"CJILUW3VUBZCSO5DXTSE4HSVW5UJAJHHCSHGHADKCQE5OTBU": null,
"HD72YVUCR4IY5MG3E73UM35ARFCUIHEPIMUSQXOKLVTT2V67": null,
"ELVTZXW3ZAKR76K6IV6ZHX7WTMKPKIFRPHIU3LK67WQR6IQG": null,
"NIZTNRLCIS4JDLMOTEAKPA6B2JOE76ZBQDEUUGXENEJBYJFV": null,
"FE743ELPJYDYWTJ374PZVE4TNGZPDZWSNUO5PATNYUYBDTBJ": null,
"FIT3JHSZMFJ7N2E7BL6PHEUUHSBHU55YBIH763TGSZQTIAZY": null,
"AP7SXAQ6HW373QPCHKKA4R7NFFUCD7CFB7EERZBNXRGM2Z7R": null,
"BAW6TALQRWXK2OWS2O2UV72BKZGBZCUPR6AXKFZ7WHZXZXWX": null,
"SM3FE7H4NI76AS5YCH6O34LTROZKJ7FEP4IKL33JUBI7FWZJ": null,
"BNO2EJXVMAPFDVF34NBTPSIYKI3UPFI5G2K6KGVU35TIHOQL": null,
"INHCLRC6WPTE2U7OQRSSRGCN4B5K4BUVSGFHEKG5DWJWICOF": null,
"OEHWM7QZ3H67QC4ZQY2USKQA62NLMESA543KWPBUKV7N65TQ": null,
"BN3U5KDJP3QGOSBX3TH5R2DR6PZA5Z7BEGVG6MYRW5GWUCGT": null,
"ID7S7JEGBCI7ES3ZN7PIW5NEP67WTL5H5IB6WVRYS47EEEJ2": null,
"BG4MHZNCCLZQN563CZ2D72CPT5TASZZ6N6L4JOW2XPR7GIDQ": null,
"IAQKAEEUCCT3ZZY5LCO4AZW6F6ZNGUAF56UCD43OPOKSMBHR": null,
"LFCSYYMAFZ5IAB5O4QIEN5GERYIGTH4JH266LORQ36SB2A26": null,
"J7W62H5B42N3YUEFS5F2MECESYBUVHXSIGRMZL6ZNQMCYQMQ": null,
"J24FG5J3MUQOCDAVVCHM6BJWZW4Y7VCSC73DW32TMKIUOXPB": null,
"DGJE6OPBSV3JW45P5WC3EGUMIETVT7MIZX4EA5SCY2F3JKFL": null,
"KWTJYJJT2LMBHE6WH4LNJEHNMNJVOEQ7SLLXGJKWPGOFDYHQ": null,
"7XZDDO3CCV34UECRKEM344EDKKUFD6YDUJ7EW4OAETABTYWV": null,
"BPS2OSY2SOAFFPRY24IEXGZVBEUNVIWZYTVVZRUWT7XM727T": null,
"6GRVGHI3FMCQ5MQ4JR7ORANBXK6GMSI4XRQVE35LPH44XROO": null,
"MZHRR2BS6HII6JD3H32DPSYTTHCVXE4WSC7NUURU43Z5SD56": null,
"QJBSWHFQKABG4CALELT62JWLMW2JVZP35RDYHWHQPZYTIX5M": null,
"K2Y3YRBFB7F5PJJUFJDH5Z5NL2MYOQWGT5T5VI5SP7TVM5NW": null,
"QLONNH4NMZX5WLEJPQEWJECL5JTLTWDSK234NU5H55GA6PFG": null,
"NSSRUR3GI6B7NBK77ZQIIHOA4TEEA5UXVVMRWVLMRIP6SN3T": null,
"WB2TXRE7EPSBGACXUA4YE23M4WLMG3PVRMD2OOCIHNGQVDRY": null,
"3MDCQC5BPGFGGFDO4C4IY53NPTWZMRK5MWLJG2KX7OWVQNFO": null
}

0
bin/types/booleans.json Executable file → Normal file
View File

0
bin/types/floats.json Executable file → Normal file
View File

0
bin/types/guids.json Executable file → Normal file
View File

0
bin/types/integers.json Executable file → Normal file
View File

0
bin/types/mixed.json Executable file → Normal file
View File

0
bin/types/nulls.json Executable file → Normal file
View File

0
bin/types/paragraphs.json Executable file → Normal file
View File

View File

@ -0,0 +1,138 @@
{
"type": "object",
"properties": {
"version": {
"$ref": "#/definitions/decimal_type"
},
"address": {
"$ref": "#/definitions/address_type"
},
"phones": {
"type": "array",
"minItems": 1,
"maxItems": 2,
"uniqueItems": true,
"items": {
"$ref": "#/definitions/phone_type"
}
},
"names": {
"type": "array",
"items": [
{ "type": "string" },
{ "type": "string" }
],
"additionalItems": false
},
"extra": {
"type": "object",
"patternProperties": {
"^S_": { "type": "string" }
}
},
"gender": {
"type": "string",
"enum": ["M", "F"]
}
},
"additionalProperties": false,
"dependencies": {
"address": [ "version" ],
"names": {
"properties": {
"version": { "$ref": "#/definitions/decimal_type" }
},
"required": ["version"]
}
},
"definitions": {
"address_type": {
"type": "object",
"properties": {
"number": {
"$ref": "#/definitions/positiveInt_type"
},
"street1": {
"type": "string"
},
"street2": {
"type": ["string", "null"]
},
"street3": {
"not": { "type": ["boolean", "number", ",integer", "object", "null"] }
},
"city": {
"type": "string",
"maxLength": 10,
"minLength": 4
},
"area": {
"oneOf": [
{ "$ref": "#/definitions/county_type" },
{ "$ref": "#/definitions/province_type" }
]
},
"country": {
"allOf": [
{ "$ref": "#/definitions/country_type" }
]
},
"postcode": {
"anyOf": [
{ "type": "string", "pattern": "^[A-Z]{2}[0-9]{1,2} [0-9][A-Z]{2}$" },
{ "type": "string", "pattern": "^[0-9]{5}$" }
]
}
},
"minProperties": 7,
"required": [
"number",
"street1",
"city"
]
},
"country_type": {
"type": "string",
"enum": ["UK", "Canada"]
},
"county_type": {
"type": "string",
"enum": ["Sussex", "Surrey", "Kent", "Narnia"]
},
"province_type": {
"type": "string",
"enum": ["Quebec", "Narnia", "BC", "Alberta"]
},
"date_type": {
"pattern": "^([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)?$",
"type": "string"
},
"positiveInt_type": {
"minimum": 0,
"exclusiveMinimum": true,
"maximum": 100,
"exclusiveMaximum": true,
"type": "integer"
},
"decimal_type": {
"multipleOf": 1.0,
"type": "number"
},
"time_type": {
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\\.[0-9]+)?$",
"type": "string"
},
"unsignedInt_type": {
"type": "integer",
"minimum": 0,
"maximum": 99999
},
"phone_type": {
"pattern": "^[0-9]*-[0-9]*",
"type": "string"
},
"url_type": {
"type": "string"
}
}
}

View File

@ -0,0 +1,7 @@
{
"allOf": [
{
"$ref": "http://localhost:1234/address.json#"
}
]
}

View File

@ -0,0 +1,7 @@
{
"anyOf": [
{
"$ref": "http://localhost:1234/address.json#"
}
]
}

View File

@ -0,0 +1,69 @@
{
"id": "http://example.com/root.json",
"definitions": {
"A": {
"id": "#foo",
"type": "integer"
},
"B": {
"id": "other.json",
"definitions": {
"X": {
"id": "#bar",
"type": "boolean"
},
"Y": {
"$ref": "#/definitions/X"
},
"W": {
"$ref": "#/definitions/Y"
},
"Z": {
"$ref": "#bar"
},
"N": {
"properties": {
"NX": {
"$ref": "#/definitions/X"
}
}
}
}
}
},
"properties": {
"PA1": {
"$ref": "http://example.com/root.json#/definitions/A"
},
"PA2": {
"$ref": "#/definitions/A"
},
"PA3": {
"$ref": "#foo"
},
"PX1": {
"$ref": "#/definitions/B/definitions/X"
},
"PX2Y": {
"$ref": "#/definitions/B/definitions/Y"
},
"PX3Z": {
"$ref": "#/definitions/B/definitions/Z"
},
"PX4": {
"$ref": "http://example.com/other.json#/definitions/X"
},
"PX5": {
"$ref": "other.json#/definitions/X"
},
"PX6": {
"$ref": "other.json#bar"
},
"PX7W": {
"$ref": "#/definitions/B/definitions/W"
},
"PX8N": {
"$ref": "#/definitions/B/definitions/N"
}
}
}

View File

@ -0,0 +1,7 @@
{
"oneOf": [
{
"$ref": "http://localhost:1234/address.json#"
}
]
}

45
contrib/natvis/LICENSE Normal file
View File

@ -0,0 +1,45 @@
The MIT License (MIT)
Copyright (c) 2017 Bart Muzzin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Derived from:
The MIT License (MIT)
Copyright (c) 2015 mojmir svoboda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

7
contrib/natvis/README.md Normal file
View File

@ -0,0 +1,7 @@
# rapidjson.natvis
This file can be used as a [Visual Studio Visualizer](https://docs.microsoft.com/en-gb/visualstudio/debugger/create-custom-views-of-native-objects) to aid in visualizing rapidjson structures within the Visual Studio debugger. Natvis visualizers are supported in Visual Studio 2012 and later. To install, copy the file into this directory:
`%USERPROFILE%\Documents\Visual Studio 2012\Visualizers`
Each version of Visual Studio has a similar directory, it must be copied into each directory to be used with that particular version. In Visual Studio 2015 and later, this can be done without restarting Visual Studio (a new debugging session must be started).

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<!-- rapidjson::GenericValue - basic support -->
<Type Name="rapidjson::GenericValue&lt;*,*&gt;">
<DisplayString Condition="(data_.f.flags &amp; kTypeMask) == rapidjson::kNullType">null</DisplayString>
<DisplayString Condition="data_.f.flags == kTrueFlag">true</DisplayString>
<DisplayString Condition="data_.f.flags == kFalseFlag">false</DisplayString>
<DisplayString Condition="data_.f.flags == kShortStringFlag">{(const Ch*)data_.ss.str,na}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kTypeMask) == rapidjson::kStringType">{(const Ch*)((size_t)data_.s.str &amp; 0x0000FFFFFFFFFFFF),[data_.s.length]na}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberIntFlag) == kNumberIntFlag">{data_.n.i.i}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberUintFlag) == kNumberUintFlag">{data_.n.u.u}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberInt64Flag) == kNumberInt64Flag">{data_.n.i64}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberUint64Flag) == kNumberUint64Flag">{data_.n.u64}</DisplayString>
<DisplayString Condition="(data_.f.flags &amp; kNumberDoubleFlag) == kNumberDoubleFlag">{data_.n.d}</DisplayString>
<DisplayString Condition="data_.f.flags == rapidjson::kObjectType">Object members={data_.o.size}</DisplayString>
<DisplayString Condition="data_.f.flags == rapidjson::kArrayType">Array members={data_.a.size}</DisplayString>
<Expand>
<Item Condition="data_.f.flags == rapidjson::kObjectType" Name="[size]">data_.o.size</Item>
<Item Condition="data_.f.flags == rapidjson::kObjectType" Name="[capacity]">data_.o.capacity</Item>
<ArrayItems Condition="data_.f.flags == rapidjson::kObjectType">
<Size>data_.o.size</Size>
<!-- NOTE: Rapidjson stores some extra data in the high bits of pointers, which is why the mask -->
<ValuePointer>(rapidjson::GenericMember&lt;$T1,$T2&gt;*)(((size_t)data_.o.members) &amp; 0x0000FFFFFFFFFFFF)</ValuePointer>
</ArrayItems>
<Item Condition="data_.f.flags == rapidjson::kArrayType" Name="[size]">data_.a.size</Item>
<Item Condition="data_.f.flags == rapidjson::kArrayType" Name="[capacity]">data_.a.capacity</Item>
<ArrayItems Condition="data_.f.flags == rapidjson::kArrayType">
<Size>data_.a.size</Size>
<!-- NOTE: Rapidjson stores some extra data in the high bits of pointers, which is why the mask -->
<ValuePointer>(rapidjson::GenericValue&lt;$T1,$T2&gt;*)(((size_t)data_.a.elements) &amp; 0x0000FFFFFFFFFFFF)</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -10,11 +10,13 @@ ELSE()
CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY)
CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY)
file(GLOB DOXYFILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*)
add_custom_command(OUTPUT html
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${DOXYFILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../
)

View File

@ -1126,7 +1126,7 @@ HTML_STYLESHEET =
# defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.

View File

@ -777,7 +777,7 @@ INPUT = readme.zh-cn.md \
doc/sax.zh-cn.md \
doc/schema.zh-cn.md \
doc/performance.zh-cn.md \
doc/internals.md \
doc/internals.zh-cn.md \
doc/faq.zh-cn.md
# This tag can be used to specify the character encoding of the source files
@ -1126,7 +1126,7 @@ HTML_STYLESHEET =
# defined cascading style sheet that is included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.

View File

@ -18,7 +18,7 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c1 [label="{contact:array|}", fillcolor=4]
c1 [label="{contacts:array|}", fillcolor=4]
c11 [label="{|}"]
c12 [label="{|}"]
c13 [shape="none", label="...", style="solid"]
@ -41,13 +41,13 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c2 [label="{contact:array|}", fillcolor=4]
c2 [label="{contacts:array|}", fillcolor=4]
c3 [label="{array|}", fillcolor=4]
c21 [label="{|}"]
c22 [label="{|}"]
c23 [shape=none, label="...", style="solid"]
o2 [label="{o:object|}", fillcolor=3]
cs [label="{string|\"contact\"}", fillcolor=5]
cs [label="{string|\"contacts\"}", fillcolor=5]
c31 [label="{|}"]
c32 [label="{|}"]
c33 [shape="none", label="...", style="solid"]
@ -59,4 +59,4 @@ digraph {
c3 -> { c31; c32; c33 }
}
ghost -> o2 [style=invis]
}
}

View File

@ -19,7 +19,7 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c1 [label="{contact:array|}", fillcolor=4]
c1 [label="{contacts:array|}", fillcolor=4]
c11 [label="{|}"]
c12 [label="{|}"]
c13 [shape=none, label="...", style="solid"]
@ -42,13 +42,13 @@ digraph {
node [shape=Mrecord, style=filled, colorscheme=spectral7]
c2 [label="{contact:null|}", fillcolor=1]
c2 [label="{contacts:null|}", fillcolor=1]
c3 [label="{array|}", fillcolor=4]
c21 [label="{|}"]
c22 [label="{|}"]
c23 [shape="none", label="...", style="solid"]
o2 [label="{o:object|}", fillcolor=3]
cs [label="{string|\"contact\"}", fillcolor=5]
cs [label="{string|\"contacts\"}", fillcolor=5]
c2 -> o2 [style="dashed", constraint=false, label="AddMember", style=invis]
edge [arrowhead=vee]
@ -57,4 +57,4 @@ digraph {
cs -> c3 [arrowhead=none]
}
ghost -> o2 [style=invis]
}
}

View File

@ -119,6 +119,7 @@ Parse flags | Meaning
`kParseNumbersAsStringsFlag` | Parse numerical type values as strings.
`kParseTrailingCommasFlag` | Allow trailing commas at the end of objects and arrays (relaxed JSON syntax).
`kParseNanAndInfFlag` | Allow parsing `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (relaxed JSON syntax).
`kParseEscapedApostropheFlag` | Allow escaped apostrophe `\'` in strings (relaxed JSON syntax).
By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time.
@ -128,7 +129,7 @@ And the `InputStream` is type of input stream.
## Parse Error {#ParseError}
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffset()`.
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetErrorOffset()`.
Parse Error Code | Description
--------------------------------------------|---------------------------------------------------
@ -241,7 +242,7 @@ Some techniques about using DOM API is discussed here.
## DOM as SAX Event Publisher
In RapidJSON, stringifying a DOM with `Writer` may be look a little bit weired.
In RapidJSON, stringifying a DOM with `Writer` may be look a little bit weird.
~~~~~~~~~~cpp
// ...

View File

@ -1,6 +1,6 @@
# DOM
文档对象模型Document Object Model, DOM是一种罝于内存中的 JSON 表示方式,以供查询及操作。我们于 [教程](doc/tutorial.zh-cn.md) 中介绍了 DOM 的基本用法,本节将讲述一些细节及高级用法。
文档对象模型Document Object Model, DOM是一种罝于内存中的 JSON 表示方式,以供查询及操作。我们于 [教程](doc/tutorial.zh-cn.md) 中介绍了 DOM 的基本用法,本节将讲述一些细节及高级用法。
[TOC]
@ -119,6 +119,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
`kParseNumbersAsStringsFlag` | 把数字类型解析成字符串。
`kParseTrailingCommasFlag` | 容许在对象和数组结束前含有逗号(放宽的 JSON 语法)。
`kParseNanAndInfFlag` | 容许 `NaN``Inf``Infinity``-Inf``-Infinity` 作为 `double` 值(放宽的 JSON 语法)。
`kParseEscapedApostropheFlag` | 容许字符串中转义单引号 `\'` (放宽的 JSON 语法)。
由于使用了非类型模板参数而不是函数参数C++ 编译器能为个别组合生成代码,以改善性能及减少代码尺寸(当只用单种特化)。缺点是需要在编译期决定标志。
@ -128,7 +129,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
## 解析错误 {#ParseError}
当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会 * 维持不便 *。可使用 `bool HasParseError()``ParseErrorCode GetParseError()``size_t GetParseOffset()` 获取解析的错误状态。
当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会*维持不变*。可使用 `bool HasParseError()``ParseErrorCode GetParseError()``size_t GetErrorOffset()` 获取解析的错误状态。
解析错误代号 | 描述
--------------------------------------------|---------------------------------------------------

View File

@ -10,7 +10,7 @@ The earlier [RFC4627](http://www.ietf.org/rfc/rfc4627.txt) stated that,
> (in §6) JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible. When JSON is written in UTF-16 or UTF-32, the binary content-transfer-encoding must be used.
RapidJSON supports various encodings. It can also validate the encodings of JSON, and transconding JSON among encodings. All these features are implemented internally, without the need for external libraries (e.g. [ICU](http://site.icu-project.org/)).
RapidJSON supports various encodings. It can also validate the encodings of JSON, and transcoding JSON among encodings. All these features are implemented internally, without the need for external libraries (e.g. [ICU](http://site.icu-project.org/)).
[TOC]

View File

@ -14,7 +14,7 @@
> (in §6) JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible. When JSON is written in UTF-16 or UTF-32, the binary content-transfer-encoding must be used.
>
> 翻译JSON 可使用 UTF-8、UTF-16 或 UTF-18 表示。当 JSON 以 UTF-8 写入,该 JSON 是 8 位兼容的。当 JSON 以 UTF-16 或 UTF-32 写入,就必须使用二进制的内容传送编码。
> 翻译JSON 可使用 UTF-8、UTF-16 或 UTF-32 表示。当 JSON 以 UTF-8 写入,该 JSON 是 8 位兼容的。当 JSON 以 UTF-16 或 UTF-32 写入,就必须使用二进制的内容传送编码。
RapidJSON 支持多种编码。它也能检查 JSON 的编码,以及在不同编码中进行转码。所有这些功能都是在内部实现,无需使用外部的程序库(如 [ICU](http://site.icu-project.org/))。

View File

@ -18,7 +18,7 @@
4. Is RapidJSON free?
Yes, it is free under MIT license. It can be used in commercial applications. Please check the details in [license.txt](https://github.com/miloyip/rapidjson/blob/master/license.txt).
Yes, it is free under MIT license. It can be used in commercial applications. Please check the details in [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt).
5. Is RapidJSON small? What are its dependencies?
@ -44,7 +44,7 @@
10. How RapidJSON is tested?
RapidJSON contains a unit test suite for automatic testing. [Travis](https://travis-ci.org/miloyip/rapidjson/)(for Linux) and [AppVeyor](https://ci.appveyor.com/project/miloyip/rapidjson/)(for Windows) will compile and run the unit test suite for all modifications. The test process also uses Valgrind (in Linux) to detect memory leaks.
RapidJSON contains a unit test suite for automatic testing. [Travis](https://travis-ci.org/Tencent/rapidjson/)(for Linux) and [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(for Windows) will compile and run the unit test suite for all modifications. The test process also uses Valgrind (in Linux) to detect memory leaks.
11. Is RapidJSON well documented?
@ -64,13 +64,13 @@
JSON are commonly used in web applications for transferring structured data. It is also used as a file format for data persistence.
2. Does RapidJSON conform to the JSON standard?
3. Does RapidJSON conform to the JSON standard?
Yes. RapidJSON is fully compliance with [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm). It can handle corner cases, such as supporting null character and surrogate pairs in JSON strings.
3. Does RapidJSON support relaxed syntax?
4. Does RapidJSON support relaxed syntax?
Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/miloyip/rapidjson/issues/36).
Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/Tencent/rapidjson/issues/36).
## DOM and SAX
@ -116,7 +116,7 @@
~~~~~~~~~~cpp
Value(kObjectType).Swap(d);
~~~~~~~~~~
or equivalent, but sightly longer to type:
or equivalent, but slightly longer to type:
~~~~~~~~~~cpp
d.Swap(Value(kObjectType).Move());
~~~~~~~~~~
@ -140,11 +140,11 @@
}
~~~~~~~~~~
The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer.
The most important requirement to take care of document and value life-cycle as well as consistent memory management using the right allocator during the value transfer.
Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root member of the value:
~~~~~~~~~~cpp
Documnet address(person.GetAllocator());
Document address(&person.GetAllocator());
...
person["person"].AddMember("address", address["address"], person.GetAllocator());
~~~~~~~~~~
@ -174,7 +174,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
3. Why do I need to provide the length of string?
Since C string is null-terminated, the length of string needs to be computed via `strlen()`, with linear runtime complexity. This incurs an unncessary overhead of many operations, if the user already knows the length of string.
Since C string is null-terminated, the length of string needs to be computed via `strlen()`, with linear runtime complexity. This incurs an unnecessary overhead of many operations, if the user already knows the length of string.
Also, RapidJSON can handle `\u0000` (null character) within a string. If a string contains null characters, `strlen()` cannot return the true length of it. In such case user must provide the length of string explicitly.
@ -204,7 +204,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
2. Can it validate the encoding?
Yes, just pass `kParseValidateEncodingFlag` to `Parse()`. If there is invalid encoding in the stream, it wil generate `kParseErrorStringInvalidEncoding` error.
Yes, just pass `kParseValidateEncodingFlag` to `Parse()`. If there is invalid encoding in the stream, it will generate `kParseErrorStringInvalidEncoding` error.
3. What is surrogate pair? Does RapidJSON support it?
@ -236,7 +236,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
4. What is BOM? How RapidJSON handle it?
[Byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) sometimes reside at the beginning of file/stream to indiciate the UTF encoding type of it.
[Byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) sometimes reside at the beginning of file/stream to indicate the UTF encoding type of it.
RapidJSON's `EncodedInputStream` can detect/consume BOM. `EncodedOutputStream` can optionally write a BOM. See [Encoded Streams](doc/stream.md) for example.
@ -248,7 +248,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
1. Is RapidJSON really fast?
Yes. It may be the fastest open source JSON library. There is a [benchmark](https://github.com/miloyip/nativejson-benchmark) for evaluating performance of C/C++ JSON libaries.
Yes. It may be the fastest open source JSON library. There is a [benchmark](https://github.com/miloyip/nativejson-benchmark) for evaluating performance of C/C++ JSON libraries.
2. Why is it fast?
@ -256,19 +256,19 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres
3. What is SIMD? How it is applied in RapidJSON?
[SIMD](http://en.wikipedia.org/wiki/SIMD) instructions can perform parallel computation in modern CPUs. RapidJSON support Intel's SSE2/SSE4.2 to accelerate whitespace skipping. This improves performance of parsing indent formatted JSON. Define `RAPIDJSON_SSE2` or `RAPIDJSON_SSE42` macro to enable this feature. However, running the executable on a machine without such instruction set support will make it crash.
[SIMD](http://en.wikipedia.org/wiki/SIMD) instructions can perform parallel computation in modern CPUs. RapidJSON support Intel's SSE2/SSE4.2 and ARM's Neon to accelerate whitespace/tabspace/carriage-return/line-feed skipping. This improves performance of parsing indent formatted JSON. Define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` macro to enable this feature. However, running the executable on a machine without such instruction set support will make it crash.
4. Does it consume a lot of memory?
The design of RapidJSON aims at reducing memory footprint.
In the SAX API, `Reader` consumes memory portional to maximum depth of JSON tree, plus maximum length of JSON string.
In the SAX API, `Reader` consumes memory proportional to maximum depth of JSON tree, plus maximum length of JSON string.
In the DOM API, each `Value` consumes exactly 16/24 bytes for 32/64-bit architecture respectively. RapidJSON also uses a special memory allocator to minimize overhead of allocations.
5. What is the purpose of being high performance?
Some applications need to process very large JSON files. Some server-side applications need to process huge amount of JSONs. Being high performance can improve both latency and throuput. In a broad sense, it will also save energy.
Some applications need to process very large JSON files. Some server-side applications need to process huge amount of JSONs. Being high performance can improve both latency and throughput. In a broad sense, it will also save energy.
## Gossip

View File

@ -18,7 +18,7 @@
4. RapidJSON 是免费的么?
是的,它在 MIT 特許條款下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/miloyip/rapidjson/blob/master/license.txt)。
是的,它在 MIT 协议下免费。它可用于商业软件。详情请参看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。
5. RapidJSON 很小么?它有何依赖?
@ -44,7 +44,7 @@
10. RapidJSON 是如何被测试的?
RapidJSON 包含一组单元测试去执行自动测试。[Travis](https://travis-ci.org/miloyip/rapidjson/)(供 Linux 平台)及 [AppVeyor](https://ci.appveyor.com/project/miloyip/rapidjson/)(供 Windows 平台)会对所有修改进行编译及执行单元测试。在 Linux 下还会使用 Valgrind 去检测内存泄漏。
RapidJSON 包含一组单元测试去执行自动测试。[Travis](https://travis-ci.org/Tencent/rapidjson/)(供 Linux 平台)及 [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(供 Windows 平台)会对所有修改进行编译及执行单元测试。在 Linux 下还会使用 Valgrind 去检测内存泄漏。
11. RapidJSON 是否有完整的文档?
@ -64,13 +64,13 @@
JSON 常用于网页应用程序,以传送结构化数据。它也可作为文件格式用于数据持久化。
2. RapidJSON 是否符合 JSON 标准?
3. RapidJSON 是否符合 JSON 标准?
是。RapidJSON 完全符合 [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) 及 [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)。它能处理一些特殊情况,例如支持 JSON 字符串中含有空字符及代理对surrogate pair
3. RapidJSON 是否支持宽松的语法?
4. RapidJSON 是否支持宽松的语法?
现时不支持。RapidJSON 只支持严格的标准格式。宽松语法现时在这 [issue](https://github.com/miloyip/rapidjson/issues/36) 中进行讨论。
目前不支持。RapidJSON 只支持严格的标准格式。宽松语法可以在这个 [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。
## DOM 与 SAX
@ -145,7 +145,7 @@
一个简单有效的方法就是修改上述 `address` 变量的定义,让其使用 `person` 的 allocator 初始化,然后将其添加到根节点。
~~~~~~~~~~cpp
Documnet address(person.GetAllocator());
Documnet address(&person.GetAllocator());
...
person["person"].AddMember("address", address["address"], person.GetAllocator());
~~~~~~~~~~
@ -163,9 +163,9 @@
## Document/Value (DOM)
1. 什么是转移语?为什么?
1. 什么是转移语?为什么?
`Value` 不用复制语意,而使用了转移语意。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
`Value` 不用复制语义,而使用了转移语义。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
由于转移快于复制,此设计决定强迫使用者注意到复制的消耗。
@ -257,7 +257,7 @@
3. 什是是 SIMD它如何用于 RapidJSON
[SIMD](http://en.wikipedia.org/wiki/SIMD) 指令可以在现代 CPU 中执行并行运算。RapidJSON 支持了 Intel 的 SSE2/SSE4.2 去加速跳过空白字符。在解析含缩进的 JSON 时,这能提升性能。只要定义名为 `RAPIDJSON_SSE2` `RAPIDJSON_SSE42` 的宏,就能启动这个功能。然而,若在不支持这些指令集的机器上执行这些可执行文件,会导致崩溃。
[SIMD](http://en.wikipedia.org/wiki/SIMD) 指令可以在现代 CPU 中执行并行运算。RapidJSON 支持使用 Intel 的 SSE2/SSE4.2 和 ARM 的 Neon 来加速对空白符、制表符、回车符和换行符的过滤处理。在解析含缩进的 JSON 时,这能提升性能。只要定义名为 `RAPIDJSON_SSE2` `RAPIDJSON_SSE42``RAPIDJSON_NEON` 的宏,就能启动这个功能。然而,若在不支持这些指令集的机器上执行这些可执行文件,会导致崩溃。
4. 它会消耗许多内存么?
@ -271,7 +271,7 @@
有些应用程序需要处理非常大的 JSON 文件。而有些后台应用程序需要处理大量的 JSON。达到高性能同时改善延时及吞吐量。更广义来说这也可以节省能源。
## 八
## 八
1. 谁是 RapidJSON 的开发者?
@ -279,11 +279,11 @@
2. 为何你要开发 RapidJSON
在 2011 年开始这项目是,它仅一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个仅有头文件并且快速的程序库。
在 2011 年开始这项目时,它只是一个兴趣项目。Milo Yip 是一个游戏程序员,他在那时候认识到 JSON 并希望在未来的项目中使用。由于 JSON 好像很简单,他希望写一个快速的仅有头文件的程序库。
3. 为什么开发中段有一段长期空档?
主要是个人因素例如加入新家庭成员。另外Milo Yip 也花了许多业时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
主要是个人因素例如加入新家庭成员。另外Milo Yip 也花了许多业时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游戏引擎架构》。
4. 为什么这个项目从 Google Code 搬到 GitHub

View File

@ -22,14 +22,16 @@
* RapidJSON should be fully RFC4627/ECMA-404 compliance.
* Support JSON Pointer (RFC6901).
* Support JSON Schema Draft v4.
* Support Swagger v2 schema.
* Support OpenAPI v3.0.x schema.
* Support Unicode surrogate.
* Support null character (`"\u0000"`)
* For example, `["Hello\u0000World"]` can be parsed and handled gracefully. There is API for getting/setting lengths of string.
* For example, `["Hello\u0000World"]` can be parsed and handled gracefully. There is API for getting/setting lengths of string.
* Support optional relaxed syntax.
* Single line (`// ...`) and multiple line (`/* ... */`) comments (`kParseCommentsFlag`).
* Trailing commas at the end of objects and arrays (`kParseTrailingCommasFlag`).
* `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (`kParseNanAndInfFlag`)
* [NPM compliant](http://github.com/miloyip/rapidjson/blob/master/doc/npm.md).
* Single line (`// ...`) and multiple line (`/* ... */`) comments (`kParseCommentsFlag`).
* Trailing commas at the end of objects and arrays (`kParseTrailingCommasFlag`).
* `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (`kParseNanAndInfFlag`)
* [NPM compliant](http://github.com/Tencent/rapidjson/blob/master/doc/npm.md).
## Unicode

View File

@ -22,14 +22,14 @@
* RapidJSON 应完全符合 RFC4627/ECMA-404 标准。
* 支持 JSON Pointer (RFC6901).
* 支持 JSON Schema Draft v4.
* 支持 Unicod 代理对surrogate pair
* 支持 Unicode 代理对surrogate pair
* 支持空字符(`"\u0000"`)。
* 例如,可以优雅地解析及处理 `["Hello\u0000World"]`。含读写字符串长度的 API。
* 支持可选的放宽语法
* 单行(`// ...`)及多行(`/* ... */` 注释 (`kParseCommentsFlag`)。
* 在对象和数组结束前含逗号 (`kParseTrailingCommasFlag`)。
* `NaN``Inf``Infinity``-Inf``-Infinity` 作为 `double` 值 (`kParseNanAndInfFlag`)
* [NPM 兼容](https://github.com/miloyip/rapidjson/blob/master/doc/npm.md).
* [NPM 兼容](https://github.com/Tencent/rapidjson/blob/master/doc/npm.md).
## Unicode

View File

@ -28,7 +28,7 @@ Both SAX and DOM APIs depends on 3 additional concepts: `Allocator`, `Encoding`
## Data Layout {#DataLayout}
`Value` is a [variant type](http://en.wikipedia.org/wiki/Variant_type). In RapidJSON's context, an instance of `Value` can contain 1 of 6 JSON value types. This is possible by using `union`. Each `Value` contains two members: `union Data data_` and a`unsigned flags_`. The `flags_` indiciates the JSON type, and also additional information.
`Value` is a [variant type](http://en.wikipedia.org/wiki/Variant_type). In RapidJSON's context, an instance of `Value` can contain 1 of 6 JSON value types. This is possible by using `union`. Each `Value` contains two members: `union Data data_` and a`unsigned flags_`. The `flags_` indicates the JSON type, and also additional information.
The following tables show the data layout of each type. The 32-bit/64-bit columns indicates the size of the field in bytes.
@ -79,7 +79,7 @@ The following tables show the data layout of each type. The 32-bit/64-bit column
| `unsigned u` | 32-bit unsigned integer |4 |4 |
| (zero padding) | 0 |4 |4 |
| (unused) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 |
| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 |
| Number (Int64) | |32-bit|64-bit|
|---------------------|-------------------------------------|:----:|:----:|
@ -101,7 +101,7 @@ The following tables show the data layout of each type. The 32-bit/64-bit column
Here are some notes:
* To reduce memory consumption for 64-bit architecture, `SizeType` is typedef as `unsigned` instead of `size_t`.
* Zero padding for 32-bit number may be placed after or before the actual type, according to the endianess. This makes possible for interpreting a 32-bit integer as a 64-bit integer, without any conversion.
* Zero padding for 32-bit number may be placed after or before the actual type, according to the endianness. This makes possible for interpreting a 32-bit integer as a 64-bit integer, without any conversion.
* An `Int` is always an `Int64`, but the converse is not always true.
## Flags {#Flags}
@ -183,17 +183,20 @@ void SkipWhitespace(InputStream& s) {
However, this requires 4 comparisons and a few branching for each character. This was found to be a hot spot.
To accelerate this process, SIMD was applied to compare 16 characters with 4 white spaces for each iteration. Currently RapidJSON only supports SSE2 and SSE4.2 instructions for this. And it is only activated for UTF-8 memory streams, including string stream or *in situ* parsing.
To accelerate this process, SIMD was applied to compare 16 characters with 4 white spaces for each iteration. Currently RapidJSON supports SSE2, SSE4.2 and ARM Neon instructions for this. And it is only activated for UTF-8 memory streams, including string stream or *in situ* parsing.
To enable this optimization, need to define `RAPIDJSON_SSE2` or `RAPIDJSON_SSE42` before including `rapidjson.h`. Some compilers can detect the setting, as in `perftest.h`:
To enable this optimization, need to define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` before including `rapidjson.h`. Some compilers can detect the setting, as in `perftest.h`:
~~~cpp
// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
// Likewise, __ARM_NEON is used to detect Neon.
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#elif defined(__ARM_NEON)
# define RAPIDJSON_NEON
#endif
~~~
@ -211,7 +214,7 @@ In [Intel® 64 and IA-32 Architectures Optimization Reference Manual
This is not feasible as RapidJSON should not enforce such requirement.
To fix this issue, currently the routine process bytes up to the next aligned address. After tha, use aligned read to perform SIMD processing. Also see [#85](https://github.com/miloyip/rapidjson/issues/85).
To fix this issue, currently the routine process bytes up to the next aligned address. After tha, use aligned read to perform SIMD processing. Also see [#85](https://github.com/Tencent/rapidjson/issues/85).
## Local Stream Copy {#LocalStreamCopy}

363
doc/internals.zh-cn.md Normal file
View File

@ -0,0 +1,363 @@
# 内部架构
本部分记录了一些设计和实现细节。
[TOC]
# 架构 {#Architecture}
## SAX 和 DOM
下面的 UML 图显示了 SAX 和 DOM 的基本关系。
![架构 UML 类图](diagram/architecture.png)
关系的核心是 `Handler` 概念。在 SAX 一边,`Reader` 从流解析 JSON 并将事件发送到 `Handler``Writer` 实现了 `Handler` 概念,用于处理相同的事件。在 DOM 一边,`Document` 实现了 `Handler` 概念,用于通过这些时间来构建 DOM。`Value` 支持了 `Value::Accept(Handler&)` 函数,它可以将 DOM 转换为事件进行发送。
在这个设计SAX 是不依赖于 DOM 的。甚至 `Reader``Writer` 之间也没有依赖。这提供了连接事件发送器和处理器的灵活性。除此之外,`Value` 也是不依赖于 SAX 的。所以,除了将 DOM 序列化为 JSON 之外,用户也可以将其序列化为 XML或者做任何其他事情。
## 工具类
SAX 和 DOM API 都依赖于3个额外的概念`Allocator``Encoding``Stream`。它们的继承层次结构如下图所示。
![工具类 UML 类图](diagram/utilityclass.png)
# 值Value {#Value}
`Value` (实际上被定义为 `GenericValue<UTF8<>>`)是 DOM API 的核心。本部分描述了它的设计。
## 数据布局 {#DataLayout}
`Value` 是[可变类型](http://en.wikipedia.org/wiki/Variant_type)。在 RapidJSON 的上下文中,一个 `Value` 的实例可以包含6种 JSON 数据类型之一。通过使用 `union` ,这是可能实现的。每一个 `Value` 包含两个成员:`union Data data_``unsigned flags_``flags_` 表明了 JSON 类型,以及附加的信息。
下表显示了所有类型的数据布局。32位/64位列表明了字段所占用的字节数。
| Null | | 32位 | 64位 |
|-------------------|----------------------------------|:----:|:----:|
| (未使用) | |4 |8 |
| (未使用) | |4 |4 |
| (未使用) | |4 |4 |
| `unsigned flags_` | `kNullType kNullFlag` |4 |4 |
| Bool | | 32位 | 64位 |
|-------------------|----------------------------------------------------|:----:|:----:|
| (未使用) | |4 |8 |
| (未使用) | |4 |4 |
| (未使用) | |4 |4 |
| `unsigned flags_` | `kBoolType` (either `kTrueFlag` or `kFalseFlag`) |4 |4 |
| String | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `Ch* str` | 指向字符串的指针(可能拥有所有权) |4 |8 |
| `SizeType length` | 字符串长度 |4 |4 |
| (未使用) | |4 |4 |
| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 |
| Object | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `Member* members` | 指向成员数组的指针(拥有所有权) |4 |8 |
| `SizeType size` | 成员数量 |4 |4 |
| `SizeType capacity` | 成员容量 |4 |4 |
| `unsigned flags_` | `kObjectType kObjectFlag` |4 |4 |
| Array | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `Value* values` | 指向值数组的指针(拥有所有权) |4 |8 |
| `SizeType size` | 值数量 |4 |4 |
| `SizeType capacity` | 值容量 |4 |4 |
| `unsigned flags_` | `kArrayType kArrayFlag` |4 |4 |
| Number (Int) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `int i` | 32位有符号整数 |4 |4 |
| (零填充) | 0 |4 |4 |
| (未使用) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kIntFlag kInt64Flag ...` |4 |4 |
| Number (UInt) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `unsigned u` | 32位无符号整数 |4 |4 |
| (零填充) | 0 |4 |4 |
| (未使用) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 |
| Number (Int64) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `int64_t i64` | 64位有符号整数 |8 |8 |
| (未使用) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 |
| Number (Uint64) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `uint64_t i64` | 64位无符号整数 |8 |8 |
| (未使用) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 |
| Number (Double) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `uint64_t i64` | 双精度浮点数 |8 |8 |
| (未使用) | |4 |8 |
| `unsigned flags_` |`kNumberType kNumberFlag kDoubleFlag`|4 |4 |
这里有一些需要注意的地方:
* 为了减少在64位架构上的内存消耗`SizeType` 被定义为 `unsigned` 而不是 `size_t`
* 32位整数的零填充可能被放在实际类型的前面或后面这依赖于字节序。这使得它可以将32位整数不经过任何转换就可以解释为64位整数。
* `Int` 永远是 `Int64`,反之不然。
## 标志 {#Flags}
32位的 `flags_` 包含了 JSON 类型和其他信息。如前文中的表所述,每一种 JSON 类型包含了冗余的 `kXXXType``kXXXFlag`。这个设计是为了优化测试位标志(`IsNumber()`)和获取每一种类型的序列号(`GetType()`)。
字符串有两个可选的标志。`kCopyFlag` 表明这个字符串拥有字符串拷贝的所有权。而 `kInlineStrFlag` 意味着使用了[短字符串优化](#ShortString)。
数字更加复杂一些。对于普通的整数值,它可以包含 `kIntFlag``kUintFlag``kInt64Flag` 和/或 `kUint64Flag`这由整数的范围决定。带有小数或者超过64位所能表达的范围的整数的数字会被存储为带有 `kDoubleFlag``double`
## 短字符串优化 {#ShortString}
[Kosta](https://github.com/Kosta-Github) 提供了很棒的短字符串优化。这个优化的xxx如下所述。除去 `flags_` `Value` 有12或16字节对于32位或64位来存储实际的数据。这为在其内部直接存储短字符串而不是存储字符串的指针创造了可能。对于1字节的字符类型例如 `char`),它可以在 `Value` 类型内部存储至多11或15个字符的字符串。
|ShortString (Ch=char)| | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:|
| `Ch str[MaxChars]` | 字符串缓冲区 |11 |15 |
| `Ch invLength` | MaxChars - Length |1 |1 |
| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 |
这里使用了一项特殊的技术。它存储了 (MaxChars - length) 而不直接存储字符串的长度。这使得存储11个字符并且带有后缀 `\0` 成为可能。
这个优化可以减少字符串拷贝内存占用。它也改善了缓存一致性,并进一步提高了运行时性能。
# 分配器Allocator {#InternalAllocator}
`Allocator` 是 RapidJSON 中的概念:
~~~cpp
concept Allocator {
static const bool kNeedFree; //!< 表明这个分配器是否需要调用 Free()
// 申请内存块。
// \param size 内存块的大小,以字节记。
// \returns 指向内存块的指针。
void* Malloc(size_t size);
// 调整内存块的大小。
// \param originalPtr 当前内存块的指针。空指针是被允许的。
// \param originalSize 当前大小,以字节记。(设计问题:因为有些分配器可能不会记录它,显示的传递它可以节约内存。)
// \param newSize 新大小,以字节记。
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
// 释放内存块。
// \param ptr 指向内存块的指针。空指针是被允许的。
static void Free(void *ptr);
};
~~~
需要注意的是 `Malloc()``Realloc()` 是成员函数而 `Free()` 是静态成员函数。
## MemoryPoolAllocator {#MemoryPoolAllocator}
`MemoryPoolAllocator` 是 DOM 的默认内存分配器。它只申请内存而不释放内存。这对于构建 DOM 树非常合适。
在它的内部,它从基础的内存分配器申请内存块(默认为 `CrtAllocator`)并将这些内存块存储为单向链表。当用户请求申请内存,它会遵循下列步骤来申请内存:
1. 如果可用,使用用户提供的缓冲区。(见 [User Buffer section in DOM](doc/dom.md)
2. 如果用户提供的缓冲区已满,使用当前内存块。
3. 如果当前内存块已满,申请新的内存块。
# 解析优化 {#ParsingOptimization}
## 使用 SIMD 跳过空格 {#SkipwhitespaceWithSIMD}
当从流中解析 JSON 时解析器需要跳过4种空格字符
1. 空格 (`U+0020`)
2. 制表符 (`U+000B`)
3. 换行 (`U+000A`)
4. 回车 (`U+000D`)
这是一份简单的实现:
~~~cpp
void SkipWhitespace(InputStream& s) {
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
s.Take();
}
~~~
但是这需要对每个字符进行4次比较以及一些分支。这被发现是一个热点。
为了加速这一处理RapidJSON 使用 SIMD 来在一次迭代中比较16个字符和4个空格。目前 RapidJSON 支持 SSE2 SSE4.2 和 ARM Neon 指令。同时它也只会对 UTF-8 内存流启用,包括字符串流或 *原位* 解析。
你可以通过在包含 `rapidjson.h` 之前定义 `RAPIDJSON_SSE2` `RAPIDJSON_SSE42``RAPIDJSON_NEON` 来启用这个优化。一些编译器可以检测这个设置,如 `perftest.h`
~~~cpp
// __SSE2____SSE4_2__ 可被 gcc、clang 和 Intel 编译器识别:
// 如果支持的话,我们在 gmake 中使用了 -march=native 来启用 -msse2 和 -msse4.2
// 同样的, __ARM_NEON 被用于识别Neon
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#elif defined(__ARM_NEON)
# define RAPIDJSON_NEON
#endif
~~~
需要注意的是,这是编译期的设置。在不支持这些指令的机器上运行可执行文件会使它崩溃。
### 页面对齐问题
在 RapidJSON 的早期版本中,被报告了[一个问题](https://code.google.com/archive/p/rapidjson/issues/104)`SkipWhitespace_SIMD()` 会罕见地导致崩溃(约五十万分之一的几率)。在调查之后,怀疑是 `_mm_loadu_si128()` 访问了 `'\0'` 之后的内存,并越过被保护的页面边界。
在 [Intel® 64 and IA-32 Architectures Optimization Reference Manual
](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) 中,章节 10.2.1
> 为了支持需要费对齐的128位 SIMD 内存访问的算法调用者的内存缓冲区申请应当考虑添加一些填充空间这样被调用的函数可以安全地将地址指针用于未对齐的128位 SIMD 内存操作。
> 在结合非对齐的 SIMD 内存操作中,最小的对齐大小应该等于 SIMD 寄存器的大小。
对于 RapidJSON 来说,这显然是不可行的,因为 RapidJSON 不应当强迫用户进行内存对齐。
为了修复这个问题,当前的代码会先按字节处理直到下一个对齐的地址。在这之后,使用对齐读取来进行 SIMD 处理。见 [#85](https://github.com/Tencent/rapidjson/issues/85)。
## 局部流拷贝 {#LocalStreamCopy}
在优化的过程中,我们发现一些编译器不能将访问流的一些成员数据放入局部变量或者寄存器中。测试结果显示,对于一些流类型,创建流的拷贝并将其用于内层循环中可以改善性能。例如,实际(非 SIMD`SkipWhitespace()` 被实现为:
~~~cpp
template<typename InputStream>
void SkipWhitespace(InputStream& is) {
internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s);
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
s.Take();
}
~~~
基于流的特征,`StreamLocalCopy` 会创建(或不创建)流对象的拷贝,在局部使用它并将流的状态拷贝回原来的流。
## 解析为双精度浮点数 {#ParsingDouble}
将字符串解析为 `double` 并不简单。标准库函数 `strtod()` 可以胜任这项工作,但它比较缓慢。默认情况下,解析器使用默认的精度设置。这最多有 3[ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) 的误差,并实现在 `internal::StrtodNormalPrecision()` 中。
当使用 `kParseFullPrecisionFlag` 时,编译器会改为调用 `internal::StrtodFullPrecision()` ,这个函数会自动调用三个版本的转换。
1. [Fast-Path](http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/)。
2. [double-conversion](https://github.com/floitsch/double-conversion) 中的自定义 DIY-FP 实现。
3. Clinger, William D. How to read floating point numbers accurately. Vol. 25. No. 6. ACM, 1990 中的大整数算法。
如果第一个转换方法失败,则尝试使用第二种方法,以此类推。
# 生成优化 {#GenerationOptimization}
## 整数到字符串的转换 {#itoa}
整数到字符串转换的朴素算法需要对每一个十进制位进行一次除法。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。
虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` 差距不大。而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut`
## 双精度浮点数到字符串的转换 {#dtoa}
原来 RapidJSON 使用 `snprintf(..., ..., "%g")` 来进行双精度浮点数到字符串的转换。这是不准确的因为默认的精度是6。随后我们发现它很缓慢而且有其它的替代品。
Google 的 V8 [double-conversion](https://github.com/floitsch/double-conversion
) 实现了更新的、快速的被称为 Grisu3 的算法Loitsch, Florian. "Printing floating-point numbers quickly and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.)。
然而,这个实现不是仅头文件的,所以我们实现了一个仅头文件的 Grisu2 版本。这个算法保证了结果永远精确。而且在大多数情况下,它会生成最短的(可选)字符串表示。
这个仅头文件的转换函数在 [dtoa-benchmark](https://github.com/miloyip/dtoa-benchmark) 中进行评估。
# 解析器 {#Parser}
## 迭代解析 {#IterativeParser}
迭代解析器是一个以非递归方式实现的递归下降的 LL(1) 解析器。
### 语法 {#IterativeParserGrammar}
解析器使用的语法是基于严格 JSON 语法的:
~~~~~~~~~~
S -> array | object
array -> [ values ]
object -> { members }
values -> non-empty-values | ε
non-empty-values -> value addition-values
addition-values -> ε | , non-empty-values
members -> non-empty-members | ε
non-empty-members -> member addition-members
addition-members -> ε | , non-empty-members
member -> STRING : value
value -> STRING | NUMBER | NULL | BOOLEAN | object | array
~~~~~~~~~~
注意到左因子被加入了非终结符的 `values``members` 来保证语法是 LL(1) 的。
### 解析表 {#IterativeParserParsingTable}
基于这份语法,我们可以构造 FIRST 和 FOLLOW 集合。
非终结符的 FIRST 集合如下所示:
| NON-TERMINAL | FIRST |
|:-----------------:|:--------------------------------:|
| array | [ |
| object | { |
| values | ε STRING NUMBER NULL BOOLEAN { [ |
| addition-values | ε COMMA |
| members | ε STRING |
| addition-members | ε COMMA |
| member | STRING |
| value | STRING NUMBER NULL BOOLEAN { [ |
| S | [ { |
| non-empty-members | STRING |
| non-empty-values | STRING NUMBER NULL BOOLEAN { [ |
FOLLOW 集合如下所示:
| NON-TERMINAL | FOLLOW |
|:-----------------:|:-------:|
| S | $ |
| array | , $ } ] |
| object | , $ } ] |
| values | ] |
| non-empty-values | ] |
| addition-values | ] |
| members | } |
| non-empty-members | } |
| addition-members | } |
| member | , } |
| value | , } ] |
最终可以从 FIRST 和 FOLLOW 集合生成解析表:
| NON-TERMINAL | [ | { | , | : | ] | } | STRING | NUMBER | NULL | BOOLEAN |
|:-----------------:|:---------------------:|:---------------------:|:-------------------:|:-:|:-:|:-:|:-----------------------:|:---------------------:|:---------------------:|:---------------------:|
| S | array | object | | | | | | | | |
| array | [ values ] | | | | | | | | | |
| object | | { members } | | | | | | | | |
| values | non-empty-values | non-empty-values | | | ε | | non-empty-values | non-empty-values | non-empty-values | non-empty-values |
| non-empty-values | value addition-values | value addition-values | | | | | value addition-values | value addition-values | value addition-values | value addition-values |
| addition-values | | | , non-empty-values | | ε | | | | | |
| members | | | | | | ε | non-empty-members | | | |
| non-empty-members | | | | | | | member addition-members | | | |
| addition-members | | | , non-empty-members | | | ε | | | | |
| member | | | | | | | STRING : value | | | |
| value | array | object | | | | | STRING | NUMBER | NULL | BOOLEAN |
对于上面的语法分析,这里有一个很棒的[工具](http://hackingoff.com/compilers/predict-first-follow-set)。
### 实现 {#IterativeParserImplementation}
基于这份解析表,一个直接的(常规的)将规则反向入栈的实现可以正常工作。
在 RapidJSON 中,对直接的实现进行了一些修改:
首先,在 RapidJSON 中,这份解析表被编码为状态机。
规则由头部和主体组成。
状态转换由规则构造。
除此之外,额外的状态被添加到与 `array``object` 有关的规则。
通过这种方式,生成数组值或对象成员可以只用一次状态转移便可完成,
而不需要在直接的实现中的多次出栈/入栈操作。
这也使得估计栈的大小更加容易。
状态图如如下所示:
![状态图](diagram/iterative-parser-states-diagram.png)
第二,迭代解析器也在内部栈保存了数组的值个数和对象成员的数量,这也与传统的实现不同。

View File

@ -18,7 +18,7 @@ $extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="topbanner"><a href="https://github.com/miloyip/rapidjson" title="RapidJSON GitHub"><i class="githublogo"></i></a></div>
<div id="topbanner"><a href="https://github.com/Tencent/rapidjson" title="RapidJSON GitHub"><i class="githublogo"></i></a></div>
$searchbox
<!--END TITLEAREA-->
<!-- end header part -->

View File

@ -7,7 +7,7 @@
...
"dependencies": {
...
"rapidjson": "git@github.com:miloyip/rapidjson.git"
"rapidjson": "git@github.com:Tencent/rapidjson.git"
},
...
"gypfile": true

View File

@ -1,6 +1,6 @@
# Performance
There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libaries.
There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libraries.
[1]: https://github.com/miloyip/nativejson-benchmark
@ -15,12 +15,12 @@ Additionally, you may refer to the following third-party benchmarks.
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)

View File

@ -15,12 +15,12 @@ RapidJSON 0.1 版本的性能测试文章位于 [这里](https://code.google.com
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
* [rapidjson](https://github.com/miloyip/rapidjson/)
* [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)

View File

@ -211,7 +211,7 @@ p.Stringify(sb);
std::cout << sb.GetString() << std::endl;
~~~
It can also stringify to URI fragment reprsentation by `StringifyUriFragment()`.
It can also stringify to URI fragment representation by `StringifyUriFragment()`.
# User-Supplied Tokens {#UserSuppliedTokens}

View File

@ -181,7 +181,7 @@ private:
`Pointer` 在其建构函数里会解译源字符串。若有解析错误,`Pointer::IsValid()` 返回 `false`。你可使用 `Pointer::GetParseErrorCode()``GetParseErrorOffset()` 去获取错信息。
要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会成断言失败。
要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会成断言失败。
# URI 片段表示方式 {#URIFragment}

View File

@ -8,7 +8,7 @@ In RapidJSON, `Reader` (typedef of `GenericReader<...>`) is the SAX-style parser
# Reader {#Reader}
`Reader` parses a JSON from a stream. While it reads characters from the stream, it analyze the characters according to the syntax of JSON, and publish events to a handler.
`Reader` parses a JSON from a stream. While it reads characters from the stream, it analyzes the characters according to the syntax of JSON, and publishes events to a handler.
For example, here is a JSON.
@ -24,7 +24,7 @@ For example, here is a JSON.
}
~~~~~~~~~~
While a `Reader` parses this JSON, it publishes the following events to the handler sequentially:
When a `Reader` parses this JSON, it publishes the following events to the handler sequentially:
~~~~~~~~~~
StartObject()
@ -37,7 +37,7 @@ Bool(false)
Key("n", 1, true)
Null()
Key("i")
UInt(123)
Uint(123)
Key("pi")
Double(3.1416)
Key("a")
@ -50,7 +50,7 @@ EndArray(4)
EndObject(7)
~~~~~~~~~~
These events can be easily matched with the JSON, except some event parameters need further explanation. Let's see the `simplereader` example which produces exactly the same output as above:
These events can be easily matched with the JSON, but some event parameters need further explanation. Let's see the `simplereader` example which produces exactly the same output as above:
~~~~~~~~~~cpp
#include "rapidjson/reader.h"
@ -91,11 +91,11 @@ void main() {
}
~~~~~~~~~~
Note that, RapidJSON uses template to statically bind the `Reader` type and the handler type, instead of using class with virtual functions. This paradigm can improve the performance by inlining functions.
Note that RapidJSON uses templates to statically bind the `Reader` type and the handler type, instead of using classes with virtual functions. This paradigm can improve performance by inlining functions.
## Handler {#Handler}
As the previous example showed, user needs to implement a handler, which consumes the events (function calls) from `Reader`. The handler must contain the following member functions.
As shown in the previous example, the user needs to implement a handler which consumes the events (via function calls) from the `Reader`. The handler must contain the following member functions.
~~~~~~~~~~cpp
class Handler {
@ -122,15 +122,15 @@ class Handler {
When the `Reader` encounters a JSON number, it chooses a suitable C++ type mapping. And then it calls *one* function out of `Int(int)`, `Uint(unsigned)`, `Int64(int64_t)`, `Uint64(uint64_t)` and `Double(double)`. If `kParseNumbersAsStrings` is enabled, `Reader` will always calls `RawNumber()` instead.
`String(const char* str, SizeType length, bool copy)` is called when the `Reader` encounters a string. The first parameter is pointer to the string. The second parameter is the length of the string (excluding the null terminator). Note that RapidJSON supports null character `'\0'` inside a string. If such situation happens, `strlen(str) < length`. The last `copy` indicates whether the handler needs to make a copy of the string. For normal parsing, `copy = true`. Only when *insitu* parsing is used, `copy = false`. And beware that, the character type depends on the target encoding, which will be explained later.
`String(const char* str, SizeType length, bool copy)` is called when the `Reader` encounters a string. The first parameter is pointer to the string. The second parameter is the length of the string (excluding the null terminator). Note that RapidJSON supports null character `\0` inside a string. If such situation happens, `strlen(str) < length`. The last `copy` indicates whether the handler needs to make a copy of the string. For normal parsing, `copy = true`. Only when *insitu* parsing is used, `copy = false`. And be aware that the character type depends on the target encoding, which will be explained later.
When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeats until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler, user may not need this parameter.
When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeat until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler; users who do not need this parameter may ignore it.
Array is similar to object but simpler. At the beginning of an array, the `Reader` calls `BeginArary()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
Arrays are similar to objects, but simpler. At the beginning of an array, the `Reader` calls `BeginArray()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
Every handler functions returns a `bool`. Normally it should returns `true`. If the handler encounters an error, it can return `false` to notify event publisher to stop further processing.
Every handler function returns a `bool`. Normally it should return `true`. If the handler encounters an error, it can return `false` to notify the event publisher to stop further processing.
For example, when we parse a JSON with `Reader` and the handler detected that the JSON does not conform to the required schema, then the handler can return `false` and let the `Reader` stop further parsing. And the `Reader` will be in error state with error code `kParseErrorTermination`.
For example, when we parse a JSON with `Reader` and the handler detects that the JSON does not conform to the required schema, the handler can return `false` and let the `Reader` stop further parsing. This will place the `Reader` in an error state, with error code `kParseErrorTermination`.
## GenericReader {#GenericReader}
@ -149,19 +149,19 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
} // namespace rapidjson
~~~~~~~~~~
The `Reader` uses UTF-8 as both source and target encoding. The source encoding means the encoding in the JSON stream. The target encoding means the encoding of the `str` parameter in `String()` calls. For example, to parse a UTF-8 stream and outputs UTF-16 string events, you can define a reader by:
The `Reader` uses UTF-8 as both source and target encoding. The source encoding means the encoding in the JSON stream. The target encoding means the encoding of the `str` parameter in `String()` calls. For example, to parse a UTF-8 stream and output UTF-16 string events, you can define a reader by:
~~~~~~~~~~cpp
GenericReader<UTF8<>, UTF16<> > reader;
~~~~~~~~~~
Note that, the default character type of `UTF16` is `wchar_t`. So this `reader`needs to call `String(const wchar_t*, SizeType, bool)` of the handler.
Note that, the default character type of `UTF16` is `wchar_t`. So this `reader` needs to call `String(const wchar_t*, SizeType, bool)` of the handler.
The third template parameter `Allocator` is the allocator type for internal data structure (actually a stack).
## Parsing {#SaxParsing}
The one and only one function of `Reader` is to parse JSON.
The main function of `Reader` is used to parse JSON.
~~~~~~~~~~cpp
template <unsigned parseFlags, typename InputStream, typename Handler>
@ -172,7 +172,30 @@ template <typename InputStream, typename Handler>
bool Parse(InputStream& is, Handler& handler);
~~~~~~~~~~
If an error occurs during parsing, it will return `false`. User can also calls `bool HasParseEror()`, `ParseErrorCode GetParseErrorCode()` and `size_t GetErrorOffset()` to obtain the error states. Actually `Document` uses these `Reader` functions to obtain parse errors. Please refer to [DOM](doc/dom.md) for details about parse error.
If an error occurs during parsing, it will return `false`. User can also call `bool HasParseError()`, `ParseErrorCode GetParseErrorCode()` and `size_t GetErrorOffset()` to obtain the error states. In fact, `Document` uses these `Reader` functions to obtain parse errors. Please refer to [DOM](doc/dom.md) for details about parse errors.
## Token-by-Token Parsing {#TokenByTokenParsing}
Some users may wish to parse a JSON input stream a single token at a time, instead of immediately parsing an entire document without stopping. To parse JSON this way, instead of calling `Parse`, you can use the `IterativeParse` set of functions:
~~~~~~~~~~cpp
void IterativeParseInit();
template <unsigned parseFlags, typename InputStream, typename Handler>
bool IterativeParseNext(InputStream& is, Handler& handler);
bool IterativeParseComplete();
~~~~~~~~~~
Here is an example of iteratively parsing JSON, token by token:
~~~~~~~~~~cpp
reader.IterativeParseInit();
while (!reader.IterativeParseComplete()) {
reader.IterativeParseNext<kParseDefaultFlags>(is, handler);
// Your handler has been called once.
}
~~~~~~~~~~
# Writer {#Writer}

View File

@ -37,7 +37,7 @@ Bool(false)
Key("n", 1, true)
Null()
Key("i")
UInt(123)
Uint(123)
Key("pi")
Double(3.1416)
Key("a")
@ -91,7 +91,7 @@ void main() {
}
~~~~~~~~~~
注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。
注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。
## 处理器 {#Handler}
@ -122,7 +122,7 @@ class Handler {
`Reader` 遇到 JSON number它会选择一个合适的 C++ 类型映射,然后调用 `Int(int)``Uint(unsigned)``Int64(int64_t)``Uint64(uint64_t)``Double(double)`* 其中之一个 *。 若开启了 `kParseNumbersAsStrings` 选项,`Reader` 便会改为调用 `RawNumber()`
`Reader` 遇到 JSON string它会调用 `String(const char* str, SizeType length, bool copy)`。第一个参数是字符串的指针。第二个参数是字符串的长度(不包含空终止符号)。注意 RapidJSON 支持字串中含有空字符 `'\0'`。若出现这种情况,便会有 `strlen(str) < length`。最后的 `copy` 参数表示处理器是否需要复制该字符串。在正常解析时,`copy = true`。仅当使用原位解析时,`copy = false`。此外,还要注意字符的类型与目标编码相关,我们稍后会再谈这一点。
`Reader` 遇到 JSON string它会调用 `String(const char* str, SizeType length, bool copy)`。第一个参数是字符串的指针。第二个参数是字符串的长度(不包含空终止符号)。注意 RapidJSON 支持字串中含有空字符 `\0`。若出现这种情况,便会有 `strlen(str) < length`。最后的 `copy` 参数表示处理器是否需要复制该字符串。在正常解析时,`copy = true`。仅当使用原位解析时,`copy = false`。此外,还要注意字符的类型与目标编码相关,我们稍后会再谈这一点。
`Reader` 遇到 JSON object 的开始之时,它会调用 `StartObject()`。JSON 的 object 是一个键值对(成员)的集合。若 object 包含成员,它会先为成员的名字调用 `Key()`,然后再按值的类型调用函数。它不断调用这些键值对,直至最终调用 `EndObject(SizeType memberCount)`。注意 `memberCount` 参数对处理器来说只是协助性质,使用者可能不需要此参数。

View File

@ -8,7 +8,7 @@ RapidJSON implemented a JSON Schema validator for [JSON Schema Draft v4](http://
[TOC]
## Basic Usage
# Basic Usage {#Basic}
First of all, you need to parse a JSON Schema into `Document`, and then compile the `Document` into a `SchemaDocument`.
@ -20,15 +20,23 @@ Secondly, construct a `SchemaValidator` with the `SchemaDocument`. It is similar
// ...
Document sd;
if (!sd.Parse(schemaJson).HasParseError()) {
if (sd.Parse(schemaJson).HasParseError()) {
// the schema is not a valid JSON.
// ...
}
SchemaDocument schema(sd); // Compile a Document to SchemaDocument
if (!schema.GetError().ObjectEmpty()) {
// there was a problem compiling the schema
StringBuffer sb;
Writer<StringBuffer> w(sb);
schema.GetError().Accept(w);
printf("Invalid schema: %s\n", sb.GetString());
}
// sd is no longer needed here.
Document d;
if (!d.Parse(inputJson).HasParseError()) {
if (d.Parse(inputJson).HasParseError()) {
// the input is not a valid JSON.
// ...
}
@ -49,14 +57,14 @@ if (!d.Accept(validator)) {
Some notes:
* One `SchemaDocment` can be referenced by multiple `SchemaValidator`s. It will not be modified by `SchemaValidator`s.
* One `SchemaDocument` can be referenced by multiple `SchemaValidator`s. It will not be modified by `SchemaValidator`s.
* A `SchemaValidator` may be reused to validate multiple documents. To run it for other documents, call `validator.Reset()` first.
## Validation during parsing/serialization
# Validation during parsing/serialization {#Fused}
Unlike most JSON Schema validator implementations, RapidJSON provides a SAX-based schema validator. Therefore, you can parse a JSON from a stream while validating it on the fly. If the validator encounters a JSON value that invalidates the supplied schema, the parsing will be terminated immediately. This design is especially useful for parsing large JSON files.
### DOM parsing
## DOM parsing {#DOM}
For using DOM in parsing, `Document` needs some preparation and finalizing tasks, in addition to receiving SAX events, thus it needs some work to route the reader, validator and the document. `SchemaValidatingReader` is a helper class that doing such work.
@ -97,7 +105,7 @@ if (!reader.GetParseResult()) {
}
~~~
### SAX parsing
## SAX parsing {#SAX}
For using SAX in parsing, it is much simpler. If it only need to validate the JSON without further processing, it is simply:
@ -126,7 +134,7 @@ if (!reader.Parse(ss, validator)) {
}
~~~
### Serialization
## Serialization {#Serialization}
It is also possible to do validation during serializing. This can ensure the result JSON is valid according to the JSON schema.
@ -144,7 +152,7 @@ if (!d.Accept(validator)) {
Of course, if your application only needs SAX-style serialization, it can simply send SAX events to `SchemaValidator` instead of `Writer`.
## Remote Schema
# Remote Schema {#Remote}
JSON Schema supports [`$ref` keyword](http://spacetelescope.github.io/understanding-json-schema/structuring.html), which is a [JSON pointer](doc/pointer.md) referencing to a local or remote schema. Local pointer is prefixed with `#`, while remote pointer is an relative or absolute URI. For example:
@ -157,7 +165,7 @@ As `SchemaDocument` does not know how to resolve such URI, it needs a user-provi
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@ -168,7 +176,7 @@ MyRemoteSchemaDocumentProvider provider;
SchemaDocument schema(sd, &provider);
~~~
## Conformance
# Conformance {#Conformance}
RapidJSON passed 262 out of 263 tests in [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4).
@ -176,7 +184,7 @@ The failed test is "changed scope ref invalid" of "change resolution scope" in `
Besides, the `format` schema keyword for string values is ignored, since it is not required by the specification.
### Regular Expression
## Regular Expression {#Regex}
The schema keyword `pattern` and `patternProperties` uses regular expression to match the required pattern.
@ -185,7 +193,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|Syntax|Description|
|------|-----------|
|`ab` | Concatenation |
|`a|b` | Alternation |
|<code>a&#124;b</code> | Alternation |
|`a?` | Zero or one |
|`a*` | Zero or more |
|`a+` | One or more |
@ -202,7 +210,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|`[^abc]` | Negated character classes |
|`[^a-c]` | Negated character class range |
|`[\b]` | Backspace (U+0008) |
|`\|`, `\\`, ... | Escape characters |
|<code>\\&#124;</code>, `\\`, ... | Escape characters |
|`\f` | Form feed (U+000C) |
|`\n` | Line feed (U+000A) |
|`\r` | Carriage return (U+000D) |
@ -211,7 +219,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
For C++11 compiler, it is also possible to use the `std::regex` by defining `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0` and `RAPIDJSON_SCHEMA_USE_STDREGEX=1`. If your schemas do not need `pattern` and `patternProperties`, you can set both macros to zero to disable this feature, which will reduce some code size.
## Performance
# Performance {#Performance}
Most C++ JSON libraries do not yet support JSON Schema. So we tried to evaluate the performance of RapidJSON's JSON Schema validator according to [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), which tests 11 JavaScript libraries running on Node.js.
@ -235,3 +243,271 @@ On a Mac Book Pro (2.8 GHz Intel Core i7), the following results are collected.
|[`jayschema`](https://github.com/natesilva/jayschema)|0.1%|21 (± 1.14%)|
That is, RapidJSON is about 1.5x faster than the fastest JavaScript library (ajv). And 1400x faster than the slowest one.
# Schema violation reporting {#Reporting}
(Unreleased as of 2017-09-20)
When validating an instance against a JSON Schema,
it is often desirable to report not only whether the instance is valid,
but also the ways in which it violates the schema.
The `SchemaValidator` class
collects errors encountered during validation
into a JSON `Value`.
This error object can then be accessed as `validator.GetError()`.
The structure of the error object is subject to change
in future versions of RapidJSON,
as there is no standard schema for violations.
The details below this point are provisional only.
## General provisions {#ReportingGeneral}
Validation of an instance value against a schema
produces an error value.
The error value is always an object.
An empty object `{}` indicates the instance is valid.
* The name of each member
corresponds to the JSON Schema keyword that is violated.
* The value is either an object describing a single violation,
or an array of such objects.
Each violation object contains two string-valued members
named `instanceRef` and `schemaRef`.
`instanceRef` contains the URI fragment serialization
of a JSON Pointer to the instance subobject
in which the violation was detected.
`schemaRef` contains the URI of the schema
and the fragment serialization of a JSON Pointer
to the subschema that was violated.
Individual violation objects can contain other keyword-specific members.
These are detailed further.
For example, validating this instance:
~~~json
{"numbers": [1, 2, "3", 4, 5]}
~~~
against this schema:
~~~json
{
"type": "object",
"properties": {
"numbers": {"$ref": "numbers.schema.json"}
}
}
~~~
where `numbers.schema.json` refers
(via a suitable `IRemoteSchemaDocumentProvider`)
to this schema:
~~~json
{
"type": "array",
"items": {"type": "number"}
}
~~~
produces the following error object:
~~~json
{
"type": {
"instanceRef": "#/numbers/2",
"schemaRef": "numbers.schema.json#/items",
"expected": ["number"],
"actual": "string"
}
}
~~~
## Validation keywords for numbers {#Numbers}
### multipleOf {#multipleof}
* `expected`: required number strictly greater than 0.
The value of the `multipleOf` keyword specified in the schema.
* `actual`: required number.
The instance value.
### maximum {#maximum}
* `expected`: required number.
The value of the `maximum` keyword specified in the schema.
* `exclusiveMaximum`: optional boolean.
This will be true if the schema specified `"exclusiveMaximum": true`,
and will be omitted otherwise.
* `actual`: required number.
The instance value.
### minimum {#minimum}
* `expected`: required number.
The value of the `minimum` keyword specified in the schema.
* `exclusiveMinimum`: optional boolean.
This will be true if the schema specified `"exclusiveMinimum": true`,
and will be omitted otherwise.
* `actual`: required number.
The instance value.
## Validation keywords for strings {#Strings}
### maxLength {#maxLength}
* `expected`: required number greater than or equal to 0.
The value of the `maxLength` keyword specified in the schema.
* `actual`: required string.
The instance value.
### minLength {#minLength}
* `expected`: required number greater than or equal to 0.
The value of the `minLength` keyword specified in the schema.
* `actual`: required string.
The instance value.
### pattern {#pattern}
* `actual`: required string.
The instance value.
(The expected pattern is not reported
because the internal representation in `SchemaDocument`
does not store the pattern in original string form.)
## Validation keywords for arrays {#Arrays}
### additionalItems {#additionalItems}
This keyword is reported
when the value of `items` schema keyword is an array,
the value of `additionalItems` is `false`,
and the instance is an array
with more items than specified in the `items` array.
* `disallowed`: required integer greater than or equal to 0.
The index of the first item that has no corresponding schema.
### maxItems and minItems {#maxItems-minItems}
* `expected`: required integer greater than or equal to 0.
The value of `maxItems` (respectively, `minItems`)
specified in the schema.
* `actual`: required integer greater than or equal to 0.
Number of items in the instance array.
### uniqueItems {#uniqueItems}
* `duplicates`: required array
whose items are integers greater than or equal to 0.
Indices of items of the instance that are equal.
(RapidJSON only reports the first two equal items,
for performance reasons.)
## Validation keywords for objects
### maxProperties and minProperties {#maxProperties-minProperties}
* `expected`: required integer greater than or equal to 0.
The value of `maxProperties` (respectively, `minProperties`)
specified in the schema.
* `actual`: required integer greater than or equal to 0.
Number of properties in the instance object.
### required {#required}
* `missing`: required array of one or more unique strings.
The names of properties
that are listed in the value of the `required` schema keyword
but not present in the instance object.
### additionalProperties {#additionalProperties}
This keyword is reported
when the schema specifies `additionalProperties: false`
and the name of a property of the instance is
neither listed in the `properties` keyword
nor matches any regular expression in the `patternProperties` keyword.
* `disallowed`: required string.
Name of the offending property of the instance.
(For performance reasons,
RapidJSON only reports the first such property encountered.)
### dependencies {#dependencies}
* `errors`: required object with one or more properties.
Names and values of its properties are described below.
Recall that JSON Schema Draft 04 supports
*schema dependencies*,
where presence of a named *controlling* property
requires the instance object to be valid against a subschema,
and *property dependencies*,
where presence of a controlling property
requires other *dependent* properties to be also present.
For a violated schema dependency,
`errors` will contain a property
with the name of the controlling property
and its value will be the error object
produced by validating the instance object
against the dependent schema.
For a violated property dependency,
`errors` will contain a property
with the name of the controlling property
and its value will be an array of one or more unique strings
listing the missing dependent properties.
## Validation keywords for any instance type {#AnyTypes}
### enum {#enum}
This keyword has no additional properties
beyond `instanceRef` and `schemaRef`.
* The allowed values are not listed
because `SchemaDocument` does not store them in original form.
* The violating value is not reported
because it might be unwieldy.
If you need to report these details to your users,
you can access the necessary information
by following `instanceRef` and `schemaRef`.
### type {#type}
* `expected`: required array of one or more unique strings,
each of which is one of the seven primitive types
defined by the JSON Schema Draft 04 Core specification.
Lists the types allowed by the `type` schema keyword.
* `actual`: required string, also one of seven primitive types.
The primitive type of the instance.
### allOf, anyOf, and oneOf {#allOf-anyOf-oneOf}
* `errors`: required array of at least one object.
There will be as many items as there are subschemas
in the `allOf`, `anyOf` or `oneOf` schema keyword, respectively.
Each item will be the error value
produced by validating the instance
against the corresponding subschema.
For `allOf`, at least one error value will be non-empty.
For `anyOf`, all error values will be non-empty.
For `oneOf`, either all error values will be non-empty,
or more than one will be empty.
### not {#not}
This keyword has no additional properties
apart from `instanceRef` and `schemaRef`.

View File

@ -8,7 +8,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
[TOC]
## 基本用法
# 基本用法 {#BasicUsage}
首先,你要把 JSON Schema 解析成 `Document`,再把它编译成一个 `SchemaDocument`
@ -20,7 +20,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
// ...
Document sd;
if (!sd.Parse(schemaJson).HasParseError()) {
if (sd.Parse(schemaJson).HasParseError()) {
// 此 schema 不是合法的 JSON
// ...
}
@ -28,7 +28,7 @@ SchemaDocument schema(sd); // 把一个 Document 编译至 SchemaDocument
// 之后不再需要 sd
Document d;
if (!d.Parse(inputJson).HasParseError()) {
if (d.Parse(inputJson).HasParseError()) {
// 输入不是一个合法的 JSON
// ...
}
@ -52,11 +52,11 @@ if (!d.Accept(validator)) {
* 一个 `SchemaDocment` 能被多个 `SchemaValidator` 引用。它不会被 `SchemaValidator` 修改。
* 可以重复使用一个 `SchemaValidator` 来校验多个文件。在校验其他文件前,须先调用 `validator.Reset()`
## 在解析/生成时进行校验
# 在解析/生成时进行校验 {#ParsingSerialization}
与大部分 JSON Schema 校验器有所不同RapidJSON 提供了一个基于 SAX 的 schema 校验器实现。因此,你可以在输入流解析 JSON 的同时进行校验。若校验器遇到一个与 schema 不符的值,就会立即终止解析。这设计对于解析大型 JSON 文件时特别有用。
### DOM 解析
## DOM 解析 {#DomParsing}
在使用 DOM 进行解析时,`Document` 除了接收 SAX 事件外,还需做一些准备及结束工作,因此,为了连接 `Reader``SchemaValidator``Document` 要做多一点事情。`SchemaValidatingReader` 是一个辅助类去做那些工作。
@ -97,7 +97,7 @@ if (!reader.GetParseResult()) {
}
~~~
### SAX 解析
## SAX 解析 {#SaxParsing}
使用 SAX 解析时,情况就简单得多。若只需要校验 JSON 而无需进一步处理,那么仅需要:
@ -126,7 +126,7 @@ if (!reader.Parse(ss, validator)) {
}
~~~
### 生成
## 生成 {#Serialization}
我们也可以在生成serialization的时候进行校验。这能确保输出的 JSON 符合一个 JSON Schema。
@ -144,7 +144,7 @@ if (!d.Accept(validator)) {
当然,如果你的应用仅需要 SAX 风格的生成,那么只需要把 SAX 事件由原来发送到 `Writer`,改为发送到 `SchemaValidator`
## 远程 Schema
# 远程 Schema {#RemoteSchema}
JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understanding-json-schema/structuring.html),它是一个 [JSON pointer](doc/pointer.zh-cn.md) 引用至一个本地local或远程remote schema。本地指针的首字符是 `#`,而远程指针是一个相对或绝对 URI。例如
@ -157,7 +157,7 @@ JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understand
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@ -168,7 +168,7 @@ MyRemoteSchemaDocumentProvider provider;
SchemaDocument schema(sd, &provider);
~~~
## 标准的符合程度
# 标准的符合程度 {#Conformance}
RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4) 中 263 个测试的 262 个。
@ -176,7 +176,7 @@ RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON
除此以外,关于字符串类型的 `format` schema 关键字也会被忽略,因为标准中并没需求必须实现。
### 正则表达式
## 正则表达式 {#RegEx}
`pattern``patternProperties` 这两个 schema 关键字使用了正则表达式去匹配所需的模式。
@ -185,7 +185,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|语法|描述|
|------|-----------|
|`ab` | 串联 |
|`a|b` | 交替 |
|<code>a&#124;b</code> | 交替 |
|`a?` | 零或一次 |
|`a*` | 零或多次 |
|`a+` | 一或多次 |
@ -202,7 +202,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|`[^abc]` | 字符组取反 |
|`[^a-c]` | 字符组范围取反 |
|`[\b]` | 退格符 (U+0008) |
|`\|`, `\\`, ... | 转义字符 |
|<code>\\&#124;</code>, `\\`, ... | 转义字符 |
|`\f` | 馈页 (U+000C) |
|`\n` | 馈行 (U+000A) |
|`\r` | 回车 (U+000D) |
@ -211,7 +211,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
对于使用 C++11 编译器的使用者,也可使用 `std::regex`,只需定义 `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0``RAPIDJSON_SCHEMA_USE_STDREGEX=1`。若你的 schema 无需使用 `pattern``patternProperties`,可以把两个宏都设为零,以禁用此功能,这样做可节省一些代码体积。
## 性能
# 性能 {#Performance}
大部分 C++ JSON 库都未支持 JSON Schema。因此我们尝试按照 [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) 去评估 RapidJSON 的 JSON Schema 校验器。该评测测试了 11 个运行在 node.js 上的 JavaScript 库。

View File

@ -1,6 +1,6 @@
# Stream
In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we first show how to use streams provided. And then see how to create a custom stream.
In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we'll first show you how to use provided streams. And then see how to create a custom stream.
[TOC]
@ -42,6 +42,7 @@ Note that, `StringStream` is a typedef of `GenericStringStream<UTF8<> >`, user m
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
#include <rapidjson/writer.h>
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
@ -50,7 +51,7 @@ d.Accept(writer);
const char* output = buffer.GetString();
~~~~~~~~~~
When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and a initial capacity.
When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and an initial capacity.
~~~~~~~~~~cpp
StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024
@ -88,7 +89,7 @@ d.ParseStream(is);
fclose(fp);
~~~~~~~~~~
Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. It will be discussed very soon.
Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. We will discuss more about this later in this tutorial.
Apart from reading file, user can also use `FileReadStream` to read `stdin`.
@ -98,6 +99,7 @@ Apart from reading file, user can also use `FileReadStream` to read `stdin`.
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
#include <rapidjson/writer.h>
#include <cstdio>
using namespace rapidjson;
@ -117,15 +119,15 @@ d.Accept(writer);
fclose(fp);
~~~~~~~~~~
It can also directs the output to `stdout`.
It can also redirect the output to `stdout`.
# iostream Wrapper {#iostreamWrapper}
Due to users' requests, RapidJSON provided official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
Due to users' requests, RapidJSON also provides official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
## IStreamWrapper {#IStreamWrapper}
`IStreamWrapper` wraps any class drived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
`IStreamWrapper` wraps any class derived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
~~~cpp
#include <rapidjson/document.h>
@ -179,7 +181,7 @@ As mentioned above, UTF-8 byte streams can be read directly. However, UTF-16 and
Besides, it also need to handle [byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark). When reading from a byte stream, it is needed to detect or just consume the BOM if exists. When writing to a byte stream, it can optionally write BOM.
If the encoding of stream is known in compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
If the encoding of stream is known during compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
Note that, these encoded streams can be applied to streams other than file. For example, you may have a file in memory, or a custom byte stream, be wrapped in encoded streams.
@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
#include <rapidjson/writer.h>
#include <cstdio>
Document d; // Document is GenericDocument<UTF8<> >
@ -228,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream<UTF32LE<>, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // Write BOM
Writer<OutputStream, UTF32LE<>, UTF8<>> writer(eos);
Writer<OutputStream, UTF8<>, UTF32LE<>> writer(eos);
d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory
fclose(fp);

View File

@ -42,6 +42,7 @@ d.Parse(json);
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
#include <rapidjson/writer.h>
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
@ -98,6 +99,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
#include <rapidjson/writer.h>
#include <cstdio>
using namespace rapidjson;
@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
#include <rapidjson/writer.h>
#include <cstdio>
Document d; // Document 为 GenericDocument<UTF8<> >
@ -228,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream<UTF32LE<>, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // 写入 BOM
Writer<OutputStream, UTF32LE<>, UTF8<>> writer(eos);
Writer<OutputStream, UTF8<>, UTF32LE<>> writer(eos);
d.Accept(writer); // 这里从内存的 UTF-8 生成 UTF32-LE 文件
fclose(fp);

View File

@ -2,7 +2,7 @@
This tutorial introduces the basics of the Document Object Model(DOM) API.
As shown in [Usage at a glance](@ref index), a JSON can be parsed into DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON.
As shown in [Usage at a glance](@ref index), JSON can be parsed into a DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON.
[TOC]
@ -12,9 +12,9 @@ Each JSON value is stored in a type called `Value`. A `Document`, representing t
# Query Value {#QueryValue}
In this section, we will use excerpt of `example/tutorial/tutorial.cpp`.
In this section, we will use excerpt from `example/tutorial/tutorial.cpp`.
Assumes we have a JSON stored in a C string (`const char* json`):
Assume we have the following JSON stored in a C string (`const char* json`):
~~~~~~~~~~js
{
"hello": "world",
@ -55,7 +55,7 @@ printf("hello = %s\n", document["hello"].GetString());
~~~~~~~~~~
~~~~~~~~~~
world
hello = world
~~~~~~~~~~
JSON true/false values are represented as `bool`.
@ -65,16 +65,16 @@ printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
~~~~~~~~~~
~~~~~~~~~~
true
t = true
~~~~~~~~~~
JSON null can be queryed by `IsNull()`.
JSON null can be queried with `IsNull()`.
~~~~~~~~~~cpp
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
~~~~~~~~~~
~~~~~~~~~~
null
n = null
~~~~~~~~~~
JSON number type represents all numeric values. However, C++ needs more specific type for manipulation.
@ -82,10 +82,10 @@ JSON number type represents all numeric values. However, C++ needs more specific
~~~~~~~~~~cpp
assert(document["i"].IsNumber());
// In this case, IsUint()/IsInt64()/IsUInt64() also return true.
// In this case, IsUint()/IsInt64()/IsUint64() also return true.
assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt());
// Alternative (int)document["i"]
// Alternatively (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
@ -113,17 +113,17 @@ a[2] = 3
a[3] = 4
~~~~~~~~~~
Note that, RapidJSON does not automatically convert values between JSON types. If a value is a string, it is invalid to call `GetInt()`, for example. In debug mode it will fail an assertion. In release mode, the behavior is undefined.
Note that, RapidJSON does not automatically convert values between JSON types. For example, if a value is a string, it is invalid to call `GetInt()`. In debug mode it will fail on assertion. In release mode, the behavior is undefined.
In the following, details about querying individual types are discussed.
In the following sections we discuss details about querying individual types.
## Query Array {#QueryArray}
By default, `SizeType` is typedef of `unsigned`. In most systems, array is limited to store up to 2^32-1 elements.
By default, `SizeType` is typedef of `unsigned`. In most systems, an array is limited to store up to 2^32-1 elements.
You may access the elements in array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`.
You may access the elements in an array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`.
Array is similar to `std::vector`, instead of using indices, you may also use iterator to access all the elements.
Array is similar to `std::vector`: instead of using indices, you may also use iterator to access all the elements.
~~~~~~~~~~cpp
for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
printf("%d ", itr->GetInt());
@ -144,7 +144,7 @@ for (auto& v : a.GetArray())
## Query Object {#QueryObject}
Similar to array, we can access all object members by iterator:
Similar to Array, we can access all object members by iterator:
~~~~~~~~~~cpp
static const char* kTypeNames[] =
@ -168,9 +168,9 @@ Type of member pi is Number
Type of member a is Array
~~~~~~~~~~
Note that, when `operator[](const char*)` cannot find the member, it will fail an assertion.
Note that, when `operator[](const char*)` cannot find the member, it will fail on assertion.
If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of member and obtain its value at once:
If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of a member and obtain its value at once:
~~~~~~~~~~cpp
Value::ConstMemberIterator itr = document.FindMember("hello");
@ -190,11 +190,11 @@ for (auto& m : document.GetObject())
## Querying Number {#QueryNumber}
JSON provide a single numerical type called Number. Number can be integer or real numbers. RFC 4627 says the range of Number is specified by parser.
JSON provides a single numerical type called Number. Number can be an integer or a real number. RFC 4627 says the range of Number is specified by the parser implementation.
As C++ provides several integer and floating point number types, the DOM tries to handle these with widest possible range and good performance.
As C++ provides several integer and floating point number types, the DOM tries to handle these with the widest possible range and good performance.
When a Number is parsed, it is stored in the DOM as either one of the following type:
When a Number is parsed, it is stored in the DOM as one of the following types:
Type | Description
-----------|---------------------------------------
@ -204,7 +204,7 @@ Type | Description
`int64_t` | 64-bit signed integer
`double` | 64-bit double precision floating point
When querying a number, you can check whether the number can be obtained as target type:
When querying a number, you can check whether the number can be obtained as the target type:
Checking | Obtaining
------------------|---------------------
@ -215,24 +215,24 @@ Checking | Obtaining
`bool IsInt64()` | `int64_t GetInt64()`
`bool IsDouble()` | `double GetDouble()`
Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only makes `x.IsInt64() == true`.
Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only make `x.IsInt64() == true`.
When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely convert to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits).
When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely converted to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits).
## Query String {#QueryString}
In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why.
In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why:
According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats ``\0'` as the terminator symbol.
According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats `\0` as the terminator symbol.
To conform RFC 4627, RapidJSON supports string containing `U+0000`. If you need to handle this, you can use `GetStringLength()` API to obtain the correct length of string.
To conform with RFC 4627, RapidJSON supports string containing `U+0000` character. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length.
For example, after parsing a the following JSON to `Document d`:
For example, after parsing the following JSON to `Document d`:
~~~~~~~~~~js
{ "s" : "a\u0000b" }
~~~~~~~~~~
The correct length of the value `"a\u0000b"` is 3. But `strlen()` returns 1.
The correct length of the string `"a\u0000b"` is 3, as returned by `GetStringLength()`. But `strlen()` returns 1.
`GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer.
@ -246,7 +246,7 @@ which accepts the length of string as parameter. This constructor supports stori
## Comparing values
You can use `==` and `!=` to compare values. Two values are equal if and only if they are have same type and contents. You can also compare values with primitive types. Here is an example.
You can use `==` and `!=` to compare values. Two values are equal if and only if they have same type and contents. You can also compare values with primitive types. Here is an example:
~~~~~~~~~~cpp
if (document["hello"] == document["n"]) /*...*/; // Compare values
@ -264,7 +264,7 @@ Note that, currently if an object contains duplicated named member, comparing eq
There are several ways to create values. After a DOM tree is created and/or modified, it can be saved as JSON again using `Writer`.
## Change Value Type {#ChangeValueType}
When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
When creating a `Value` or `Document` by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
~~~~~~~~~~cpp
Document d; // Null
@ -285,7 +285,7 @@ Value u(123u); // calls Value(unsigned)
Value d(1.5); // calls Value(double)
~~~~~~~~~~
To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one shot:
To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one call:
~~~~~~~~~~cpp
Value o(kObjectType);
@ -299,7 +299,7 @@ A very special decision during design of RapidJSON is that, assignment of value
~~~~~~~~~~cpp
Value a(123);
Value b(456);
b = a; // a becomes a Null value, b becomes number 123.
a = b; // b becomes a Null value, a becomes number 456.
~~~~~~~~~~
![Assignment with move semantics.](diagram/move1.png)
@ -360,14 +360,14 @@ a.PushBack(Value(42).Move(), allocator); // same as above
~~~~~~~~~~
## Create String {#CreateString}
RapidJSON provide two strategies for storing string.
RapidJSON provides two strategies for storing string.
1. copy-string: allocates a buffer, and then copy the source data into it.
2. const-string: simply store a pointer of string.
Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing string literal, and in-situ parsing which we will mentioned in Document section.
Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing a string literal, and for in-situ parsing which will be mentioned in the DOM section.
To make memory allocation customizable, RapidJSON requires user to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing a allocator (or Document) pointer per Value.
To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing an allocator (or Document) pointer per Value.
Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator:
@ -385,7 +385,7 @@ In this example, we get the allocator from a `Document` instance. This is a comm
Besides, the above `SetString()` requires length. This can handle null characters within a string. There is another `SetString()` overloaded function without the length parameter. And it assumes the input is null-terminated and calls a `strlen()`-like function to obtain the length.
Finally, for string literal or string with safe life-cycle can use const-string version of `SetString()`, which lacks allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient:
Finally, for a string literal or string with a safe life-cycle one can use the const-string version of `SetString()`, which lacks an allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient:
~~~~~~~~~~cpp
Value s;
@ -393,7 +393,7 @@ s.SetString("rapidjson"); // can contain null character, length derived at co
s = "rapidjson"; // shortcut, same as above
~~~~~~~~~~
For character pointer, the RapidJSON requires to mark it as safe before using it without copying. This can be achieved by using the `StringRef` function:
For a character pointer, RapidJSON requires it to be marked as safe before using it without copying. This can be achieved by using the `StringRef` function:
~~~~~~~~~cpp
const char * cstr = getenv("USER");
@ -408,7 +408,7 @@ s = StringRef(cstr,cstr_len); // shortcut, same as above
~~~~~~~~~
## Modify Array {#ModifyArray}
Value with array type provides similar APIs as `std::vector`.
Value with array type provides an API similar to `std::vector`.
* `Clear()`
* `Reserve(SizeType, Allocator&)`
@ -418,7 +418,7 @@ Value with array type provides similar APIs as `std::vector`.
* `ValueIterator Erase(ConstValueIterator pos)`
* `ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)`
Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore require an allocator.
Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore requiring an allocator.
Here is an example of `PushBack()`:
@ -433,7 +433,7 @@ for (int i = 5; i <= 10; i++)
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
~~~~~~~~~~
Differs from STL, `PushBack()`/`PopBack()` returns the array reference itself. This is called _fluent interface_.
This API differs from STL in that `PushBack()`/`PopBack()` return the array reference itself. This is called _fluent interface_.
If you want to add a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)) to the array, you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:
@ -448,7 +448,7 @@ contact.PushBack(val, document.GetAllocator());
~~~~~~~~~~
## Modify Object {#ModifyObject}
Object is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. THe following APIs are for adding members:
The Object class is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. The following API is for adding members:
* `Value& AddMember(Value&, Value&, Allocator& allocator)`
* `Value& AddMember(StringRefType, Value&, Allocator&)`
@ -462,7 +462,7 @@ contact.AddMember("name", "Milo", document.GetAllocator());
contact.AddMember("married", true, document.GetAllocator());
~~~~~~~~~~
The name parameter with `StringRefType` is similar to the interface of `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, as constant key names are very common in JSON objects.
The name parameter with `StringRefType` is similar to the interface of the `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, since constant key names are very common in JSON objects.
If you need to create a name from a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)), you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:

View File

@ -82,7 +82,7 @@ JSON Number 类型表示所有数值。然而C++ 需要使用更专门的类
~~~~~~~~~~cpp
assert(document["i"].IsNumber());
// 在此情况下IsUint()/IsInt64()/IsUInt64() 也会返回 true
// 在此情况下IsUint()/IsInt64()/IsUint64() 也会返回 true
assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt());
// 另一种用法: (int)document["i"]
@ -250,7 +250,7 @@ string(const char* s, size_t count);
~~~~~~~~~~cpp
if (document["hello"] == document["n"]) /*...*/; // 比较两个值
if (document["hello"] == "world") /*...*/; // 与字符串面量作比较
if (document["hello"] == "world") /*...*/; // 与字符串面量作比较
if (document["i"] != 123) /*...*/; // 与整数作比较
if (document["pi"] != 3.14) /*...*/; // 与 double 作比较
~~~~~~~~~~
@ -292,9 +292,9 @@ Value o(kObjectType);
Value a(kArrayType);
~~~~~~~~~~
## 转移语Move Semantics {#MoveSemantics}
## 转移语Move Semantics {#MoveSemantics}
在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value而是把来源 Value 转移move至目的 Value。例如
在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value而是把来源 Value 转移move至目的 Value。例如
~~~~~~~~~~cpp
Value a(123);
@ -302,13 +302,13 @@ Value b(456);
b = a; // a 变成 Nullb 变成数字 123。
~~~~~~~~~~
![使用移动语赋值。](diagram/move1.png)
![使用移动语赋值。](diagram/move1.png)
为什么?此语有何优点?
为什么?此语有何优点?
最简单的答案就是性能。对于固定大小的 JSON 类型Number、True、False、Null复制它们是简单快捷。然而对于可变大小的 JSON 类型String、Array、Object复制它们会产生大量开销而且这些开销常常不被察觉。尤其是当我们需要创建临时 Object把它复制至另一变量然后再析构它。
例如,若使用正常 * 复制 *
例如,若使用正常 * 复制 *
~~~~~~~~~~cpp
Value o(kObjectType);
@ -321,15 +321,15 @@ Value o(kObjectType);
}
~~~~~~~~~~
![复制语产生大量的复制操作。](diagram/move2.png)
![复制语产生大量的复制操作。](diagram/move2.png)
那个 `o` Object 需要分配一个和 contacts 相同大小的缓冲区,对 conacts 做深度复制,并最终要析构 contacts。这样会产生大量无必要的内存分配释放以及内存复制。
有一些方案可避免实质地复制这些数据例如引用计数reference counting、垃圾回收garbage collection, GC
为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 *。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 *。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
因此,使用转移语后,上面的例子变成:
因此,使用转移语后,上面的例子变成:
~~~~~~~~~~cpp
Value o(kObjectType);
@ -341,11 +341,11 @@ Value o(kObjectType);
}
~~~~~~~~~~
![转移语不需复制。](diagram/move3.png)
![转移语不需复制。](diagram/move3.png)
在 C++11 中这称为转移赋值操作move assignment operator。由于 RapidJSON 支持 C++03它在赋值操作采用转移语意,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语意
在 C++11 中这称为转移赋值操作move assignment operator。由于 RapidJSON 支持 C++03它在赋值操作采用转移语义,其它修改型函数如 `AddMember()`, `PushBack()` 也采用转移语义
### 转移语及临时值 {#TemporaryValues}
### 转移语及临时值 {#TemporaryValues}
有时候,我们想直接构造一个 Value 并传递给一个“转移”函数(如 `PushBack()``AddMember()`)。由于临时对象是不能转换为正常的 Value 引用,我们加入了一个方便的 `Move()` 函数:
@ -383,11 +383,12 @@ memset(buffer, 0, sizeof(buffer));
另外,上面的 `SetString()` 需要长度参数。这个 API 能处理含有空字符的字符串。另一个 `SetString()` 重载函数没有长度参数,它假设输入是空字符结尾的,并会调用类似 `strlen()` 的函数去获取长度。
最后,对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 `SetString()`,它没有 allocator 参数。对于字符串家面量(或字符数组常量),只需简单地传递字面量,又安全又高效:
最后,对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 `SetString()`,它没有
allocator 参数。对于字符串字面量(或字符数组常量),只需简单地传递字面量,又安全又高效:
~~~~~~~~~~cpp
Value s;
s.SetString("rapidjson"); // 可包含空字符,长度在编译推导
s.SetString("rapidjson"); // 可包含空字符,长度在编译推导
s = "rapidjson"; // 上行的缩写
~~~~~~~~~~
@ -446,7 +447,7 @@ contact.PushBack(val, document.GetAllocator());
~~~~~~~~~~
## 修改 Object {#ModifyObject}
Object 是键值对的集合。每个键必须为 String。要修改 Object方法是增加或移除成员。以下的 API 用来增加员:
Object 是键值对的集合。每个键必须为 String。要修改 Object方法是增加或移除成员。以下的 API 用来增加员:
* `Value& AddMember(Value&, Value&, Allocator& allocator)`
* `Value& AddMember(StringRefType, Value&, Allocator&)`

View File

@ -10,6 +10,7 @@ set(EXAMPLES
filterkey
filterkeydom
jsonx
lookaheadparser
messagereader
parsebyparts
pretty
@ -18,19 +19,22 @@ set(EXAMPLES
serialize
simpledom
simplereader
simplepullreader
simplewriter
sortkeys
tutorial)
include_directories("../include/")
add_definitions(-D__STDC_FORMAT_MACROS)
set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
add_executable(archivertest archiver/archiver.cpp archiver/archivertest.cpp)
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
endforeach()

View File

@ -0,0 +1,292 @@
#include "archiver.h"
#include <cassert>
#include <stack>
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
struct JsonReaderStackItem {
enum State {
BeforeStart, //!< An object/array is in the stack but it is not yet called by StartObject()/StartArray().
Started, //!< An object/array is called by StartObject()/StartArray().
Closed //!< An array is closed after read all element, but before EndArray().
};
JsonReaderStackItem(const Value* value, State state) : value(value), state(state), index() {}
const Value* value;
State state;
SizeType index; // For array iteration
};
typedef std::stack<JsonReaderStackItem> JsonReaderStack;
#define DOCUMENT reinterpret_cast<Document*>(mDocument)
#define STACK (reinterpret_cast<JsonReaderStack*>(mStack))
#define TOP (STACK->top())
#define CURRENT (*TOP.value)
JsonReader::JsonReader(const char* json) : mDocument(), mStack(), mError(false) {
mDocument = new Document;
DOCUMENT->Parse(json);
if (DOCUMENT->HasParseError())
mError = true;
else {
mStack = new JsonReaderStack;
STACK->push(JsonReaderStackItem(DOCUMENT, JsonReaderStackItem::BeforeStart));
}
}
JsonReader::~JsonReader() {
delete DOCUMENT;
delete STACK;
}
// Archive concept
JsonReader& JsonReader::StartObject() {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::BeforeStart)
TOP.state = JsonReaderStackItem::Started;
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::EndObject() {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
Next();
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::Member(const char* name) {
if (!mError) {
if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) {
Value::ConstMemberIterator memberItr = CURRENT.FindMember(name);
if (memberItr != CURRENT.MemberEnd())
STACK->push(JsonReaderStackItem(&memberItr->value, JsonReaderStackItem::BeforeStart));
else
mError = true;
}
else
mError = true;
}
return *this;
}
bool JsonReader::HasMember(const char* name) const {
if (!mError && CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
return CURRENT.HasMember(name);
return false;
}
JsonReader& JsonReader::StartArray(size_t* size) {
if (!mError) {
if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::BeforeStart) {
TOP.state = JsonReaderStackItem::Started;
if (size)
*size = CURRENT.Size();
if (!CURRENT.Empty()) {
const Value* value = &CURRENT[TOP.index];
STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
}
else
TOP.state = JsonReaderStackItem::Closed;
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::EndArray() {
if (!mError) {
if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::Closed)
Next();
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(bool& b) {
if (!mError) {
if (CURRENT.IsBool()) {
b = CURRENT.GetBool();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(unsigned& u) {
if (!mError) {
if (CURRENT.IsUint()) {
u = CURRENT.GetUint();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(int& i) {
if (!mError) {
if (CURRENT.IsInt()) {
i = CURRENT.GetInt();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(double& d) {
if (!mError) {
if (CURRENT.IsNumber()) {
d = CURRENT.GetDouble();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::operator&(std::string& s) {
if (!mError) {
if (CURRENT.IsString()) {
s = CURRENT.GetString();
Next();
}
else
mError = true;
}
return *this;
}
JsonReader& JsonReader::SetNull() {
// This function is for JsonWriter only.
mError = true;
return *this;
}
void JsonReader::Next() {
if (!mError) {
assert(!STACK->empty());
STACK->pop();
if (!STACK->empty() && CURRENT.IsArray()) {
if (TOP.state == JsonReaderStackItem::Started) { // Otherwise means reading array item pass end
if (TOP.index < CURRENT.Size() - 1) {
const Value* value = &CURRENT[++TOP.index];
STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
}
else
TOP.state = JsonReaderStackItem::Closed;
}
else
mError = true;
}
}
}
#undef DOCUMENT
#undef STACK
#undef TOP
#undef CURRENT
////////////////////////////////////////////////////////////////////////////////
// JsonWriter
#define WRITER reinterpret_cast<PrettyWriter<StringBuffer>*>(mWriter)
#define STREAM reinterpret_cast<StringBuffer*>(mStream)
JsonWriter::JsonWriter() : mWriter(), mStream() {
mStream = new StringBuffer;
mWriter = new PrettyWriter<StringBuffer>(*STREAM);
}
JsonWriter::~JsonWriter() {
delete WRITER;
delete STREAM;
}
const char* JsonWriter::GetString() const {
return STREAM->GetString();
}
JsonWriter& JsonWriter::StartObject() {
WRITER->StartObject();
return *this;
}
JsonWriter& JsonWriter::EndObject() {
WRITER->EndObject();
return *this;
}
JsonWriter& JsonWriter::Member(const char* name) {
WRITER->String(name, static_cast<SizeType>(strlen(name)));
return *this;
}
bool JsonWriter::HasMember(const char*) const {
// This function is for JsonReader only.
assert(false);
return false;
}
JsonWriter& JsonWriter::StartArray(size_t*) {
WRITER->StartArray();
return *this;
}
JsonWriter& JsonWriter::EndArray() {
WRITER->EndArray();
return *this;
}
JsonWriter& JsonWriter::operator&(bool& b) {
WRITER->Bool(b);
return *this;
}
JsonWriter& JsonWriter::operator&(unsigned& u) {
WRITER->Uint(u);
return *this;
}
JsonWriter& JsonWriter::operator&(int& i) {
WRITER->Int(i);
return *this;
}
JsonWriter& JsonWriter::operator&(double& d) {
WRITER->Double(d);
return *this;
}
JsonWriter& JsonWriter::operator&(std::string& s) {
WRITER->String(s.c_str(), static_cast<SizeType>(s.size()));
return *this;
}
JsonWriter& JsonWriter::SetNull() {
WRITER->Null();
return *this;
}
#undef STREAM
#undef WRITER

145
example/archiver/archiver.h Normal file
View File

@ -0,0 +1,145 @@
#ifndef ARCHIVER_H_
#define ARCHIVER_H_
#include <cstddef>
#include <string>
/**
\class Archiver
\brief Archiver concept
Archiver can be a reader or writer for serialization or deserialization respectively.
class Archiver {
public:
/// \returns true if the archiver is in normal state. false if it has errors.
operator bool() const;
/// Starts an object
Archiver& StartObject();
/// After calling StartObject(), assign a member with a name
Archiver& Member(const char* name);
/// After calling StartObject(), check if a member presents
bool HasMember(const char* name) const;
/// Ends an object
Archiver& EndObject();
/// Starts an array
/// \param size If Archiver::IsReader is true, the size of array is written.
Archiver& StartArray(size_t* size = 0);
/// Ends an array
Archiver& EndArray();
/// Read/Write primitive types.
Archiver& operator&(bool& b);
Archiver& operator&(unsigned& u);
Archiver& operator&(int& i);
Archiver& operator&(double& d);
Archiver& operator&(std::string& s);
/// Write primitive types.
Archiver& SetNull();
//! Whether it is a reader.
static const bool IsReader;
//! Whether it is a writer.
static const bool IsWriter;
};
*/
/// Represents a JSON reader which implements Archiver concept.
class JsonReader {
public:
/// Constructor.
/**
\param json A non-const source json string for in-situ parsing.
\note in-situ means the source JSON string will be modified after parsing.
*/
JsonReader(const char* json);
/// Destructor.
~JsonReader();
// Archive concept
operator bool() const { return !mError; }
JsonReader& StartObject();
JsonReader& Member(const char* name);
bool HasMember(const char* name) const;
JsonReader& EndObject();
JsonReader& StartArray(size_t* size = 0);
JsonReader& EndArray();
JsonReader& operator&(bool& b);
JsonReader& operator&(unsigned& u);
JsonReader& operator&(int& i);
JsonReader& operator&(double& d);
JsonReader& operator&(std::string& s);
JsonReader& SetNull();
static const bool IsReader = true;
static const bool IsWriter = !IsReader;
private:
JsonReader(const JsonReader&);
JsonReader& operator=(const JsonReader&);
void Next();
// PIMPL
void* mDocument; ///< DOM result of parsing.
void* mStack; ///< Stack for iterating the DOM
bool mError; ///< Whether an error has occurred.
};
class JsonWriter {
public:
/// Constructor.
JsonWriter();
/// Destructor.
~JsonWriter();
/// Obtains the serialized JSON string.
const char* GetString() const;
// Archive concept
operator bool() const { return true; }
JsonWriter& StartObject();
JsonWriter& Member(const char* name);
bool HasMember(const char* name) const;
JsonWriter& EndObject();
JsonWriter& StartArray(size_t* size = 0);
JsonWriter& EndArray();
JsonWriter& operator&(bool& b);
JsonWriter& operator&(unsigned& u);
JsonWriter& operator&(int& i);
JsonWriter& operator&(double& d);
JsonWriter& operator&(std::string& s);
JsonWriter& SetNull();
static const bool IsReader = false;
static const bool IsWriter = !IsReader;
private:
JsonWriter(const JsonWriter&);
JsonWriter& operator=(const JsonWriter&);
// PIMPL idiom
void* mWriter; ///< JSON writer.
void* mStream; ///< Stream buffer.
};
#endif // ARCHIVER_H__

View File

@ -0,0 +1,287 @@
#include "archiver.h"
#include <iostream>
#include <vector>
//////////////////////////////////////////////////////////////////////////////
// Test1: simple object
struct Student {
Student() : name(), age(), height(), canSwim() {}
Student(const std::string name, unsigned age, double height, bool canSwim) :
name(name), age(age), height(height), canSwim(canSwim)
{}
std::string name;
unsigned age;
double height;
bool canSwim;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Student& s) {
ar.StartObject();
ar.Member("name") & s.name;
ar.Member("age") & s.age;
ar.Member("height") & s.height;
ar.Member("canSwim") & s.canSwim;
return ar.EndObject();
}
std::ostream& operator<<(std::ostream& os, const Student& s) {
return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim;
}
void test1() {
std::string json;
// Serialize
{
Student s("Lua", 9, 150.5, true);
JsonWriter writer;
writer & s;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Student s;
JsonReader reader(json.c_str());
reader & s;
std::cout << s << std::endl;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test2: std::vector <=> JSON array
//
// You can map a JSON array to other data structures as well
struct Group {
Group() : groupName(), students() {}
std::string groupName;
std::vector<Student> students;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Group& g) {
ar.StartObject();
ar.Member("groupName");
ar & g.groupName;
ar.Member("students");
size_t studentCount = g.students.size();
ar.StartArray(&studentCount);
if (ar.IsReader)
g.students.resize(studentCount);
for (size_t i = 0; i < studentCount; i++)
ar & g.students[i];
ar.EndArray();
return ar.EndObject();
}
std::ostream& operator<<(std::ostream& os, const Group& g) {
os << g.groupName << std::endl;
for (std::vector<Student>::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr)
os << *itr << std::endl;
return os;
}
void test2() {
std::string json;
// Serialize
{
Group g;
g.groupName = "Rainbow";
Student s1("Lua", 9, 150.5, true);
Student s2("Mio", 7, 120.0, false);
g.students.push_back(s1);
g.students.push_back(s2);
JsonWriter writer;
writer & g;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Group g;
JsonReader reader(json.c_str());
reader & g;
std::cout << g << std::endl;
}
}
//////////////////////////////////////////////////////////////////////////////
// Test3: polymorphism & friend
//
// Note that friendship is not necessary but make things simpler.
class Shape {
public:
virtual ~Shape() {}
virtual const char* GetType() const = 0;
virtual void Print(std::ostream& os) const = 0;
protected:
Shape() : x_(), y_() {}
Shape(double x, double y) : x_(x), y_(y) {}
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Shape& s);
double x_, y_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape& s) {
ar.Member("x") & s.x_;
ar.Member("y") & s.y_;
return ar;
}
class Circle : public Shape {
public:
Circle() : radius_() {}
Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {}
~Circle() {}
const char* GetType() const { return "Circle"; }
void Print(std::ostream& os) const {
os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_;
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Circle& c);
double radius_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Circle& c) {
ar & static_cast<Shape&>(c);
ar.Member("radius") & c.radius_;
return ar;
}
class Box : public Shape {
public:
Box() : width_(), height_() {}
Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {}
~Box() {}
const char* GetType() const { return "Box"; }
void Print(std::ostream& os) const {
os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_;
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Box& b);
double width_, height_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Box& b) {
ar & static_cast<Shape&>(b);
ar.Member("width") & b.width_;
ar.Member("height") & b.height_;
return ar;
}
class Canvas {
public:
Canvas() : shapes_() {}
~Canvas() { Clear(); }
void Clear() {
for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr)
delete *itr;
}
void AddShape(Shape* shape) { shapes_.push_back(shape); }
void Print(std::ostream& os) {
for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) {
(*itr)->Print(os);
std::cout << std::endl;
}
}
private:
template <typename Archiver>
friend Archiver& operator&(Archiver& ar, Canvas& c);
std::vector<Shape*> shapes_;
};
template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape*& shape) {
std::string type = ar.IsReader ? "" : shape->GetType();
ar.StartObject();
ar.Member("type") & type;
if (type == "Circle") {
if (ar.IsReader) shape = new Circle;
ar & static_cast<Circle&>(*shape);
}
else if (type == "Box") {
if (ar.IsReader) shape = new Box;
ar & static_cast<Box&>(*shape);
}
return ar.EndObject();
}
template <typename Archiver>
Archiver& operator&(Archiver& ar, Canvas& c) {
size_t shapeCount = c.shapes_.size();
ar.StartArray(&shapeCount);
if (ar.IsReader) {
c.Clear();
c.shapes_.resize(shapeCount);
}
for (size_t i = 0; i < shapeCount; i++)
ar & c.shapes_[i];
return ar.EndArray();
}
void test3() {
std::string json;
// Serialize
{
Canvas c;
c.AddShape(new Circle(1.0, 2.0, 3.0));
c.AddShape(new Box(4.0, 5.0, 6.0, 7.0));
JsonWriter writer;
writer & c;
json = writer.GetString();
std::cout << json << std::endl;
}
// Deserialize
{
Canvas c;
JsonReader reader(json.c_str());
reader & c;
c.Print(std::cout);
}
}
//////////////////////////////////////////////////////////////////////////////
int main() {
test1();
test2();
test3();
}

View File

@ -1,4 +1,4 @@
// JSON to JSONx conversion exmaple, using SAX API.
// JSON to JSONx conversion example, using SAX API.
// JSONx is an IBM standard format to represent JSON as XML.
// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
// This example parses JSON text from stdin with validation,

View File

@ -0,0 +1,350 @@
#include "rapidjson/reader.h"
#include "rapidjson/document.h"
#include <iostream>
RAPIDJSON_DIAG_PUSH
#ifdef __GNUC__
RAPIDJSON_DIAG_OFF(effc++)
#endif
// This example demonstrates JSON token-by-token parsing with an API that is
// more direct; you don't need to design your logic around a handler object and
// callbacks. Instead, you retrieve values from the JSON stream by calling
// GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures
// by calling EnterObject() and EnterArray(), and skip over unwanted data by
// calling SkipValue(). When you know your JSON's structure, this can be quite
// convenient.
//
// If you aren't sure of what's next in the JSON data, you can use PeekType() and
// PeekValue() to look ahead to the next object before reading it.
//
// If you call the wrong retrieval method--e.g. GetInt when the next JSON token is
// not an int, EnterObject or EnterArray when there isn't actually an object or array
// to read--the stream parsing will end immediately and no more data will be delivered.
//
// After calling EnterObject, you retrieve keys via NextObjectKey() and values via
// the normal getters. When NextObjectKey() returns null, you have exited the
// object, or you can call SkipObject() to skip to the end of the object
// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null),
// you should not call SkipObject().
//
// After calling EnterArray(), you must alternate between calling NextArrayValue()
// to see if the array has more data, and then retrieving values via the normal
// getters. You can call SkipArray() to skip to the end of the array immediately.
// If you fetch the entire array (i.e. NextArrayValue() returned null),
// you should not call SkipArray().
//
// This parser uses in-situ strings, so the JSON buffer will be altered during the
// parse.
using namespace rapidjson;
class LookaheadParserHandler {
public:
bool Null() { st_ = kHasNull; v_.SetNull(); return true; }
bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; }
bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; }
bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; }
bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; }
bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; }
bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; }
bool RawNumber(const char*, SizeType, bool) { return false; }
bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; }
bool StartObject() { st_ = kEnteringObject; return true; }
bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; }
bool EndObject(SizeType) { st_ = kExitingObject; return true; }
bool StartArray() { st_ = kEnteringArray; return true; }
bool EndArray(SizeType) { st_ = kExitingArray; return true; }
protected:
LookaheadParserHandler(char* str);
void ParseNext();
protected:
enum LookaheadParsingState {
kInit,
kError,
kHasNull,
kHasBool,
kHasNumber,
kHasString,
kHasKey,
kEnteringObject,
kExitingObject,
kEnteringArray,
kExitingArray
};
Value v_;
LookaheadParsingState st_;
Reader r_;
InsituStringStream ss_;
static const int parseFlags = kParseDefaultFlags | kParseInsituFlag;
};
LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) {
r_.IterativeParseInit();
ParseNext();
}
void LookaheadParserHandler::ParseNext() {
if (r_.HasParseError()) {
st_ = kError;
return;
}
r_.IterativeParseNext<parseFlags>(ss_, *this);
}
class LookaheadParser : protected LookaheadParserHandler {
public:
LookaheadParser(char* str) : LookaheadParserHandler(str) {}
bool EnterObject();
bool EnterArray();
const char* NextObjectKey();
bool NextArrayValue();
int GetInt();
double GetDouble();
const char* GetString();
bool GetBool();
void GetNull();
void SkipObject();
void SkipArray();
void SkipValue();
Value* PeekValue();
int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
bool IsValid() { return st_ != kError; }
protected:
void SkipOut(int depth);
};
bool LookaheadParser::EnterObject() {
if (st_ != kEnteringObject) {
st_ = kError;
return false;
}
ParseNext();
return true;
}
bool LookaheadParser::EnterArray() {
if (st_ != kEnteringArray) {
st_ = kError;
return false;
}
ParseNext();
return true;
}
const char* LookaheadParser::NextObjectKey() {
if (st_ == kHasKey) {
const char* result = v_.GetString();
ParseNext();
return result;
}
if (st_ != kExitingObject) {
st_ = kError;
return 0;
}
ParseNext();
return 0;
}
bool LookaheadParser::NextArrayValue() {
if (st_ == kExitingArray) {
ParseNext();
return false;
}
if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) {
st_ = kError;
return false;
}
return true;
}
int LookaheadParser::GetInt() {
if (st_ != kHasNumber || !v_.IsInt()) {
st_ = kError;
return 0;
}
int result = v_.GetInt();
ParseNext();
return result;
}
double LookaheadParser::GetDouble() {
if (st_ != kHasNumber) {
st_ = kError;
return 0.;
}
double result = v_.GetDouble();
ParseNext();
return result;
}
bool LookaheadParser::GetBool() {
if (st_ != kHasBool) {
st_ = kError;
return false;
}
bool result = v_.GetBool();
ParseNext();
return result;
}
void LookaheadParser::GetNull() {
if (st_ != kHasNull) {
st_ = kError;
return;
}
ParseNext();
}
const char* LookaheadParser::GetString() {
if (st_ != kHasString) {
st_ = kError;
return 0;
}
const char* result = v_.GetString();
ParseNext();
return result;
}
void LookaheadParser::SkipOut(int depth) {
do {
if (st_ == kEnteringArray || st_ == kEnteringObject) {
++depth;
}
else if (st_ == kExitingArray || st_ == kExitingObject) {
--depth;
}
else if (st_ == kError) {
return;
}
ParseNext();
}
while (depth > 0);
}
void LookaheadParser::SkipValue() {
SkipOut(0);
}
void LookaheadParser::SkipArray() {
SkipOut(1);
}
void LookaheadParser::SkipObject() {
SkipOut(1);
}
Value* LookaheadParser::PeekValue() {
if (st_ >= kHasNull && st_ <= kHasKey) {
return &v_;
}
return 0;
}
int LookaheadParser::PeekType() {
if (st_ >= kHasNull && st_ <= kHasKey) {
return v_.GetType();
}
if (st_ == kEnteringArray) {
return kArrayType;
}
if (st_ == kEnteringObject) {
return kObjectType;
}
return -1;
}
//-------------------------------------------------------------------------
int main() {
using namespace std;
char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null,"
"\"i\":123, \"pi\": 3.1416, \"a\":[-1, 2, 3, 4, \"array\", []], \"skipArrays\":[1, 2, [[[3]]]], "
"\"skipObject\":{ \"i\":0, \"t\":true, \"n\":null, \"d\":123.45 }, "
"\"skipNested\":[[[[{\"\":0}, {\"\":[-9.87]}]]], [], []], "
"\"skipString\":\"zzz\", \"reachedEnd\":null, \"t\":true }";
LookaheadParser r(json);
RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
r.EnterObject();
while (const char* key = r.NextObjectKey()) {
if (0 == strcmp(key, "hello")) {
RAPIDJSON_ASSERT(r.PeekType() == kStringType);
cout << key << ":" << r.GetString() << endl;
}
else if (0 == strcmp(key, "t") || 0 == strcmp(key, "f")) {
RAPIDJSON_ASSERT(r.PeekType() == kTrueType || r.PeekType() == kFalseType);
cout << key << ":" << r.GetBool() << endl;
continue;
}
else if (0 == strcmp(key, "n")) {
RAPIDJSON_ASSERT(r.PeekType() == kNullType);
r.GetNull();
cout << key << endl;
continue;
}
else if (0 == strcmp(key, "pi")) {
RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
cout << key << ":" << r.GetDouble() << endl;
continue;
}
else if (0 == strcmp(key, "a")) {
RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
r.EnterArray();
cout << key << ":[ ";
while (r.NextArrayValue()) {
if (r.PeekType() == kNumberType) {
cout << r.GetDouble() << " ";
}
else if (r.PeekType() == kStringType) {
cout << r.GetString() << " ";
}
else {
r.SkipArray();
break;
}
}
cout << "]" << endl;
}
else {
cout << key << ":skipped" << endl;
r.SkipValue();
}
}
return 0;
}
RAPIDJSON_DIAG_POP

View File

@ -21,12 +21,15 @@ public:
AsyncDocumentParser(Document& d)
: stream_(*this)
, d_(d)
, parseThread_(&AsyncDocumentParser::Parse, this)
, parseThread_()
, mutex_()
, notEmpty_()
, finish_()
, completed_()
{}
{
// Create and execute thread after all member variables are initialized.
parseThread_ = std::thread(&AsyncDocumentParser::Parse, this);
}
~AsyncDocumentParser() {
if (!parseThread_.joinable())
@ -140,7 +143,7 @@ int main() {
AsyncDocumentParser<> parser(d);
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // For test parsing error
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";

View File

@ -2,13 +2,132 @@
// The example validates JSON text from stdin with a JSON schema specified in the argument.
#define RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"
#include <string>
#include <iostream>
#include <sstream>
using namespace rapidjson;
typedef GenericValue<UTF8<>, CrtAllocator > ValueType;
// Forward ref
static void CreateErrorMessages(const ValueType& errors, size_t depth, const char* context);
// Convert GenericValue to std::string
static std::string GetString(const ValueType& val) {
std::ostringstream s;
if (val.IsString())
s << val.GetString();
else if (val.IsDouble())
s << val.GetDouble();
else if (val.IsUint())
s << val.GetUint();
else if (val.IsInt())
s << val.GetInt();
else if (val.IsUint64())
s << val.GetUint64();
else if (val.IsInt64())
s << val.GetInt64();
else if (val.IsBool() && val.GetBool())
s << "true";
else if (val.IsBool())
s << "false";
else if (val.IsFloat())
s << val.GetFloat();
return s.str();
}
// Create the error message for a named error
// The error object can either be empty or contain at least member properties:
// {"errorCode": <code>, "instanceRef": "<pointer>", "schemaRef": "<pointer>" }
// Additional properties may be present for use as inserts.
// An "errors" property may be present if there are child errors.
static void HandleError(const char* errorName, const ValueType& error, size_t depth, const char* context) {
if (!error.ObjectEmpty()) {
// Get error code and look up error message text (English)
int code = error["errorCode"].GetInt();
std::string message(GetValidateError_En(static_cast<ValidateErrorCode>(code)));
// For each member property in the error, see if its name exists as an insert in the error message and if so replace with the stringified property value
// So for example - "Number '%actual' is not a multiple of the 'multipleOf' value '%expected'." - we would expect "actual" and "expected" members.
for (ValueType::ConstMemberIterator insertsItr = error.MemberBegin();
insertsItr != error.MemberEnd(); ++insertsItr) {
std::string insertName("%");
insertName += insertsItr->name.GetString(); // eg "%actual"
size_t insertPos = message.find(insertName);
if (insertPos != std::string::npos) {
std::string insertString("");
const ValueType &insert = insertsItr->value;
if (insert.IsArray()) {
// Member is an array so create comma-separated list of items for the insert string
for (ValueType::ConstValueIterator itemsItr = insert.Begin(); itemsItr != insert.End(); ++itemsItr) {
if (itemsItr != insert.Begin()) insertString += ",";
insertString += GetString(*itemsItr);
}
} else {
insertString += GetString(insert);
}
message.replace(insertPos, insertName.length(), insertString);
}
}
// Output error message, references, context
std::string indent(depth * 2, ' ');
std::cout << indent << "Error Name: " << errorName << std::endl;
std::cout << indent << "Message: " << message.c_str() << std::endl;
std::cout << indent << "Instance: " << error["instanceRef"].GetString() << std::endl;
std::cout << indent << "Schema: " << error["schemaRef"].GetString() << std::endl;
if (depth > 0) std::cout << indent << "Context: " << context << std::endl;
std::cout << std::endl;
// If child errors exist, apply the process recursively to each error structure.
// This occurs for "oneOf", "allOf", "anyOf" and "dependencies" errors, so pass the error name as context.
if (error.HasMember("errors")) {
depth++;
const ValueType &childErrors = error["errors"];
if (childErrors.IsArray()) {
// Array - each item is an error structure - example
// "anyOf": {"errorCode": ..., "errors":[{"pattern": {"errorCode\": ...\"}}, {"pattern": {"errorCode\": ...}}]
for (ValueType::ConstValueIterator errorsItr = childErrors.Begin();
errorsItr != childErrors.End(); ++errorsItr) {
CreateErrorMessages(*errorsItr, depth, errorName);
}
} else if (childErrors.IsObject()) {
// Object - each member is an error structure - example
// "dependencies": {"errorCode": ..., "errors": {"address": {"required": {"errorCode": ...}}, "name": {"required": {"errorCode": ...}}}
for (ValueType::ConstMemberIterator propsItr = childErrors.MemberBegin();
propsItr != childErrors.MemberEnd(); ++propsItr) {
CreateErrorMessages(propsItr->value, depth, errorName);
}
}
}
}
}
// Create error message for all errors in an error structure
// Context is used to indicate whether the error structure has a parent 'dependencies', 'allOf', 'anyOf' or 'oneOf' error
static void CreateErrorMessages(const ValueType& errors, size_t depth = 0, const char* context = 0) {
// Each member property contains one or more errors of a given type
for (ValueType::ConstMemberIterator errorTypeItr = errors.MemberBegin(); errorTypeItr != errors.MemberEnd(); ++errorTypeItr) {
const char* errorName = errorTypeItr->name.GetString();
const ValueType& errorContent = errorTypeItr->value;
if (errorContent.IsArray()) {
// Member is an array where each item is an error - eg "type": [{"errorCode": ...}, {"errorCode": ...}]
for (ValueType::ConstValueIterator contentItr = errorContent.Begin(); contentItr != errorContent.End(); ++contentItr) {
HandleError(errorName, *contentItr, depth, context);
}
} else if (errorContent.IsObject()) {
// Member is an object which is a single error - eg "type": {"errorCode": ... }
HandleError(errorName, errorContent, depth, context);
}
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n");
@ -64,9 +183,17 @@ int main(int argc, char *argv[]) {
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid schema: %s\n", sb.GetString());
fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
fprintf(stderr, "Invalid code: %d\n", validator.GetInvalidSchemaCode());
fprintf(stderr, "Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode()));
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
// Detailed violation report is available as a JSON value
sb.Clear();
PrettyWriter<StringBuffer> w(sb);
validator.GetError().Accept(w);
fprintf(stderr, "Error report:\n%s\n", sb.GetString());
CreateErrorMessages(validator.GetError());
return EXIT_FAILURE;
}
}

View File

@ -0,0 +1,53 @@
#include "rapidjson/reader.h"
#include <iostream>
#include <sstream>
using namespace rapidjson;
using namespace std;
// If you can require C++11, you could use std::to_string here
template <typename T> std::string stringify(T x) {
std::stringstream ss;
ss << x;
return ss.str();
}
struct MyHandler {
const char* type;
std::string data;
MyHandler() : type(), data() {}
bool Null() { type = "Null"; data.clear(); return true; }
bool Bool(bool b) { type = "Bool:"; data = b? "true": "false"; return true; }
bool Int(int i) { type = "Int:"; data = stringify(i); return true; }
bool Uint(unsigned u) { type = "Uint:"; data = stringify(u); return true; }
bool Int64(int64_t i) { type = "Int64:"; data = stringify(i); return true; }
bool Uint64(uint64_t u) { type = "Uint64:"; data = stringify(u); return true; }
bool Double(double d) { type = "Double:"; data = stringify(d); return true; }
bool RawNumber(const char* str, SizeType length, bool) { type = "Number:"; data = std::string(str, length); return true; }
bool String(const char* str, SizeType length, bool) { type = "String:"; data = std::string(str, length); return true; }
bool StartObject() { type = "StartObject"; data.clear(); return true; }
bool Key(const char* str, SizeType length, bool) { type = "Key:"; data = std::string(str, length); return true; }
bool EndObject(SizeType memberCount) { type = "EndObject:"; data = stringify(memberCount); return true; }
bool StartArray() { type = "StartArray"; data.clear(); return true; }
bool EndArray(SizeType elementCount) { type = "EndArray:"; data = stringify(elementCount); return true; }
private:
MyHandler(const MyHandler& noCopyConstruction);
MyHandler& operator=(const MyHandler& noAssignment);
};
int main() {
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
MyHandler handler;
Reader reader;
StringStream ss(json);
reader.IterativeParseInit();
while (!reader.IterativeParseComplete()) {
reader.IterativeParseNext<kParseDefaultFlags>(ss, handler);
cout << handler.type << handler.data << endl;
}
return 0;
}

View File

@ -0,0 +1,62 @@
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include <rapidjson/prettywriter.h>
#include <algorithm>
#include <iostream>
using namespace rapidjson;
using namespace std;
static void printIt(const Value &doc) {
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
PrettyWriter<FileWriteStream> writer(os);
doc.Accept(writer);
cout << endl;
}
struct NameComparator {
bool operator()(const Value::Member &lhs, const Value::Member &rhs) const {
return (strcmp(lhs.name.GetString(), rhs.name.GetString()) < 0);
}
};
int main() {
Document d(kObjectType);
Document::AllocatorType &allocator = d.GetAllocator();
d.AddMember("zeta", Value().SetBool(false), allocator);
d.AddMember("gama", Value().SetString("test string", allocator), allocator);
d.AddMember("delta", Value().SetInt(123), allocator);
d.AddMember("alpha", Value(kArrayType).Move(), allocator);
printIt(d);
/*
{
"zeta": false,
"gama": "test string",
"delta": 123,
"alpha": []
}
*/
// C++11 supports std::move() of Value so it always have no problem for std::sort().
// Some C++03 implementations of std::sort() requires copy constructor which causes compilation error.
// Needs a sorting function only depends on std::swap() instead.
#if __cplusplus >= 201103L || (!defined(__GLIBCXX__) && (!defined(_MSC_VER) || _MSC_VER >= 1900))
std::sort(d.MemberBegin(), d.MemberEnd(), NameComparator());
printIt(d);
/*
{
"alpha": [],
"delta": 123,
"gama": "test string",
"zeta": false
}
*/
#endif
}

View File

@ -0,0 +1,39 @@
#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/pointer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
using namespace rapidjson;
void traverse(const Value& v, const Pointer& p) {
StringBuffer sb;
p.Stringify(sb);
std::cout << sb.GetString() << std::endl;
switch (v.GetType()) {
case kArrayType:
for (SizeType i = 0; i != v.Size(); ++i)
traverse(v[i], p.Append(i));
break;
case kObjectType:
for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m)
traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength()));
break;
default:
break;
}
}
int main(int, char*[]) {
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
Document d;
d.ParseStream(is);
Pointer root;
traverse(d, root);
return 0;
}

View File

@ -57,7 +57,7 @@ int main(int, char*[]) {
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type.
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUint64() also return true.
printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
assert(document["pi"].IsNumber());

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -16,6 +16,14 @@
#define RAPIDJSON_ALLOCATORS_H_
#include "rapidjson.h"
#include "internal/meta.h"
#include <memory>
#include <limits>
#if RAPIDJSON_HAS_CXX11
#include <type_traits>
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -52,6 +60,19 @@ concept Allocator {
\endcode
*/
/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
\ingroup RAPIDJSON_CONFIG
\brief User-defined kDefaultChunkCapacity definition.
User can define this as any \c size that is a power of 2.
*/
#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
#endif
///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
@ -64,19 +85,26 @@ public:
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
return std::malloc(size);
return RAPIDJSON_MALLOC(size);
else
return NULL; // standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize;
if (newSize == 0) {
std::free(originalPtr);
RAPIDJSON_FREE(originalPtr);
return NULL;
}
return std::realloc(originalPtr, newSize);
return RAPIDJSON_REALLOC(originalPtr, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
return true;
}
bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
return false;
}
static void Free(void *ptr) { std::free(ptr); }
};
///////////////////////////////////////////////////////////////////////////////
@ -100,16 +128,64 @@ public:
*/
template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator {
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
*/
struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
};
struct SharedData {
ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
size_t refcount;
bool ownBuffer;
};
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
static inline ChunkHeader *GetChunkHead(SharedData *shared)
{
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
}
static inline uint8_t *GetChunkBuffer(SharedData *shared)
{
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
}
static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
//! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
explicit
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
{
RAPIDJSON_ASSERT(baseAllocator_ != 0);
RAPIDJSON_ASSERT(shared_ != 0);
if (baseAllocator) {
shared_->ownBaseAllocator = 0;
}
else {
shared_->ownBaseAllocator = baseAllocator_;
}
shared_->chunkHead = GetChunkHead(shared_);
shared_->chunkHead->capacity = 0;
shared_->chunkHead->size = 0;
shared_->chunkHead->next = 0;
shared_->ownBuffer = true;
shared_->refcount = 1;
}
//! Constructor with user-supplied buffer.
@ -123,41 +199,101 @@ public:
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator),
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
{
RAPIDJSON_ASSERT(buffer != 0);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
chunkHead_->capacity = size - sizeof(ChunkHeader);
chunkHead_->size = 0;
chunkHead_->next = 0;
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
shared_->chunkHead = GetChunkHead(shared_);
shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
shared_->chunkHead->size = 0;
shared_->chunkHead->next = 0;
shared_->ownBaseAllocator = 0;
shared_->ownBuffer = false;
shared_->refcount = 1;
}
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
++shared_->refcount;
}
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
++rhs.shared_->refcount;
this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_;
chunk_capacity_ = rhs.chunk_capacity_;
shared_ = rhs.shared_;
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
rhs.shared_ = 0;
}
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_;
chunk_capacity_ = rhs.chunk_capacity_;
shared_ = rhs.shared_;
rhs.shared_ = 0;
return *this;
}
#endif
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
~MemoryPoolAllocator() {
~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
if (!shared_) {
// do nothing if moved
return;
}
if (shared_->refcount > 1) {
--shared_->refcount;
return;
}
Clear();
RAPIDJSON_DELETE(ownBaseAllocator_);
BaseAllocator *a = shared_->ownBaseAllocator;
if (shared_->ownBuffer) {
baseAllocator_->Free(shared_);
}
RAPIDJSON_DELETE(a);
}
//! Deallocates all memory chunks, excluding the user-supplied buffer.
void Clear() {
while (chunkHead_ && chunkHead_ != userBuffer_) {
ChunkHeader* next = chunkHead_->next;
baseAllocator_->Free(chunkHead_);
chunkHead_ = next;
//! Deallocates all memory chunks, excluding the first/user one.
void Clear() RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
for (;;) {
ChunkHeader* c = shared_->chunkHead;
if (!c->next) {
break;
}
shared_->chunkHead = c->next;
baseAllocator_->Free(c);
}
if (chunkHead_ && chunkHead_ == userBuffer_)
chunkHead_->size = 0; // Clear user buffer
shared_->chunkHead->size = 0;
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
size_t Capacity() const {
size_t Capacity() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t capacity = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
capacity += c->capacity;
return capacity;
}
@ -165,25 +301,35 @@ public:
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
size_t Size() const {
size_t Size() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t size = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
size += c->size;
return size;
}
//! Whether the allocator is shared.
/*! \return true or false.
*/
bool Shared() const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
return shared_->refcount > 1;
}
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
shared_->chunkHead->size += size;
return buffer;
}
@ -192,6 +338,7 @@ public:
if (originalPtr == 0)
return Malloc(newSize);
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (newSize == 0)
return NULL;
@ -203,10 +350,10 @@ public:
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize);
if (chunkHead_->size + increment <= chunkHead_->capacity) {
chunkHead_->size += increment;
if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
shared_->chunkHead->size += increment;
return originalPtr;
}
}
@ -222,50 +369,325 @@ public:
}
//! Frees a memory block (concept Allocator)
static void Free(void *ptr) { (void)ptr; } // Do nothing
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
//! Compare (equality) with another MemoryPoolAllocator
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
return shared_ == rhs.shared_;
}
//! Compare (inequality) with another MemoryPoolAllocator
bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
return !operator==(rhs);
}
private:
//! Copy constructor is not permitted.
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
//! Copy assignment operator is not permitted.
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
chunk->next = shared_->chunkHead;
shared_->chunkHead = chunk;
return true;
}
else
return false;
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
static inline void* AlignBuffer(void* buf, size_t &size)
{
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
const uintptr_t mask = sizeof(void*) - 1;
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
const uintptr_t abuf = (ubuf + mask) & ~mask;
RAPIDJSON_ASSERT(size >= abuf - ubuf);
buf = reinterpret_cast<void*>(abuf);
size -= abuf - ubuf;
}
return buf;
}
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
*/
struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
SharedData *shared_; //!< The shared data of the allocator
};
namespace internal {
template<typename, typename = void>
struct IsRefCounted :
public FalseType
{ };
template<typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
public TrueType
{ };
}
template<typename T, typename A>
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
{
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits<size_t>::max)() / sizeof(T) && new_n <= (std::numeric_limits<size_t>::max)() / sizeof(T));
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
}
template<typename T, typename A>
inline T *Malloc(A& a, size_t n = 1)
{
return Realloc<T, A>(a, NULL, 0, n);
}
template<typename T, typename A>
inline void Free(A& a, T *p, size_t n = 1)
{
static_cast<void>(Realloc<T, A>(a, p, n, 0));
}
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
#endif
template <typename T, typename BaseAllocator = CrtAllocator>
class StdAllocator :
public std::allocator<T>
{
typedef std::allocator<T> allocator_type;
#if RAPIDJSON_HAS_CXX11
typedef std::allocator_traits<allocator_type> traits_type;
#else
typedef allocator_type traits_type;
#endif
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(std::move(rhs)),
baseAllocator_(std::move(rhs.baseAllocator_))
{ }
#endif
#if RAPIDJSON_HAS_CXX11
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
#endif
/* implicit */
StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(baseAllocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
};
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
void *userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
typedef typename traits_type::size_type size_type;
typedef typename traits_type::difference_type difference_type;
typedef typename traits_type::value_type value_type;
typedef typename traits_type::pointer pointer;
typedef typename traits_type::const_pointer const_pointer;
#if RAPIDJSON_HAS_CXX11
typedef typename std::add_lvalue_reference<value_type>::type &reference;
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return traits_type::max_size(*this);
}
template <typename ...Args>
void construct(pointer p, Args&&... args)
{
traits_type::construct(*this, p, std::forward<Args>(args)...);
}
void destroy(pointer p)
{
traits_type::destroy(*this, p);
}
#else // !RAPIDJSON_HAS_CXX11
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r);
}
size_type max_size() const RAPIDJSON_NOEXCEPT
{
return allocator_type::max_size();
}
void construct(pointer p, const_reference r)
{
allocator_type::construct(p, r);
}
void destroy(pointer p)
{
allocator_type::destroy(p);
}
#endif // !RAPIDJSON_HAS_CXX11
template <typename U>
U* allocate(size_type n = 1, const void* = 0)
{
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
}
template <typename U>
void deallocate(U* p, size_type n = 1)
{
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
}
pointer allocate(size_type n = 1, const void* = 0)
{
return allocate<value_type>(n);
}
void deallocate(pointer p, size_type n = 1)
{
deallocate<value_type>(p, n);
}
#if RAPIDJSON_HAS_CXX11
using is_always_equal = std::is_empty<BaseAllocator>;
#endif
template<typename U>
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return baseAllocator_ == rhs.baseAllocator_;
}
template<typename U>
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return !operator==(rhs);
}
//! rapidjson Allocator concept
static const bool kNeedFree = BaseAllocator::kNeedFree;
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
void* Malloc(size_t size)
{
return baseAllocator_.Malloc(size);
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
{
BaseAllocator::Free(ptr);
}
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
};
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
template <typename BaseAllocator>
class StdAllocator<void, BaseAllocator> :
public std::allocator<void>
{
typedef std::allocator<void> allocator_type;
public:
typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
/* implicit */
StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
allocator_type(),
baseAllocator_(baseAllocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template<typename U>
struct rebind {
typedef StdAllocator<U, BaseAllocator> other;
};
typedef typename allocator_type::value_type value_type;
private:
template <typename, typename>
friend class StdAllocator; // access to StdAllocator<!T>.*
BaseAllocator baseAllocator_;
};
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_

View File

@ -0,0 +1,78 @@
// 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_CURSORSTREAMWRAPPER_H_
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
#include "stream.h"
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4702) // unreachable code
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
RAPIDJSON_NAMESPACE_BEGIN
//! Cursor stream wrapper for counting line and column number if error exists.
/*!
\tparam InputStream Any stream that implements Stream Concept
*/
template <typename InputStream, typename Encoding = UTF8<> >
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public:
typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is):
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number
Ch Take() {
Ch ch = this->is_.Take();
if(ch == '\n') {
line_ ++;
col_ = 0;
} else {
col_ ++;
}
return ch;
}
//! Get the error line number, if error exists.
size_t GetLine() const { return line_; }
//! Get the error column number, if error exists.
size_t GetColumn() const { return col_; }
private:
size_t line_; //!< Current Line
size_t col_; //!< Current Column
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
RAPIDJSON_DIAG_POP
#endif
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -200,7 +200,7 @@ private:
// xx xx xx xx UTF-8
if (!hasBOM_) {
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
switch (pattern) {
case 0x08: type_ = kUTF32BE; break;
case 0x0A: type_ = kUTF16BE; break;

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -17,7 +17,7 @@
#include "rapidjson.h"
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
RAPIDJSON_DIAG_OFF(4702) // unreachable code
@ -144,9 +144,9 @@ struct UTF8 {
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
typename InputStream::Ch c = is.Take();
if (!(c & 0x80)) {
*codepoint = static_cast<unsigned char>(c);
@ -157,48 +157,48 @@ struct UTF8 {
if (type >= 32) {
*codepoint = 0;
} else {
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
}
bool result = true;
switch (type) {
case 2: TAIL(); return result;
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
case 2: RAPIDJSON_TAIL(); return result;
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
default: return false;
}
#undef COPY
#undef TRANS
#undef TAIL
#undef RAPIDJSON_COPY
#undef RAPIDJSON_TRANS
#undef RAPIDJSON_TAIL
}
template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) {
#define COPY() os.Put(c = is.Take())
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
Ch c;
COPY();
#define RAPIDJSON_COPY() if (c != '\0') os.Put(c = is.Take())
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
Ch c = static_cast<Ch>(-1);
RAPIDJSON_COPY();
if (!(c & 0x80))
return true;
bool result = true;
switch (GetRange(static_cast<unsigned char>(c))) {
case 2: TAIL(); return result;
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
case 2: RAPIDJSON_TAIL(); return result;
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
default: return false;
}
#undef COPY
#undef TRANS
#undef TAIL
#undef RAPIDJSON_COPY
#undef RAPIDJSON_TRANS
#undef RAPIDJSON_TAIL
}
static unsigned char GetRange(unsigned char c) {
@ -283,7 +283,7 @@ struct UTF16 {
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
os.Put((v & 0x3FF) | 0xDC00);
os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
}
}
@ -299,7 +299,7 @@ struct UTF16 {
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
PutUnsafe(os, (v & 0x3FF) | 0xDC00);
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
}
}
@ -384,7 +384,7 @@ struct UTF16BE : UTF16<CharType> {
static CharType Take(InputByteStream& is) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
c |= static_cast<uint8_t>(is.Take());
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
return static_cast<CharType>(c);
}
@ -620,28 +620,28 @@ struct AutoUTF {
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint);
}
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
(*f[os.GetType()])(os, codepoint);
}
template <typename InputStream>
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint);
}
template <typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os);
@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
@ -667,7 +667,7 @@ struct Transcoder {
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
return false;
@ -677,7 +677,7 @@ struct Transcoder {
//! Validate one Unicode codepoint from an encoded stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode.
}
};
@ -690,26 +690,26 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
template<typename Encoding>
struct Transcoder<Encoding, Encoding> {
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same
}
};
RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || defined(_MSC_VER)
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// 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
// 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_ERROR_EN_H_
@ -39,13 +39,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
@ -65,6 +65,108 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
}
}
//! Maps error code of validation into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param validateErrorCode Error code obtained from validator.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) {
case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'.");
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing.");
case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
//! Maps error code of schema document compilation into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param schemaErrorCode Error code obtained from compiling the schema document.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) {
switch (schemaErrorCode) {
case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document.");
case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer.");
case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string.");
case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'.");
case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document.");
case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical.");
case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider.");
case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema.");
case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'.");
case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized.");
case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported.");
case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document.");
case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
//! Maps error code of pointer parse into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param pointerParseErrorCode Error code obtained from pointer parse.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) {
switch (pointerParseErrorCode) {
case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'.");
case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape.");
case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment.");
case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
RAPIDJSON_NAMESPACE_END
#ifdef __clang__

View File

@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// 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
// 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_ERROR_ERROR_H_
@ -42,7 +42,7 @@ RAPIDJSON_DIAG_OFF(padded)
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_STRING
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
//! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[].
/*! \ingroup RAPIDJSON_ERRORS
By default this conversion macro does nothing.
On Windows, user can define this macro as \c _T(x) for supporting both
@ -104,6 +104,8 @@ enum ParseErrorCode {
\see GenericReader::Parse, GenericDocument::Parse
*/
struct ParseResult {
//!! Unspecified boolean type
typedef bool (ParseResult::*BooleanType)() const;
public:
//! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {}
@ -115,8 +117,8 @@ public:
//! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; }
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
operator bool() const { return !IsError(); }
//! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
//! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; }
@ -124,6 +126,10 @@ public:
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator!=(const ParseResult& that) const { return !(*this == that); }
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
//! Reset error code.
void Clear() { Set(kParseErrorNone); }
//! Update error code and offset.
@ -146,6 +152,130 @@ private:
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
///////////////////////////////////////////////////////////////////////////////
// ValidateErrorCode
//! Error codes when validating.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericSchemaValidator
*/
enum ValidateErrorCode {
kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set.
kValidateErrorNone = 0, //!< No error.
kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value.
kValidateErrorMaximum, //!< Number is greater than the 'maximum' value.
kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value.
kValidateErrorMinimum, //!< Number is less than the 'minimum' value.
kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value.
kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value.
kValidateErrorMinLength, //!< String is longer than the 'maxLength' value.
kValidateErrorPattern, //!< String does not match the 'pattern' regular expression.
kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value.
kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value.
kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true.
kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema.
kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value.
kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value.
kValidateErrorRequired, //!< Object is missing one or more members required by the schema.
kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema.
kValidateErrorPatternProperties, //!< See other errors.
kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values.
kValidateErrorType, //!< Property has a type that is not allowed by the schema.
kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'.
kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'.
kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'.
kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'.
kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing
kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading
};
//! Function pointer type of GetValidateError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetValidateError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
///////////////////////////////////////////////////////////////////////////////
// SchemaErrorCode
//! Error codes when validating.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericSchemaValidator
*/
enum SchemaErrorCode {
kSchemaErrorNone = 0, //!< No error.
kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document
kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer
kSchemaErrorRefInvalid, //!< $ref must not be an empty string
kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset
kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document
kSchemaErrorRefCyclical, //!< $ref is cyclical
kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider
kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema
kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties'
kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized
kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported
kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document
kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly'
};
//! Function pointer type of GetSchemaError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetSchemaError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode);
///////////////////////////////////////////////////////////////////////////////
// PointerParseErrorCode
//! Error code of JSON pointer parsing.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
*/
enum PointerParseErrorCode {
kPointerParseErrorNone = 0, //!< The parse is successful
kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
kPointerParseErrorInvalidEscape, //!< Invalid escape
kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
};
//! Function pointer type of GetPointerParseError().
/*! \ingroup RAPIDJSON_ERRORS
This is the prototype for \c GetPointerParseError_X(), where \c X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode());
\endcode
*/
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode);
RAPIDJSON_NAMESPACE_END
#ifdef __clang__

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -59,7 +59,7 @@ public:
// For encoding detection only.
const Ch* Peek4() const {
return (current_ + 4 <= bufferLast_) ? current_ : 0;
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
}
private:
@ -68,7 +68,7 @@ private:
++current_;
else if (!eof_) {
count_ += readCount_;
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_;

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -25,7 +25,7 @@ RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_NAMESPACE_BEGIN
//! Wrapper of C file stream for input using fread().
//! Wrapper of C file stream for output using fwrite().
/*!
\note implements Stream concept
*/
@ -62,7 +62,7 @@ public:
void Flush() {
if (current_ != buffer_) {
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
if (result < static_cast<size_t>(current_ - buffer_)) {
// failure deliberately ignored at this time
// added to avoid warn_unused_result build errors

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -102,7 +102,7 @@ class PrettyWriter;
// document.h
template <typename Encoding, typename Allocator>
struct GenericMember;
class GenericMember;
template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator;

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -17,9 +17,13 @@
#include "../rapidjson.h"
#if defined(_MSC_VER) && defined(_M_AMD64)
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128
#if !defined(_ARM64EC_)
#pragma intrinsic(_umul128)
#else
#pragma comment(lib,"softintrin")
#endif
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -37,7 +41,8 @@ public:
digits_[0] = u;
}
BigInteger(const char* decimals, size_t length) : count_(1) {
template<typename Ch>
BigInteger(const Ch* decimals, size_t length) : count_(1) {
RAPIDJSON_ASSERT(length > 0);
digits_[0] = 0;
size_t i = 0;
@ -133,7 +138,7 @@ public:
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
if (interShift == 0) {
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
count_ += offset;
}
else {
@ -221,7 +226,8 @@ public:
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
private:
void AppendDecimal64(const char* begin, const char* end) {
template<typename Ch>
void AppendDecimal64(const Ch* begin, const Ch* end) {
uint64_t u = ParseUint64(begin, end);
if (IsZero())
*this = u;
@ -236,11 +242,12 @@ private:
digits_[count_++] = digit;
}
static uint64_t ParseUint64(const char* begin, const char* end) {
template<typename Ch>
static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
uint64_t r = 0;
for (const char* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
r = r * 10u + static_cast<unsigned>(*p - '0');
for (const Ch* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
r = r * 10u + static_cast<unsigned>(*p - Ch('0'));
}
return r;
}
@ -252,7 +259,7 @@ private:
if (low < k)
(*outHigh)++;
return low;
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128;
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
p += k;

View File

@ -0,0 +1,71 @@
// 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_CLZLL_H_
#define RAPIDJSON_CLZLL_H_
#include "../rapidjson.h"
#if defined(_MSC_VER) && !defined(UNDER_CE)
#include <intrin.h>
#if defined(_WIN64)
#pragma intrinsic(_BitScanReverse64)
#else
#pragma intrinsic(_BitScanReverse)
#endif
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
inline uint32_t clzll(uint64_t x) {
// Passing 0 to __builtin_clzll is UB in GCC and results in an
// infinite loop in the software implementation.
RAPIDJSON_ASSERT(x != 0);
#if defined(_MSC_VER) && !defined(UNDER_CE)
unsigned long r = 0;
#if defined(_WIN64)
_BitScanReverse64(&r, x);
#else
// Scan the high 32 bits.
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
return 63 - (r + 32);
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
#endif // _WIN64
return 63 - r;
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
// __builtin_clzll wrapper
return static_cast<uint32_t>(__builtin_clzll(x));
#else
// naive version
uint32_t r = 0;
while (!(x & (static_cast<uint64_t>(1) << 63))) {
x <<= 1;
++r;
}
return r;
#endif // _MSC_VER
}
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
} // namespace internal
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_CLZLL_H_

View File

@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// 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
// 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.
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
@ -20,11 +20,16 @@
#define RAPIDJSON_DIYFP_H_
#include "../rapidjson.h"
#include "clzll.h"
#include <limits>
#if defined(_MSC_VER) && defined(_M_AMD64)
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
#include <intrin.h>
#pragma intrinsic(_BitScanReverse64)
#if !defined(_ARM64EC_)
#pragma intrinsic(_umul128)
#else
#pragma comment(lib,"softintrin")
#endif
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -56,7 +61,7 @@ struct DiyFp {
if (biased_e != 0) {
f = significand + kDpHiddenBit;
e = biased_e - kDpExponentBias;
}
}
else {
f = significand;
e = kDpMinExponent + 1;
@ -74,7 +79,7 @@ struct DiyFp {
if (l & (uint64_t(1) << 63)) // rounding
h++;
return DiyFp(h, e + rhs.e + 64);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128;
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
uint64_t h = static_cast<uint64_t>(p >> 64);
@ -99,21 +104,8 @@ struct DiyFp {
}
DiyFp Normalize() const {
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
return DiyFp(f << (63 - index), e - (63 - index));
#elif defined(__GNUC__) && __GNUC__ >= 4
int s = __builtin_clzll(f);
int s = static_cast<int>(clzll(f));
return DiyFp(f << s, e - s);
#else
DiyFp res = *this;
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
res.f <<= 1;
res.e--;
}
return res;
#endif
}
DiyFp NormalizeBoundary() const {
@ -141,7 +133,16 @@ struct DiyFp {
double d;
uint64_t u64;
}u;
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
if (e < kDpDenormalExponent) {
// Underflow.
return 0.0;
}
if (e >= kDpMaxExponent) {
// Overflow.
return std::numeric_limits<double>::infinity();
}
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
return u.d;
@ -220,9 +221,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
907, 933, 960, 986, 1013, 1039, 1066
};
RAPIDJSON_ASSERT(index < 87);
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
}
inline DiyFp GetCachedPower(int e, int* K) {
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
@ -238,10 +240,11 @@ inline DiyFp GetCachedPower(int e, int* K) {
}
inline DiyFp GetCachedPower10(int exp, int *outExp) {
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
*outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index);
}
RAPIDJSON_ASSERT(exp >= -348);
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
*outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index);
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
}
}
inline unsigned CountDecimalDigit32(uint32_t n) {
inline int CountDecimalDigit32(uint32_t n) {
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
if (n < 10) return 1;
if (n < 100) return 2;
@ -58,12 +58,16 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
}
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL,
1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL,
10000000000000000000ULL };
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1);
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0;
while (kappa > 0) {
@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
if (tmp <= delta) {
*K += kappa;
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
return;
}
}
@ -102,8 +106,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--;
if (p2 < delta) {
*K += kappa;
int index = -static_cast<int>(kappa);
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
int index = -kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
return;
}
}

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -48,13 +48,13 @@ public:
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
static unsigned EffectiveSignificandSize(int order) {
static int EffectiveSignificandSize(int order) {
if (order >= -1021)
return 53;
else if (order <= -1074)
return 0;
else
return static_cast<unsigned>(order) + 1074;
return order + 1074;
}
private:

View File

@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// 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
// 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_ITOA_
@ -37,12 +37,14 @@ inline const char* GetDigitsLut() {
}
inline char* u32toa(uint32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut();
if (value < 10000) {
const uint32_t d1 = (value / 100) << 1;
const uint32_t d2 = (value % 100) << 1;
if (value >= 1000)
*buffer++ = cDigitsLut[d1];
if (value >= 100)
@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
// value = bbbbcccc
const uint32_t b = value / 10000;
const uint32_t c = value % 10000;
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
if (value >= 100000)
*buffer++ = cDigitsLut[d2];
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
*buffer++ = cDigitsLut[d3 + 1];
*buffer++ = cDigitsLut[d4];
@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) {
}
else {
// value = aabbbbcccc in decimal
const uint32_t a = value / 100000000; // 1 to 42
value %= 100000000;
if (a >= 10) {
const unsigned i = a << 1;
*buffer++ = cDigitsLut[i];
@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
const uint32_t b = value / 10000; // 0 to 9999
const uint32_t c = value % 10000; // 0 to 9999
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
*buffer++ = cDigitsLut[d1];
*buffer++ = cDigitsLut[d1 + 1];
*buffer++ = cDigitsLut[d2];
@ -111,6 +113,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
}
inline char* i32toa(int32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
uint32_t u = static_cast<uint32_t>(value);
if (value < 0) {
*buffer++ = '-';
@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) {
}
inline char* u64toa(uint64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut();
const uint64_t kTen8 = 100000000;
const uint64_t kTen9 = kTen8 * 10;
@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
const uint64_t kTen14 = kTen8 * 1000000;
const uint64_t kTen15 = kTen8 * 10000000;
const uint64_t kTen16 = kTen8 * kTen8;
if (value < kTen8) {
uint32_t v = static_cast<uint32_t>(value);
if (v < 10000) {
const uint32_t d1 = (v / 100) << 1;
const uint32_t d2 = (v % 100) << 1;
if (v >= 1000)
*buffer++ = cDigitsLut[d1];
if (v >= 100)
@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
// value = bbbbcccc
const uint32_t b = v / 10000;
const uint32_t c = v % 10000;
const uint32_t d1 = (b / 100) << 1;
const uint32_t d2 = (b % 100) << 1;
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
if (value >= 100000)
*buffer++ = cDigitsLut[d2];
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
*buffer++ = cDigitsLut[d3 + 1];
*buffer++ = cDigitsLut[d4];
@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) {
else if (value < kTen16) {
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
const uint32_t b0 = v0 / 10000;
const uint32_t c0 = v0 % 10000;
const uint32_t d1 = (b0 / 100) << 1;
const uint32_t d2 = (b0 % 100) << 1;
const uint32_t d3 = (c0 / 100) << 1;
const uint32_t d4 = (c0 % 100) << 1;
const uint32_t b1 = v1 / 10000;
const uint32_t c1 = v1 % 10000;
const uint32_t d5 = (b1 / 100) << 1;
const uint32_t d6 = (b1 % 100) << 1;
const uint32_t d7 = (c1 / 100) << 1;
const uint32_t d8 = (c1 % 100) << 1;
@ -207,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d3 + 1];
if (value >= kTen9)
*buffer++ = cDigitsLut[d4];
if (value >= kTen8)
*buffer++ = cDigitsLut[d4 + 1];
*buffer++ = cDigitsLut[d4 + 1];
*buffer++ = cDigitsLut[d5];
*buffer++ = cDigitsLut[d5 + 1];
*buffer++ = cDigitsLut[d6];
@ -222,7 +225,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
else {
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
value %= kTen16;
if (a < 10)
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
else if (a < 100) {
@ -232,7 +235,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
}
else if (a < 1000) {
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
const uint32_t i = (a % 100) << 1;
*buffer++ = cDigitsLut[i];
*buffer++ = cDigitsLut[i + 1];
@ -245,28 +248,28 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[j];
*buffer++ = cDigitsLut[j + 1];
}
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
const uint32_t b0 = v0 / 10000;
const uint32_t c0 = v0 % 10000;
const uint32_t d1 = (b0 / 100) << 1;
const uint32_t d2 = (b0 % 100) << 1;
const uint32_t d3 = (c0 / 100) << 1;
const uint32_t d4 = (c0 % 100) << 1;
const uint32_t b1 = v1 / 10000;
const uint32_t c1 = v1 % 10000;
const uint32_t d5 = (b1 / 100) << 1;
const uint32_t d6 = (b1 % 100) << 1;
const uint32_t d7 = (c1 / 100) << 1;
const uint32_t d8 = (c1 % 100) << 1;
*buffer++ = cDigitsLut[d1];
*buffer++ = cDigitsLut[d1 + 1];
*buffer++ = cDigitsLut[d2];
@ -284,11 +287,12 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d8];
*buffer++ = cDigitsLut[d8 + 1];
}
return buffer;
}
inline char* i64toa(int64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0);
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
*buffer++ = '-';

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -21,7 +21,8 @@
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(6334)
#endif
@ -174,7 +175,11 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
RAPIDJSON_NAMESPACE_END
//@endcond
#if defined(__GNUC__) || defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -23,7 +23,9 @@
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#ifdef __GNUC__
@ -31,11 +33,6 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#ifndef RAPIDJSON_REGEX_VERBOSE
#define RAPIDJSON_REGEX_VERBOSE 0
#endif
@ -43,12 +40,40 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
///////////////////////////////////////////////////////////////////////////////
// DecodedStream
template <typename SourceStream, typename Encoding>
class DecodedStream {
public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; }
unsigned Take() {
unsigned c = codepoint_;
if (c) // No further decoding when '\0'
Decode();
return c;
}
private:
void Decode() {
if (!Encoding::Decode(ss_, &codepoint_))
codepoint_ = 0;
}
SourceStream& ss_;
unsigned codepoint_;
};
///////////////////////////////////////////////////////////////////////////////
// GenericRegex
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
static const SizeType kRegexInvalidRange = ~SizeType(0);
template <typename Encoding, typename Allocator>
class GenericRegexSearch;
//! Regular expression engine with subset of ECMAscript grammar.
/*!
Supported regular expression syntax:
@ -84,45 +109,29 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex {
public:
typedef Encoding EncodingType;
typedef typename Encoding::Ch Ch;
template <typename, typename> friend class GenericRegexSearch;
GenericRegex(const Ch* source, Allocator* allocator = 0) :
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
anchorBegin_(), anchorEnd_()
{
GenericStringStream<Encoding> ss(source);
DecodedStream<GenericStringStream<Encoding> > ds(ss);
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
Parse(ds);
}
~GenericRegex() {
Allocator::Free(stateSet_);
~GenericRegex()
{
RAPIDJSON_DELETE(ownAllocator_);
}
bool IsValid() const {
return root_ != kRegexInvalidState;
}
template <typename InputStream>
bool Match(InputStream& is) const {
return SearchWithAnchoring(is, true, true);
}
bool Match(const Ch* s) const {
GenericStringStream<Encoding> is(s);
return Match(is);
}
template <typename InputStream>
bool Search(InputStream& is) const {
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
}
bool Search(const Ch* s) const {
GenericStringStream<Encoding> is(s);
return Search(is);
}
private:
enum Operator {
kZeroOrOne,
@ -157,28 +166,6 @@ private:
SizeType minIndex;
};
template <typename SourceStream>
class DecodedStream {
public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; }
unsigned Take() {
unsigned c = codepoint_;
if (c) // No further decoding when '\0'
Decode();
return c;
}
private:
void Decode() {
if (!Encoding::Decode(ss_, &codepoint_))
codepoint_ = 0;
}
SourceStream& ss_;
unsigned codepoint_;
};
State& GetState(SizeType index) {
RAPIDJSON_ASSERT(index < stateCount_);
return states_.template Bottom<State>()[index];
@ -200,11 +187,10 @@ private:
}
template <typename InputStream>
void Parse(DecodedStream<InputStream>& ds) {
Allocator allocator;
Stack<Allocator> operandStack(&allocator, 256); // Frag
Stack<Allocator> operatorStack(&allocator, 256); // Operator
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
void Parse(DecodedStream<InputStream, Encoding>& ds) {
Stack<Allocator> operandStack(allocator_, 256); // Frag
Stack<Allocator> operatorStack(allocator_, 256); // Operator
Stack<Allocator> atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis)
*atomCountStack.template Push<unsigned>() = 0;
@ -301,6 +287,7 @@ private:
if (!CharacterEscape(ds, &codepoint))
return; // Unsupported escape character
// fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default: // Pattern character
PushOperand(operandStack, codepoint);
@ -327,14 +314,6 @@ private:
printf("\n");
#endif
}
// Preallocate buffer for SearchWithAnchoring()
RAPIDJSON_ASSERT(stateSet_ == 0);
if (stateCount_ > 0) {
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(stateCount_);
state1_.template Reserve<SizeType>(stateCount_);
}
}
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
@ -413,8 +392,7 @@ private:
}
return false;
default:
RAPIDJSON_ASSERT(op == kOneOrMore);
case kOneOrMore:
if (operandStack.GetSize() >= sizeof(Frag)) {
Frag e = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(kRegexInvalidState, e.start, 0);
@ -423,6 +401,10 @@ private:
return true;
}
return false;
default:
// syntax error (e.g. unclosed kLeftParenthesis)
return false;
}
}
@ -483,7 +465,7 @@ private:
}
template <typename InputStream>
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
unsigned r = 0;
if (ds.Peek() < '0' || ds.Peek() > '9')
return false;
@ -497,7 +479,7 @@ private:
}
template <typename InputStream>
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
bool isBegin = true;
bool negate = false;
int step = 0;
@ -535,6 +517,7 @@ private:
else if (!CharacterEscape(ds, &codepoint))
return false;
// fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default:
switch (step) {
@ -544,6 +527,7 @@ private:
break;
}
// fall through to step 0 for other characters
RAPIDJSON_DELIBERATE_FALLTHROUGH;
case 0:
{
@ -575,7 +559,7 @@ private:
}
template <typename InputStream>
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
unsigned codepoint;
switch (codepoint = ds.Take()) {
case '^':
@ -603,72 +587,8 @@ private:
}
}
template <typename InputStream>
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
RAPIDJSON_ASSERT(IsValid());
DecodedStream<InputStream> ds(is);
state0_.Clear();
Stack<Allocator> *current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize);
bool matched = AddState(*current, root_);
unsigned codepoint;
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
std::memset(stateSet_, 0, stateSetSize);
next->Clear();
matched = false;
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = GetState(*s);
if (sr.codepoint == codepoint ||
sr.codepoint == kAnyCharacterClass ||
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched)
return true;
}
if (!anchorBegin)
AddState(*next, root_);
}
internal::Swap(current, next);
}
return matched;
}
size_t GetStateSetSize() const {
return (stateCount_ + 31) / 32 * 4;
}
// Return whether the added states is a match state
bool AddState(Stack<Allocator>& l, SizeType index) const {
RAPIDJSON_ASSERT(index != kRegexInvalidState);
const State& s = GetState(index);
if (s.out1 != kRegexInvalidState) { // Split
bool matched = AddState(l, s.out);
return AddState(l, s.out1) || matched;
}
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
stateSet_[index >> 5] |= (1 << (index & 31));
*l.template PushUnsafe<SizeType>() = index;
}
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
}
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
while (rangeIndex != kRegexInvalidRange) {
const Range& r = GetRange(rangeIndex);
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
return yes;
rangeIndex = r.next;
}
return !yes;
}
Allocator* ownAllocator_;
Allocator* allocator_;
Stack<Allocator> states_;
Stack<Allocator> ranges_;
SizeType root_;
@ -678,23 +598,141 @@ private:
static const unsigned kInfinityQuantifier = ~0u;
// For SearchWithAnchoring()
uint32_t* stateSet_; // allocated by states_.GetAllocator()
mutable Stack<Allocator> state0_;
mutable Stack<Allocator> state1_;
bool anchorBegin_;
bool anchorEnd_;
};
template <typename RegexType, typename Allocator = CrtAllocator>
class GenericRegexSearch {
public:
typedef typename RegexType::EncodingType Encoding;
typedef typename Encoding::Ch Ch;
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
regex_(regex), allocator_(allocator), ownAllocator_(0),
state0_(allocator, 0), state1_(allocator, 0), stateSet_()
{
RAPIDJSON_ASSERT(regex_.IsValid());
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
stateSet_ = static_cast<uint32_t*>(allocator_->Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(regex_.stateCount_);
state1_.template Reserve<SizeType>(regex_.stateCount_);
}
~GenericRegexSearch() {
Allocator::Free(stateSet_);
RAPIDJSON_DELETE(ownAllocator_);
}
template <typename InputStream>
bool Match(InputStream& is) {
return SearchWithAnchoring(is, true, true);
}
bool Match(const Ch* s) {
GenericStringStream<Encoding> is(s);
return Match(is);
}
template <typename InputStream>
bool Search(InputStream& is) {
return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
}
bool Search(const Ch* s) {
GenericStringStream<Encoding> is(s);
return Search(is);
}
private:
typedef typename RegexType::State State;
typedef typename RegexType::Range Range;
template <typename InputStream>
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
DecodedStream<InputStream, Encoding> ds(is);
state0_.Clear();
Stack<Allocator> *current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize);
bool matched = AddState(*current, regex_.root_);
unsigned codepoint;
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
std::memset(stateSet_, 0, stateSetSize);
next->Clear();
matched = false;
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = regex_.GetState(*s);
if (sr.codepoint == codepoint ||
sr.codepoint == RegexType::kAnyCharacterClass ||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched)
return true;
}
if (!anchorBegin)
AddState(*next, regex_.root_);
}
internal::Swap(current, next);
}
return matched;
}
size_t GetStateSetSize() const {
return (regex_.stateCount_ + 31) / 32 * 4;
}
// Return whether the added states is a match state
bool AddState(Stack<Allocator>& l, SizeType index) {
RAPIDJSON_ASSERT(index != kRegexInvalidState);
const State& s = regex_.GetState(index);
if (s.out1 != kRegexInvalidState) { // Split
bool matched = AddState(l, s.out);
return AddState(l, s.out1) || matched;
}
else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
stateSet_[index >> 5] |= (1u << (index & 31));
*l.template PushUnsafe<SizeType>() = index;
}
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
}
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
while (rangeIndex != kRegexInvalidRange) {
const Range& r = regex_.GetRange(rangeIndex);
if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
return yes;
rangeIndex = r.next;
}
return !yes;
}
const RegexType& regex_;
Allocator* allocator_;
Allocator* ownAllocator_;
Stack<Allocator> state0_;
Stack<Allocator> state1_;
uint32_t* stateSet_;
};
typedef GenericRegex<UTF8<> > Regex;
typedef GenericRegexSearch<Regex> RegexSearch;
} // namespace internal
RAPIDJSON_NAMESPACE_END
#ifdef __clang__
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
#if defined(__clang__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -17,6 +17,7 @@
#include "../allocators.h"
#include "swap.h"
#include <cstddef>
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
@ -100,7 +101,7 @@ public:
void ShrinkToFit() {
if (Empty()) {
// If the stack is empty, completely deallocate the memory.
Allocator::Free(stack_);
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
stack_ = 0;
stackTop_ = 0;
stackEnd_ = 0;
@ -114,7 +115,7 @@ public:
template<typename T>
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
// Expand the stack if needed
if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
Expand<T>(count);
}
@ -126,7 +127,8 @@ public:
template<typename T>
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
RAPIDJSON_ASSERT(stackTop_);
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
T* ret = reinterpret_cast<T*>(stackTop_);
stackTop_ += sizeof(T) * count;
return ret;
@ -183,7 +185,7 @@ private:
size_t newCapacity;
if (stack_ == 0) {
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
newCapacity = initialCapacity_;
} else {
newCapacity = GetCapacity();

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -16,6 +16,7 @@
#define RAPIDJSON_INTERNAL_STRFUNC_H_
#include "../stream.h"
#include <cwchar>
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -28,14 +29,41 @@ namespace internal {
*/
template <typename Ch>
inline SizeType StrLen(const Ch* s) {
RAPIDJSON_ASSERT(s != 0);
const Ch* p = s;
while (*p) ++p;
return SizeType(p - s);
}
template <>
inline SizeType StrLen(const char* s) {
return SizeType(std::strlen(s));
}
template <>
inline SizeType StrLen(const wchar_t* s) {
return SizeType(std::wcslen(s));
}
//! Custom strcmpn() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s1 Null-terminated input string.
\param s2 Null-terminated input string.
\return 0 if equal
*/
template<typename Ch>
inline int StrCmp(const Ch* s1, const Ch* s2) {
RAPIDJSON_ASSERT(s1 != 0);
RAPIDJSON_ASSERT(s2 != 0);
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
}
//! Returns number of code points in a encoded string.
template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
RAPIDJSON_ASSERT(s != 0);
RAPIDJSON_ASSERT(outCount != 0);
GenericStringStream<Encoding> is(s);
const typename Encoding::Ch* end = s + length;
SizeType count = 0;

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -19,6 +19,8 @@
#include "biginteger.h"
#include "diyfp.h"
#include "pow10.h"
#include <climits>
#include <limits>
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -126,46 +128,47 @@ inline bool StrtodFast(double d, int p, double* result) {
}
// Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
template<typename Ch>
inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
uint64_t significand = 0;
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < length; i++) {
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < dLen; i++) {
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] >= Ch('5')))
break;
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
}
if (i < length && decimals[i] >= '5') // Rounding
if (i < dLen && decimals[i] >= Ch('5')) // Rounding
significand++;
size_t remaining = length - i;
const unsigned kUlpShift = 3;
const unsigned kUlp = 1 << kUlpShift;
int remaining = dLen - i;
const int kUlpShift = 3;
const int kUlp = 1 << kUlpShift;
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
DiyFp v(significand, 0);
v = v.Normalize();
error <<= -v.e;
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
dExp += remaining;
int actualExp;
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
if (actualExp != dExp) {
static const DiyFp kPow10[] = {
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
};
int adjustment = dExp - actualExp - 1;
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment];
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
int adjustment = dExp - actualExp;
RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
v = v * kPow10[adjustment - 1];
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
error += kUlp / 2;
}
@ -177,17 +180,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
v = v.Normalize();
error <<= oldExp - v.e;
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
unsigned precisionSize = 64 - effectiveSignificandSize;
const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
int precisionSize = 64 - effectiveSignificandSize;
if (precisionSize + kUlpShift >= 64) {
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
int scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp;
v.e += scaleExp;
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
error = (error >> scaleExp) + 1 + kUlp;
precisionSize -= scaleExp;
}
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
@ -203,9 +206,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
}
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
const BigInteger dInt(decimals, length);
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
template<typename Ch>
inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
RAPIDJSON_ASSERT(dLen >= 0);
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
Double a(approx);
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
if (cmp < 0)
@ -221,46 +225,66 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
return a.NextPositiveDouble();
}
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
template<typename Ch>
inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
RAPIDJSON_ASSERT(d >= 0.0);
RAPIDJSON_ASSERT(length >= 1);
double result;
double result = 0.0;
if (StrtodFast(d, p, &result))
return result;
RAPIDJSON_ASSERT(length <= INT_MAX);
int dLen = static_cast<int>(length);
RAPIDJSON_ASSERT(length >= decimalPosition);
RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
int dExpAdjust = static_cast<int>(length - decimalPosition);
RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
int dExp = exp - dExpAdjust;
// Make sure length+dExp does not overflow
RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
// Trim leading zeros
while (*decimals == '0' && length > 1) {
length--;
while (dLen > 0 && *decimals == '0') {
dLen--;
decimals++;
decimalPosition--;
}
// Trim trailing zeros
while (decimals[length - 1] == '0' && length > 1) {
length--;
decimalPosition--;
exp++;
while (dLen > 0 && decimals[dLen - 1] == '0') {
dLen--;
dExp++;
}
if (dLen == 0) { // Buffer only contains zeros.
return 0.0;
}
// Trim right-most digits
const int kMaxDecimalDigit = 780;
if (static_cast<int>(length) > kMaxDecimalDigit) {
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
exp += delta;
decimalPosition -= static_cast<unsigned>(delta);
length = kMaxDecimalDigit;
const int kMaxDecimalDigit = 767 + 1;
if (dLen > kMaxDecimalDigit) {
dExp += dLen - kMaxDecimalDigit;
dLen = kMaxDecimalDigit;
}
// If too small, underflow to zero
if (int(length) + exp < -324)
// If too small, underflow to zero.
// Any x <= 10^-324 is interpreted as zero.
if (dLen + dExp <= -324)
return 0.0;
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
// If too large, overflow to infinity.
// Any x >= 10^309 is interpreted as +infinity.
if (dLen + dExp > 309)
return std::numeric_limits<double>::infinity();
if (StrtodDiyFp(decimals, dLen, dExp, &result))
return result;
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
return StrtodBigInteger(result, decimals, dLen, dExp);
}
} // namespace internal

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -17,13 +17,12 @@
#include "stream.h"
#include <iosfwd>
#include <ios>
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
#endif
#ifdef _MSC_VER
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
#endif
@ -50,57 +49,71 @@ template <typename StreamType>
class BasicIStreamWrapper {
public:
typedef typename StreamType::char_type Ch;
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
Ch Peek() const {
typename StreamType::int_type c = stream_.peek();
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
//! Constructor.
/*!
\param stream stream opened for read.
*/
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
Read();
}
Ch Take() {
typename StreamType::int_type c = stream_.get();
if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
count_++;
return static_cast<Ch>(c);
}
else
return '\0';
//! Constructor.
/*!
\param stream stream opened for read.
\param buffer user-supplied buffer.
\param bufferSize size of buffer in bytes. Must >=4 bytes.
*/
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
RAPIDJSON_ASSERT(bufferSize >= 4);
Read();
}
// tellg() may return -1 when failed. So we count by ourself.
size_t Tell() const { return count_; }
Ch Peek() const { return *current_; }
Ch Take() { Ch c = *current_; Read(); return c; }
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
// For encoding detection only.
const Ch* Peek4() const {
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
int i;
bool hasError = false;
for (i = 0; i < 4; ++i) {
typename StreamType::int_type c = stream_.get();
if (c == StreamType::traits_type::eof()) {
hasError = true;
stream_.clear();
break;
}
peekBuffer_[i] = static_cast<Ch>(c);
}
for (--i; i >= 0; --i)
stream_.putback(peekBuffer_[i]);
return !hasError ? peekBuffer_ : 0;
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
}
private:
BasicIStreamWrapper();
BasicIStreamWrapper(const BasicIStreamWrapper&);
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
StreamType& stream_;
size_t count_; //!< Number of characters read. Note:
mutable Ch peekBuffer_[4];
void Read() {
if (current_ < bufferLast_)
++current_;
else if (!eof_) {
count_ += readCount_;
readCount_ = bufferSize_;
bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_;
if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
readCount_ = static_cast<size_t>(stream_.gcount());
*(bufferLast_ = buffer_ + readCount_) = '\0';
eof_ = true;
}
}
}
StreamType &stream_;
Ch peekBuffer_[4], *buffer_;
size_t bufferSize_;
Ch *bufferLast_;
Ch *current_;
size_t readCount_;
size_t count_; //!< Number of characters read
bool eof_;
};
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -16,35 +16,28 @@
#define RAPIDJSON_POINTER_H_
#include "document.h"
#include "uri.h"
#include "internal/itoa.h"
#include "error/error.h" // PointerParseErrorCode
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch-enum)
#endif
#ifdef _MSC_VER
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#if defined(RAPIDJSON_CPLUSPLUS) && RAPIDJSON_CPLUSPLUS >= 201703L
#define RAPIDJSON_IF_CONSTEXPR if constexpr
#else
#define RAPIDJSON_IF_CONSTEXPR if
#endif
RAPIDJSON_NAMESPACE_BEGIN
static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
//! Error code of parsing.
/*! \ingroup RAPIDJSON_ERRORS
\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
*/
enum PointerParseErrorCode {
kPointerParseErrorNone = 0, //!< The parse is successful
kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
kPointerParseErrorInvalidEscape, //!< Invalid escape
kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
};
///////////////////////////////////////////////////////////////////////////////
// GenericPointer
@ -70,10 +63,10 @@ enum PointerParseErrorCode {
supplied tokens eliminates these.
GenericPointer depends on GenericDocument and GenericValue.
\tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
\tparam Allocator The allocator type for allocating memory for internal representation.
\note GenericPointer uses same encoding of ValueType.
However, Allocator of GenericPointer is independent of Allocator of Value.
*/
@ -82,8 +75,10 @@ class GenericPointer {
public:
typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
typedef typename ValueType::Ch Ch; //!< Character type from Value
typedef GenericUri<ValueType, Allocator> UriType;
//! A token is the basic units of internal representation.
//! A token is the basic units of internal representation.
/*!
A JSON pointer string representation "/foo/123" is parsed to two tokens:
"foo" and 123. 123 will be represented in both numeric form and string form.
@ -165,7 +160,12 @@ public:
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
//! Copy constructor.
GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
//! Copy constructor.
GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
@ -197,6 +197,36 @@ public:
return *this;
}
//! Swap the content of this pointer with an other.
/*!
\param other The pointer to swap with.
\note Constant complexity.
*/
GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
internal::Swap(allocator_, other.allocator_);
internal::Swap(ownAllocator_, other.ownAllocator_);
internal::Swap(nameBuffer_, other.nameBuffer_);
internal::Swap(tokens_, other.tokens_);
internal::Swap(tokenCount_, other.tokenCount_);
internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
internal::Swap(parseErrorCode_, other.parseErrorCode_);
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.pointer, b.pointer);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//@}
//!@name Append token
@ -240,7 +270,7 @@ public:
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
Append(T* name, Allocator* allocator = 0) const {
return Append(name, StrLen(name), allocator);
return Append(name, internal::StrLen(name), allocator);
}
#if RAPIDJSON_HAS_STDSTRING
@ -267,14 +297,14 @@ public:
SizeType length = static_cast<SizeType>(end - buffer);
buffer[length] = '\0';
if (sizeof(Ch) == 1) {
RAPIDJSON_IF_CONSTEXPR (sizeof(Ch) == 1) {
Token token = { reinterpret_cast<Ch*>(buffer), length, index };
return Append(token, allocator);
}
else {
Ch name[21];
for (size_t i = 0; i <= length; i++)
name[i] = buffer[i];
name[i] = static_cast<Ch>(buffer[i]);
Token token = { name, length, index };
return Append(token, allocator);
}
@ -353,6 +383,33 @@ public:
*/
bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
//! Less than operator.
/*!
\note Invalid pointers are always greater than valid ones.
*/
bool operator<(const GenericPointer& rhs) const {
if (!IsValid())
return false;
if (!rhs.IsValid())
return true;
if (tokenCount_ != rhs.tokenCount_)
return tokenCount_ < rhs.tokenCount_;
for (size_t i = 0; i < tokenCount_; i++) {
if (tokens_[i].index != rhs.tokens_[i].index)
return tokens_[i].index < rhs.tokens_[i].index;
if (tokens_[i].length != rhs.tokens_[i].length)
return tokens_[i].length < rhs.tokens_[i].length;
if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
return cmp < 0;
}
return false;
}
//@}
//!@name Stringify
@ -428,10 +485,11 @@ public:
v = &((*v)[t->index]);
}
else {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) {
v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
m = v->MemberEnd();
v = &(--m)->value; // Assumes AddMember() appends at the end
exist = false;
}
else
@ -459,6 +517,70 @@ public:
//@}
//!@name Compute URI
//@{
//! Compute the in-scope URI for a subtree.
// For use with JSON pointers into JSON schema documents.
/*!
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
\param rootUri Root URI
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
\param allocator Allocator for Uris
\return Uri if it can be resolved. Otherwise null.
\note
There are only 3 situations when a URI cannot be resolved:
1. A value in the path is not an array nor object.
2. An object value does not contain the token.
3. A token is out of range of an array value.
Use unresolvedTokenIndex to retrieve the token index.
*/
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
static const Ch kIdString[] = { 'i', 'd', '\0' };
static const ValueType kIdValue(kIdString, 2);
UriType base = UriType(rootUri, allocator);
RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root;
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
switch (v->GetType()) {
case kObjectType:
{
// See if we have an id, and if so resolve with the current base
typename ValueType::MemberIterator m = v->FindMember(kIdValue);
if (m != v->MemberEnd() && (m->value).IsString()) {
UriType here = UriType(m->value, allocator).Resolve(base, allocator);
base = here;
}
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd())
break;
v = &m->value;
}
continue;
case kArrayType:
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
break;
v = &((*v)[t->index]);
continue;
default:
break;
}
// Error: unresolved token
if (unresolvedTokenIndex)
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
return UriType(allocator);
}
return base;
}
UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
}
//!@name Query value
//@{
@ -483,7 +605,7 @@ public:
switch (v->GetType()) {
case kObjectType:
{
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd())
break;
v = &m->value;
@ -532,14 +654,14 @@ public:
*/
ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
}
//! Query a value in a subtree with default null-terminated string.
ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator);
}
@ -547,7 +669,7 @@ public:
//! Query a value in a subtree with default std::basic_string.
ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist;
Value& v = Create(root, allocator, &alreadyExist);
ValueType& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator);
}
#endif
@ -573,7 +695,7 @@ public:
ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
return GetWithDefault(document, defaultValue, document.GetAllocator());
}
#if RAPIDJSON_HAS_STDSTRING
//! Query a value in a document with default std::basic_string.
template <typename stackAllocator>
@ -719,7 +841,7 @@ public:
switch (v->GetType()) {
case kObjectType:
{
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd())
return false;
v = &m->value;
@ -758,7 +880,7 @@ private:
*/
Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
if (!allocator_) // allocator is independently owned.
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
@ -774,10 +896,16 @@ private:
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
}
// Adjust pointers to name buffer
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
t->name += diff;
// The names of each token point to a string in the nameBuffer_. The
// previous memcpy copied over string pointers into the rhs.nameBuffer_,
// but they should point to the strings in the new nameBuffer_.
for (size_t i = 0; i < rhs.tokenCount_; ++i) {
// The offset between the string address and the name buffer should
// still be constant, so we can just get this offset and set each new
// token name according the new buffer start + the known offset.
std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_;
tokens_[i].name = nameBuffer_ + name_offset;
}
return nameBuffer_ + nameBufferSize;
}
@ -806,7 +934,7 @@ private:
// Create own allocator if user did not supply.
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
// Count number of '/' as tokenCount
tokenCount_ = 0;
@ -867,7 +995,7 @@ private:
}
i++;
// Escaping "~0" -> '~', "~1" -> '/'
if (c == '~') {
if (i < length) {
@ -1029,8 +1157,8 @@ private:
unsigned char u = static_cast<unsigned char>(c);
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
os_.Put('%');
os_.Put(hexDigits[u >> 4]);
os_.Put(hexDigits[u & 15]);
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
}
private:
OutputStream& os_;
@ -1347,11 +1475,7 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
RAPIDJSON_NAMESPACE_END
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
#if defined(__clang__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,6 +1,6 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
@ -22,6 +22,11 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
RAPIDJSON_NAMESPACE_BEGIN
//! Combination of PrettyWriter format flags.
@ -34,7 +39,7 @@ enum PrettyFormatOptions {
//! Writer with indentation and spacing.
/*!
\tparam OutputStream Type of ouptut os.
\tparam OutputStream Type of output os.
\tparam SourceEncoding Encoding of source string.
\tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack.
@ -42,7 +47,7 @@ enum PrettyFormatOptions {
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
typedef typename Base::Ch Ch;
//! Constructor
@ -55,7 +60,12 @@ public:
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
PrettyWriter(PrettyWriter&& rhs) :
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
#endif
//! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
@ -82,24 +92,26 @@ public:
*/
//@{
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); }
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); }
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
RAPIDJSON_ASSERT(str != 0);
(void)copy;
PrettyPrefix(kNumberType);
return Base::WriteString(str, length);
return Base::EndValue(Base::WriteString(str, length));
}
bool String(const Ch* str, SizeType length, bool copy = false) {
RAPIDJSON_ASSERT(str != 0);
(void)copy;
PrettyPrefix(kStringType);
return Base::WriteString(str, length);
return Base::EndValue(Base::WriteString(str, length));
}
#if RAPIDJSON_HAS_STDSTRING
@ -124,19 +136,21 @@ public:
bool EndObject(SizeType memberCount = 0) {
(void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty) {
Base::os_->Put('\n');
WriteIndent();
}
bool ret = Base::WriteEndObject();
bool ret = Base::EndValue(Base::WriteEndObject());
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
Base::os_->Flush();
Base::Flush();
return true;
}
@ -156,11 +170,11 @@ public:
Base::os_->Put('\n');
WriteIndent();
}
bool ret = Base::WriteEndArray();
bool ret = Base::EndValue(Base::WriteEndArray());
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
Base::os_->Flush();
Base::Flush();
return true;
}
@ -184,7 +198,11 @@ public:
\param type Type of the root of json.
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
*/
bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
bool RawValue(const Ch* json, size_t length, Type type) {
RAPIDJSON_ASSERT(json != 0);
PrettyPrefix(type);
return Base::EndValue(Base::WriteRawValue(json, length));
}
protected:
void PrettyPrefix(Type type) {
@ -233,7 +251,7 @@ protected:
void WriteIndent() {
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
}
Ch indentChar_;
@ -248,6 +266,10 @@ private:
RAPIDJSON_NAMESPACE_END
#if defined(__clang__)
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif

View File

@ -1,15 +1,15 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// 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
// 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_RAPIDJSON_H_
@ -17,7 +17,7 @@
/*!\file rapidjson.h
\brief common definitions and configuration
\see RAPIDJSON_CONFIG
*/
@ -26,7 +26,7 @@
Some RapidJSON features are configurable to adapt the library to a wide
variety of platforms, environments and usage scenarios. Most of the
features can be configured in terms of overriden or predefined
features can be configured in terms of overridden or predefined
preprocessor macros at compile-time.
Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
@ -49,6 +49,11 @@
// token stringification
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
#define RAPIDJSON_DO_STRINGIFY(x) #x
// token concatenation
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
//!@endcond
/*! \def RAPIDJSON_MAJOR_VERSION
@ -119,6 +124,19 @@
#define RAPIDJSON_NAMESPACE_END }
#endif
///////////////////////////////////////////////////////////////////////////////
// __cplusplus macro
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#if defined(_MSC_VER)
#define RAPIDJSON_CPLUSPLUS _MSVC_LANG
#else
#define RAPIDJSON_CPLUSPLUS __cplusplus
#endif
//!@endcond
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_HAS_STDSTRING
@ -144,6 +162,24 @@
#include <string>
#endif // RAPIDJSON_HAS_STDSTRING
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_USE_MEMBERSMAP
/*! \def RAPIDJSON_USE_MEMBERSMAP
\ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for object members handling in a \c std::multimap
By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
members are stored in a \c std::multimap for faster lookup and deletion times, a
trade off with a slightly slower insertion time and a small object allocat(or)ed
memory overhead.
\hideinitializer
*/
#ifndef RAPIDJSON_USE_MEMBERSMAP
#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_NO_INT64DEFINE
@ -159,7 +195,7 @@
*/
#ifndef RAPIDJSON_NO_INT64DEFINE
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
#include "msinttypes/stdint.h"
#include "msinttypes/inttypes.h"
#else
@ -214,7 +250,7 @@
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif // __BYTE_ORDER__
// Detect with GLIBC's endian.h
# elif defined(__GLIBC__)
@ -224,7 +260,7 @@
# elif (__BYTE_ORDER == __BIG_ENDIAN)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif // __GLIBC__
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
@ -232,16 +268,16 @@
# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
// Detect with architecture macros
# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(_MSC_VER) && defined(_M_ARM)
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
# define RAPIDJSON_ENDIAN
# else
# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
# endif
#endif // RAPIDJSON_ENDIAN
@ -264,16 +300,11 @@
/*! \ingroup RAPIDJSON_CONFIG
\param x pointer to align
Some machines require strict data alignment. Currently the default uses 4 bytes
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
Some machines require strict data alignment. The default is 8 bytes.
User can customize by defining the RAPIDJSON_ALIGN function macro.
*/
#ifndef RAPIDJSON_ALIGN
#if RAPIDJSON_64BIT == 1
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
#else
#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
#endif
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
#endif
///////////////////////////////////////////////////////////////////////////////
@ -320,17 +351,17 @@
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
/*! \def RAPIDJSON_SIMD
\ingroup RAPIDJSON_CONFIG
\brief Enable SSE2/SSE4.2 optimization.
\brief Enable SSE2/SSE4.2/Neon optimization.
RapidJSON supports optimized implementations for some parsing operations
based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
processors.
based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
or ARM compatible processors.
To enable these optimizations, two different symbols can be defined;
To enable these optimizations, three different symbols can be defined;
\code
// Enable SSE2 optimization.
#define RAPIDJSON_SSE2
@ -339,13 +370,17 @@
#define RAPIDJSON_SSE42
\endcode
\c RAPIDJSON_SSE42 takes precedence, if both are defined.
// Enable ARM Neon optimization.
#define RAPIDJSON_NEON
\endcode
\c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
If any of these symbols is defined, RapidJSON defines the macro
\c RAPIDJSON_SIMD to indicate the availability of the optimized code.
*/
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
|| defined(RAPIDJSON_DOXYGEN_RUNNING)
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_SIMD
#endif
@ -405,7 +440,15 @@ RAPIDJSON_NAMESPACE_END
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_STATIC_ASSERT
// Adopt from boost
// Prefer C++11 static_assert, if available
#ifndef RAPIDJSON_STATIC_ASSERT
#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
#define RAPIDJSON_STATIC_ASSERT(x) \
static_assert(x, RAPIDJSON_STRINGIFY(x))
#endif // C++11
#endif // RAPIDJSON_STATIC_ASSERT
// Adopt C++03 implementation from boost
#ifndef RAPIDJSON_STATIC_ASSERT
#ifndef __clang__
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
@ -413,14 +456,10 @@ RAPIDJSON_NAMESPACE_END
RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template<int x> struct StaticAssertTest {};
template <size_t x> struct StaticAssertTest {};
RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
#if defined(__GNUC__)
#if defined(__GNUC__) || defined(__clang__)
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
#else
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
@ -438,7 +477,7 @@ RAPIDJSON_NAMESPACE_END
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif
#endif // RAPIDJSON_STATIC_ASSERT
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
@ -474,7 +513,7 @@ RAPIDJSON_NAMESPACE_END
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
#define RAPIDJSON_MULTILINEMACRO_END \
} while((void)0, 0)
@ -482,6 +521,12 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_VERSION_CODE(x,y,z) \
(((x)*100000) + ((y)*100) + (z))
#if defined(__has_builtin)
#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
#else
#define RAPIDJSON_HAS_BUILTIN(x) 0
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
@ -527,16 +572,23 @@ RAPIDJSON_NAMESPACE_END
///////////////////////////////////////////////////////////////////////////////
// C++11 features
#ifndef RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
#endif
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__)
#if RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#elif defined(__clang__)
#if __has_feature(cxx_rvalue_references) && \
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1600)
(defined(_MSC_VER) && _MSC_VER >= 1600) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else
@ -544,46 +596,120 @@ RAPIDJSON_NAMESPACE_END
#endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#include <utility> // std::move
#endif
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
#if defined(__clang__)
#if RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#elif defined(__clang__)
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1900) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#else
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
#endif
#endif
#ifndef RAPIDJSON_NOEXCEPT
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
#define RAPIDJSON_NOEXCEPT noexcept
#else
#define RAPIDJSON_NOEXCEPT /* noexcept */
#define RAPIDJSON_NOEXCEPT throw()
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
#endif
// no automatic detection, yet
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
#if (defined(_MSC_VER) && _MSC_VER >= 1700)
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1
#else
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif
#endif
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
#if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1700)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1700) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
#else
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
#endif
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
///////////////////////////////////////////////////////////////////////////////
// C++17 features
#ifndef RAPIDJSON_HAS_CXX17
#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L)
#endif
#if RAPIDJSON_HAS_CXX17
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
#elif defined(__has_cpp_attribute)
# if __has_cpp_attribute(clang::fallthrough)
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
# elif __has_cpp_attribute(fallthrough)
# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
# else
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
# endif
#else
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
#endif
//!@endcond
//! Assertion (in non-throwing contexts).
/*! \ingroup RAPIDJSON_CONFIG
Some functions provide a \c noexcept guarantee, if the compiler supports it.
In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
throw an exception. This macro adds a separate customization point for
such cases.
Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is
supported, and to \ref RAPIDJSON_ASSERT otherwise.
*/
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_NOEXCEPT_ASSERT
#ifndef RAPIDJSON_NOEXCEPT_ASSERT
#ifdef RAPIDJSON_ASSERT_THROWS
#include <cassert>
#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
#else
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
#endif // RAPIDJSON_ASSERT_THROWS
#endif // RAPIDJSON_NOEXCEPT_ASSERT
///////////////////////////////////////////////////////////////////////////////
// malloc/realloc/free
#ifndef RAPIDJSON_MALLOC
///! customization point for global \c malloc
#define RAPIDJSON_MALLOC(size) std::malloc(size)
#endif
#ifndef RAPIDJSON_REALLOC
///! customization point for global \c realloc
#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
#endif
#ifndef RAPIDJSON_FREE
///! customization point for global \c free
#define RAPIDJSON_FREE(ptr) std::free(ptr)
#endif
///////////////////////////////////////////////////////////////////////////////
// new/delete
#ifndef RAPIDJSON_NEW
///! customization point for global \c new
#define RAPIDJSON_NEW(x) new x
#define RAPIDJSON_NEW(TypeName) new TypeName
#endif
#ifndef RAPIDJSON_DELETE
///! customization point for global \c delete
@ -605,7 +731,7 @@ enum Type {
kFalseType = 1, //!< false
kTrueType = 2, //!< true
kObjectType = 3, //!< object
kArrayType = 4, //!< array
kArrayType = 4, //!< array
kStringType = 5, //!< string
kNumberType = 6 //!< number
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More