Merge branch 'master' into json-pointer
Conflicts: test/unittest/CMakeLists.txt
This commit is contained in:
commit
7fc716006f
11
.travis.yml
11
.travis.yml
@ -18,8 +18,10 @@ env:
|
|||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -qq cmake doxygen valgrind
|
- sudo apt-get install -qq cmake valgrind
|
||||||
|
- sudo apt-get --no-install-recommends install doxygen # Don't install LaTeX stuffs
|
||||||
- if [ "$ARCH" = "x86" ]; then sudo apt-get install -qq g++-multilib libc6-dbg:i386; fi
|
- if [ "$ARCH" = "x86" ]; then sudo apt-get install -qq g++-multilib libc6-dbg:i386; fi
|
||||||
|
- if [ "$CC" = "gcc" ] && [ "$CONF" = "debug" ]; then sudo pip install cpp-coveralls; export GCOV_FLAGS='--coverage'; fi
|
||||||
|
|
||||||
install: true
|
install: true
|
||||||
|
|
||||||
@ -34,7 +36,9 @@ before_script:
|
|||||||
-DRAPIDJSON_HAS_STDSTRING=ON
|
-DRAPIDJSON_HAS_STDSTRING=ON
|
||||||
-DCMAKE_VERBOSE_MAKEFILE=ON
|
-DCMAKE_VERBOSE_MAKEFILE=ON
|
||||||
-DCMAKE_BUILD_TYPE=$CONF
|
-DCMAKE_BUILD_TYPE=$CONF
|
||||||
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS" ..)
|
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS"
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS
|
||||||
|
..)
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cd build
|
- cd build
|
||||||
@ -42,3 +46,6 @@ script:
|
|||||||
- make examples
|
- make examples
|
||||||
- ctest -V `[ "$CONF" = "release" ] || echo "-E perftest"`
|
- ctest -V `[ "$CONF" = "release" ] || echo "-E perftest"`
|
||||||
- make travis_doc
|
- make travis_doc
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- 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
|
||||||
|
65
CHANGELOG.md
Normal file
65
CHANGELOG.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Change Log
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
* Include rapidjson.h for all internal/error headers.
|
||||||
|
|
||||||
|
## [1.0.1] - 2015-04-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314).
|
||||||
|
* Visual C++ 32-bit compilation error in `diyfp.h` (#317).
|
||||||
|
|
||||||
|
## [1.0.0] - 2015-04-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage.
|
||||||
|
* Version macros (#311)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* A bug in trimming long number sequence (4824f12efbf01af72b8cb6fc96fae7b097b73015).
|
||||||
|
* Double quote in unicode escape (#288).
|
||||||
|
* Negative zero roundtrip (double only) (#289).
|
||||||
|
* Standardize behavior of `memcpy()` and `malloc()` (0c5c1538dcfc7f160e5a4aa208ddf092c787be5a, #305, 0e8bbe5e3ef375e7f052f556878be0bd79e9062d).
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb).
|
||||||
|
|
||||||
|
## 1.0-beta - 2015-04-8
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* RFC 7159 (#101)
|
||||||
|
* Optional Iterative Parser (#76)
|
||||||
|
* Deep-copy values (#20)
|
||||||
|
* Error code and message (#27)
|
||||||
|
* ASCII Encoding (#70)
|
||||||
|
* `kParseStopWhenDoneFlag` (#83)
|
||||||
|
* `kParseFullPrecisionFlag` (881c91d696f06b7f302af6d04ec14dd08db66ceb)
|
||||||
|
* Add `Key()` to handler concept (#134)
|
||||||
|
* C++11 compatibility and support (#128)
|
||||||
|
* Optimized number-to-string and vice versa conversions (#137, #80)
|
||||||
|
* Short-String Optimization (#131)
|
||||||
|
* Local stream optimization by traits (#32)
|
||||||
|
* Travis & Appveyor Continuous Integration, with Valgrind verification (#24, #242)
|
||||||
|
* Redo all documentation (English, Simplified Chinese)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Copyright ownership transfered to THL A29 Limited (a Tencent company).
|
||||||
|
* Migrating from Premake to CMAKE (#192)
|
||||||
|
* Resolve all warning reports
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* Remove other JSON libraries for performance comparison (#180)
|
||||||
|
|
||||||
|
## 0.11 - 2012-11-16
|
||||||
|
|
||||||
|
## 0.1 - 2011-11-18
|
||||||
|
|
||||||
|
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD
|
||||||
|
[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
|
@ -3,9 +3,9 @@ SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
|
|||||||
|
|
||||||
PROJECT(RapidJSON CXX)
|
PROJECT(RapidJSON CXX)
|
||||||
|
|
||||||
set(LIB_MAJOR_VERSION "0")
|
set(LIB_MAJOR_VERSION "1")
|
||||||
set(LIB_MINOR_VERSION "12")
|
set(LIB_MINOR_VERSION "0")
|
||||||
set(LIB_PATCH_VERSION "0")
|
set(LIB_PATCH_VERSION "1")
|
||||||
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
|
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
|
||||||
|
|
||||||
# compile in release with debug info mode by default
|
# compile in release with debug info mode by default
|
||||||
@ -17,6 +17,8 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|||||||
option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON)
|
option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON)
|
||||||
option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON)
|
option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON)
|
||||||
option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON)
|
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_HAS_STDSTRING "" OFF)
|
option(RAPIDJSON_HAS_STDSTRING "" OFF)
|
||||||
if(RAPIDJSON_HAS_STDSTRING)
|
if(RAPIDJSON_HAS_STDSTRING)
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
|
||||||
SET(GTEST_SEARCH_PATH
|
SET(GTEST_SEARCH_PATH
|
||||||
"${GTEST_SOURCE_DIR}"
|
"${GTEST_SOURCE_DIR}"
|
||||||
"${CMAKE_SOURCE_DIR}/thirdparty/gtest")
|
"${CMAKE_SOURCE_DIR}/thirdparty/gtest")
|
||||||
|
|
||||||
IF(UNIX)
|
IF(UNIX)
|
||||||
LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest")
|
IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST)
|
||||||
|
LIST(APPEND GTEST_SEARCH_PATH "/usr/src/gtest")
|
||||||
|
ELSE()
|
||||||
|
LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest")
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
FIND_PATH(GTEST_SOURCE_DIR
|
FIND_PATH(GTEST_SOURCE_DIR
|
||||||
@ -15,8 +20,10 @@ FIND_PATH(GTEST_SOURCE_DIR
|
|||||||
FIND_PATH(GTEST_INCLUDE_DIR
|
FIND_PATH(GTEST_INCLUDE_DIR
|
||||||
NAMES gtest/gtest.h
|
NAMES gtest/gtest.h
|
||||||
PATH_SUFFIXES include
|
PATH_SUFFIXES include
|
||||||
|
HINTS ${GTEST_SOURCE_DIR}
|
||||||
PATHS ${GTEST_SEARCH_PATH})
|
PATHS ${GTEST_SEARCH_PATH})
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(GTestSrc DEFAULT_MSG
|
find_package_handle_standard_args(GTestSrc DEFAULT_MSG
|
||||||
GTEST_SOURCE_DIR
|
GTEST_SOURCE_DIR
|
||||||
GTEST_INCLUDE_DIR)
|
GTEST_INCLUDE_DIR)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: 0.12.{build}
|
version: 1.0.1.{build}
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
- Debug
|
- Debug
|
||||||
|
14
doc/dom.md
14
doc/dom.md
@ -84,29 +84,25 @@ template <typename InputStream>
|
|||||||
GenericDocument& GenericDocument::ParseStream(InputStream& is);
|
GenericDocument& GenericDocument::ParseStream(InputStream& is);
|
||||||
|
|
||||||
// (4) In situ parsing
|
// (4) In situ parsing
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
|
||||||
|
|
||||||
// (5) In situ parsing, using same Encoding of Document
|
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
||||||
|
|
||||||
// (6) In situ parsing, using default parse flags
|
// (5) In situ parsing, using default parse flags
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
||||||
|
|
||||||
// (7) Normal parsing of a string
|
// (6) Normal parsing of a string
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
template <unsigned parseFlags, typename SourceEncoding>
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
|
|
||||||
// (8) Normal parsing of a string, using same Encoding of Document
|
// (7) Normal parsing of a string, using same Encoding of Document
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
|
|
||||||
// (9) Normal parsing of a string, using default parse flags
|
// (8) Normal parsing of a string, using default parse flags
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
The examples of [tutorial](doc/tutorial.md) uses (9) for normal parsing of string. The examples of [stream](doc/stream.md) uses the first three. *In situ* parsing will be described soon.
|
The examples of [tutorial](doc/tutorial.md) uses (8) for normal parsing of string. The examples of [stream](doc/stream.md) uses the first three. *In situ* parsing will be described soon.
|
||||||
|
|
||||||
The `parseFlags` are combination of the following bit-flags:
|
The `parseFlags` are combination of the following bit-flags:
|
||||||
|
|
||||||
|
@ -84,29 +84,25 @@ template <typename InputStream>
|
|||||||
GenericDocument& GenericDocument::ParseStream(InputStream& is);
|
GenericDocument& GenericDocument::ParseStream(InputStream& is);
|
||||||
|
|
||||||
// (4) 原位解析
|
// (4) 原位解析
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
|
||||||
|
|
||||||
// (5) 原位解析,使用Document的编码
|
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
||||||
|
|
||||||
// (6) 原位解析,使用缺省标志
|
// (5) 原位解析,使用缺省标志
|
||||||
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
|
||||||
|
|
||||||
// (7) 正常解析一个字符串
|
// (6) 正常解析一个字符串
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
template <unsigned parseFlags, typename SourceEncoding>
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
|
|
||||||
// (8) 正常解析一个字符串,使用Document的编码
|
// (7) 正常解析一个字符串,使用Document的编码
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
|
|
||||||
// (9) 正常解析一个字符串,使用缺省标志
|
// (8) 正常解析一个字符串,使用缺省标志
|
||||||
GenericDocument& GenericDocument::Parse(const Ch* str);
|
GenericDocument& GenericDocument::Parse(const Ch* str);
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
[教程](tutorial.md)中的例使用(9)去正常解析字符串。而[流](stream.md)的例子使用前3个函数。我们将稍后介绍原位(*In situ*) 解析。
|
[教程](tutorial.md)中的例使用(8)去正常解析字符串。而[流](stream.md)的例子使用前3个函数。我们将稍后介绍原位(*In situ*) 解析。
|
||||||
|
|
||||||
`parseFlags`是以下位标置的组合:
|
`parseFlags`是以下位标置的组合:
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
6. How to install RapidJSON?
|
6. How to install RapidJSON?
|
||||||
|
|
||||||
Check [Installation section](http://miloyip.github.io/rapidjson/).
|
Check [Installation section](https://miloyip.github.io/rapidjson/).
|
||||||
|
|
||||||
7. Can RapidJSON run on my platform?
|
7. Can RapidJSON run on my platform?
|
||||||
|
|
||||||
@ -198,7 +198,7 @@
|
|||||||
|
|
||||||
3. What is SIMD? How it is applied in RapidJSON?
|
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.1 to accelerate whitespace skipping. This improves performance of parsing indent formatted JSON.
|
[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.
|
||||||
|
|
||||||
4. Does it consume a lot of memory?
|
4. Does it consume a lot of memory?
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@
|
|||||||
|
|
||||||
3. 什是是SIMD?它如何用于RapidJSON?
|
3. 什是是SIMD?它如何用于RapidJSON?
|
||||||
|
|
||||||
[SIMD](http://en.wikipedia.org/wiki/SIMD)指令可以在现代CPU中执行并行运算。RapidJSON支持了Intel的SSE2/SSE4.1去加速跳过空白字符。在解析含缩进的JSON时,这能提升性能。
|
[SIMD](http://en.wikipedia.org/wiki/SIMD)指令可以在现代CPU中执行并行运算。RapidJSON支持了Intel的SSE2/SSE4.2去加速跳过空白字符。在解析含缩进的JSON时,这能提升性能。只要定义名为`RAPIDJSON_SSE2`或`RAPIDJSON_SSE42`的宏,就能启动这个功能。然而,若在不支持这些指令集的机器上执行这些可执行文件,会导致崩溃。
|
||||||
|
|
||||||
4. 它会消耗许多内存么?
|
4. 它会消耗许多内存么?
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* High performance
|
* High performance
|
||||||
* Use template and inline functions to reduce function call overheads.
|
* Use template and inline functions to reduce function call overheads.
|
||||||
* Internal optimized Grisu2 and floating point parsing implementations.
|
* Internal optimized Grisu2 and floating point parsing implementations.
|
||||||
* Optional SSE2/SSE4.1 support.
|
* Optional SSE2/SSE4.2 support.
|
||||||
|
|
||||||
## Standard compliance
|
## Standard compliance
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* 高性能
|
* 高性能
|
||||||
* 使用模版及内联函数去降低函数调用开销。
|
* 使用模版及内联函数去降低函数调用开销。
|
||||||
* 内部经优化的Grisu2及浮点数解析实现。
|
* 内部经优化的Grisu2及浮点数解析实现。
|
||||||
* 可选的SSE2/SSE4.1支持。
|
* 可选的SSE2/SSE4.2支持。
|
||||||
|
|
||||||
## 符合标准
|
## 符合标准
|
||||||
|
|
||||||
|
@ -183,7 +183,21 @@ void SkipWhitespace(InputStream& s) {
|
|||||||
|
|
||||||
However, this requires 4 comparisons and a few branching for each character. This was found to be a hot spot.
|
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.1 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 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 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`:
|
||||||
|
|
||||||
|
~~~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.
|
||||||
|
#if defined(__SSE4_2__)
|
||||||
|
# define RAPIDJSON_SSE42
|
||||||
|
#elif defined(__SSE2__)
|
||||||
|
# define RAPIDJSON_SSE2
|
||||||
|
#endif
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Note that, these are compile-time settings. Running the executable on a machine without such instruction set support will make it crash.
|
||||||
|
|
||||||
## Local Stream Copy {#LocalStreamCopy}
|
## Local Stream Copy {#LocalStreamCopy}
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
(document.getElementsByClassName('contents')[0]).appendChild(dt);
|
(document.getElementsByClassName('contents')[0]).appendChild(dt);
|
||||||
|
|
||||||
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
||||||
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
|
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
|
||||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -192,7 +192,7 @@ Checking | Obtaining
|
|||||||
`bool IsNumber()` | N/A
|
`bool IsNumber()` | N/A
|
||||||
`bool IsUint()` | `unsigned GetUint()`
|
`bool IsUint()` | `unsigned GetUint()`
|
||||||
`bool IsInt()` | `int GetInt()`
|
`bool IsInt()` | `int GetInt()`
|
||||||
`bool IsUint64()` | `uint64_t GetUint()`
|
`bool IsUint64()` | `uint64_t GetUint64()`
|
||||||
`bool IsInt64()` | `int64_t GetInt64()`
|
`bool IsInt64()` | `int64_t GetInt64()`
|
||||||
`bool IsDouble()` | `double GetDouble()`
|
`bool IsDouble()` | `double GetDouble()`
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ JSON只提供一种数值类型──Number。数字可以是整数或实数。R
|
|||||||
`bool IsNumber()` | 不适用
|
`bool IsNumber()` | 不适用
|
||||||
`bool IsUint()` | `unsigned GetUint()`
|
`bool IsUint()` | `unsigned GetUint()`
|
||||||
`bool IsInt()` | `int GetInt()`
|
`bool IsInt()` | `int GetInt()`
|
||||||
`bool IsUint64()` | `uint64_t GetUint()`
|
`bool IsUint64()` | `uint64_t GetUint64()`
|
||||||
`bool IsInt64()` | `int64_t GetInt64()`
|
`bool IsInt64()` | `int64_t GetInt64()`
|
||||||
`bool IsDouble()` | `double GetDouble()`
|
`bool IsDouble()` | `double GetDouble()`
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// This example shows writing JSON string with writer directly.
|
// This example shows writing JSON string with writer directly.
|
||||||
|
|
||||||
#include "rapidjson/prettywriter.h" // for stringify JSON
|
#include "rapidjson/prettywriter.h" // for stringify JSON
|
||||||
#include "rapidjson/filestream.h" // wrapper of C stream for prettywriter as output
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -144,13 +143,15 @@ int main(int, char*[]) {
|
|||||||
|
|
||||||
employees.push_back(Employee("Percy TSE", 30, false));
|
employees.push_back(Employee("Percy TSE", 30, false));
|
||||||
|
|
||||||
FileStream s(stdout);
|
StringBuffer sb;
|
||||||
PrettyWriter<FileStream> writer(s); // Can also use Writer for condensed formatting
|
PrettyWriter<StringBuffer> writer(sb);
|
||||||
|
|
||||||
writer.StartArray();
|
writer.StartArray();
|
||||||
for (std::vector<Employee>::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr)
|
for (std::vector<Employee>::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr)
|
||||||
employeeItr->Serialize(writer);
|
employeeItr->Serialize(writer);
|
||||||
writer.EndArray();
|
writer.EndArray();
|
||||||
|
|
||||||
|
puts(sb.GetString());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "rapidjson/document.h" // rapidjson's DOM-style API
|
#include "rapidjson/document.h" // rapidjson's DOM-style API
|
||||||
#include "rapidjson/prettywriter.h" // for stringify JSON
|
#include "rapidjson/prettywriter.h" // for stringify JSON
|
||||||
#include "rapidjson/filestream.h" // wrapper of C stream for prettywriter as output
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
@ -143,9 +142,10 @@ int main(int, char*[]) {
|
|||||||
// 4. Stringify JSON
|
// 4. Stringify JSON
|
||||||
|
|
||||||
printf("\nModified JSON with reformatting:\n");
|
printf("\nModified JSON with reformatting:\n");
|
||||||
FileStream f(stdout);
|
StringBuffer sb;
|
||||||
PrettyWriter<FileStream> writer(f);
|
PrettyWriter<StringBuffer> writer(sb);
|
||||||
document.Accept(writer); // Accept() traverses the DOM and generates Handler events.
|
document.Accept(writer); // Accept() traverses the DOM and generates Handler events.
|
||||||
|
puts(sb.GetString());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,12 @@ concept Allocator {
|
|||||||
class CrtAllocator {
|
class CrtAllocator {
|
||||||
public:
|
public:
|
||||||
static const bool kNeedFree = true;
|
static const bool kNeedFree = true;
|
||||||
void* Malloc(size_t size) { return std::malloc(size); }
|
void* Malloc(size_t size) {
|
||||||
|
if (size) // behavior of malloc(0) is implementation defined.
|
||||||
|
return std::malloc(size);
|
||||||
|
else
|
||||||
|
return NULL; // standardize to returning NULL.
|
||||||
|
}
|
||||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
|
||||||
static void Free(void *ptr) { std::free(ptr); }
|
static void Free(void *ptr) { std::free(ptr); }
|
||||||
};
|
};
|
||||||
@ -160,6 +165,9 @@ public:
|
|||||||
|
|
||||||
//! Allocates a memory block. (concept Allocator)
|
//! Allocates a memory block. (concept Allocator)
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size) {
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
size = RAPIDJSON_ALIGN(size);
|
size = RAPIDJSON_ALIGN(size);
|
||||||
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
||||||
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
|
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
|
||||||
@ -191,7 +199,9 @@ public:
|
|||||||
// Realloc process: allocate and copy memory, do not free original buffer.
|
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||||
void* newBuffer = Malloc(newSize);
|
void* newBuffer = Malloc(newSize);
|
||||||
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
|
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
|
||||||
return std::memcpy(newBuffer, originalPtr, originalSize);
|
if (originalSize)
|
||||||
|
std::memcpy(newBuffer, originalPtr, originalSize);
|
||||||
|
return newBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Frees a memory block (concept Allocator)
|
//! Frees a memory block (concept Allocator)
|
||||||
|
@ -701,8 +701,11 @@ public:
|
|||||||
return StringEqual(rhs);
|
return StringEqual(rhs);
|
||||||
|
|
||||||
case kNumberType:
|
case kNumberType:
|
||||||
if (IsDouble() || rhs.IsDouble())
|
if (IsDouble() || rhs.IsDouble()) {
|
||||||
return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
|
double a = GetDouble(); // May convert from integer to double.
|
||||||
|
double b = rhs.GetDouble(); // Ditto
|
||||||
|
return a >= b && a <= b; // Prevent -Wfloat-equal
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return data_.n.u64 == rhs.data_.n.u64;
|
return data_.n.u64 == rhs.data_.n.u64;
|
||||||
|
|
||||||
@ -1457,17 +1460,14 @@ public:
|
|||||||
case kStringType:
|
case kStringType:
|
||||||
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
|
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
|
||||||
|
|
||||||
case kNumberType:
|
default:
|
||||||
|
RAPIDJSON_ASSERT(GetType() == kNumberType);
|
||||||
if (IsInt()) return handler.Int(data_.n.i.i);
|
if (IsInt()) return handler.Int(data_.n.i.i);
|
||||||
else if (IsUint()) return handler.Uint(data_.n.u.u);
|
else if (IsUint()) return handler.Uint(data_.n.u.u);
|
||||||
else if (IsInt64()) return handler.Int64(data_.n.i64);
|
else if (IsInt64()) return handler.Int64(data_.n.i64);
|
||||||
else if (IsUint64()) return handler.Uint64(data_.n.u64);
|
else if (IsUint64()) return handler.Uint64(data_.n.u64);
|
||||||
else return handler.Double(data_.n.d);
|
else return handler.Double(data_.n.d);
|
||||||
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1580,16 +1580,24 @@ private:
|
|||||||
// Initialize this value as array with initial data, without calling destructor.
|
// Initialize this value as array with initial data, without calling destructor.
|
||||||
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
||||||
flags_ = kArrayFlag;
|
flags_ = kArrayFlag;
|
||||||
data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
|
if (count) {
|
||||||
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
|
||||||
|
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data_.a.elements = NULL;
|
||||||
data_.a.size = data_.a.capacity = count;
|
data_.a.size = data_.a.capacity = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Initialize this value as object with initial data, without calling destructor.
|
//! Initialize this value as object with initial data, without calling destructor.
|
||||||
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
||||||
flags_ = kObjectFlag;
|
flags_ = kObjectFlag;
|
||||||
data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
|
if (count) {
|
||||||
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
|
||||||
|
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data_.o.members = NULL;
|
||||||
data_.o.size = data_.o.capacity = count;
|
data_.o.size = data_.o.capacity = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1751,7 +1759,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <unsigned parseFlags, typename InputStream>
|
template <unsigned parseFlags, typename InputStream>
|
||||||
GenericDocument& ParseStream(InputStream& is) {
|
GenericDocument& ParseStream(InputStream& is) {
|
||||||
return ParseStream<parseFlags,Encoding,InputStream>(is);
|
return ParseStream<parseFlags, Encoding, InputStream>(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
|
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
|
||||||
@ -1768,18 +1776,6 @@ public:
|
|||||||
//!@name Parse in-place from mutable string
|
//!@name Parse in-place from mutable string
|
||||||
//!@{
|
//!@{
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string (with Encoding conversion)
|
|
||||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
|
||||||
\tparam SourceEncoding Transcoding from input Encoding
|
|
||||||
\param str Mutable zero-terminated string to be parsed.
|
|
||||||
\return The document itself for fluent API.
|
|
||||||
*/
|
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
|
||||||
GenericInsituStringStream<Encoding> s(str);
|
|
||||||
return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string
|
//! Parse JSON text from a mutable string
|
||||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||||
\param str Mutable zero-terminated string to be parsed.
|
\param str Mutable zero-terminated string to be parsed.
|
||||||
@ -1787,7 +1783,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
GenericDocument& ParseInsitu(Ch* str) {
|
||||||
return ParseInsitu<parseFlags, Encoding>(str);
|
GenericInsituStringStream<Encoding> s(str);
|
||||||
|
return ParseStream<parseFlags | kParseInsituFlag>(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
|
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
|
||||||
@ -1795,7 +1792,7 @@ public:
|
|||||||
\return The document itself for fluent API.
|
\return The document itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
GenericDocument& ParseInsitu(Ch* str) {
|
||||||
return ParseInsitu<kParseDefaultFlags, Encoding>(str);
|
return ParseInsitu<kParseDefaultFlags>(str);
|
||||||
}
|
}
|
||||||
//!@}
|
//!@}
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ public:
|
|||||||
\param type UTF encoding type if it is not detected from the stream.
|
\param type UTF encoding type if it is not detected from the stream.
|
||||||
*/
|
*/
|
||||||
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
||||||
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
DetectType();
|
DetectType();
|
||||||
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||||
takeFunc_ = f[type_];
|
takeFunc_ = f[type_];
|
||||||
@ -177,21 +178,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||||
switch (type_) {
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
case kUTF8:
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
// Do nothing
|
|
||||||
break;
|
|
||||||
case kUTF16LE:
|
|
||||||
case kUTF16BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
|
||||||
break;
|
|
||||||
case kUTF32LE:
|
|
||||||
case kUTF32BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false); // Invalid type
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Ch (*TakeFunc)(InputByteStream& is);
|
typedef Ch (*TakeFunc)(InputByteStream& is);
|
||||||
@ -220,22 +208,11 @@ public:
|
|||||||
\param putBOM Whether to write BOM at the beginning of the stream.
|
\param putBOM Whether to write BOM at the beginning of the stream.
|
||||||
*/
|
*/
|
||||||
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
||||||
// RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
switch (type_) {
|
|
||||||
case kUTF16LE:
|
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||||
case kUTF16BE:
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
break;
|
|
||||||
case kUTF32LE:
|
|
||||||
case kUTF32BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
|
||||||
break;
|
|
||||||
case kUTF8:
|
|
||||||
// Do nothing
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false); // Invalid UTFType
|
|
||||||
}
|
|
||||||
|
|
||||||
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||||
putFunc_ = f[type_];
|
putFunc_ = f[type_];
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef RAPIDJSON_ERROR_ERROR_H__
|
#ifndef RAPIDJSON_ERROR_ERROR_H__
|
||||||
#define RAPIDJSON_ERROR_ERROR_H__
|
#define RAPIDJSON_ERROR_ERROR_H__
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
/*! \file error.h */
|
/*! \file error.h */
|
||||||
|
|
||||||
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
|
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// 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_FILESTREAM_H_
|
|
||||||
#define RAPIDJSON_FILESTREAM_H_
|
|
||||||
|
|
||||||
#include "rapidjson.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
//! (Deprecated) Wrapper of C file stream for input or output.
|
|
||||||
/*!
|
|
||||||
This simple wrapper does not check the validity of the stream.
|
|
||||||
\note implements Stream concept
|
|
||||||
\note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead.
|
|
||||||
*/
|
|
||||||
class FileStream {
|
|
||||||
public:
|
|
||||||
typedef char Ch; //!< Character type. Only support char.
|
|
||||||
|
|
||||||
FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
|
|
||||||
char Peek() const { return current_; }
|
|
||||||
char Take() { char c = current_; Read(); return c; }
|
|
||||||
size_t Tell() const { return count_; }
|
|
||||||
void Put(char c) { fputc(c, fp_); }
|
|
||||||
void Flush() { fflush(fp_); }
|
|
||||||
|
|
||||||
// Not implemented
|
|
||||||
char* PutBegin() { return 0; }
|
|
||||||
size_t PutEnd(char*) { return 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Prohibit copy constructor & assignment operator.
|
|
||||||
FileStream(const FileStream&);
|
|
||||||
FileStream& operator=(const FileStream&);
|
|
||||||
|
|
||||||
void Read() {
|
|
||||||
RAPIDJSON_ASSERT(fp_ != 0);
|
|
||||||
int c = fgetc(fp_);
|
|
||||||
if (c != EOF) {
|
|
||||||
current_ = (char)c;
|
|
||||||
count_++;
|
|
||||||
}
|
|
||||||
else if (current_ != '\0')
|
|
||||||
current_ = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
std::FILE* fp_;
|
|
||||||
char current_;
|
|
||||||
size_t count_;
|
|
||||||
};
|
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
|
||||||
|
|
||||||
#endif // RAPIDJSON_FILESTREAM_H_
|
|
@ -172,13 +172,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute absolute difference of this and rhs.
|
// Compute absolute difference of this and rhs.
|
||||||
// Return false if this < rhs
|
// Assume this != rhs
|
||||||
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
||||||
int cmp = Compare(rhs);
|
int cmp = Compare(rhs);
|
||||||
if (cmp == 0) {
|
RAPIDJSON_ASSERT(cmp != 0);
|
||||||
*out = BigInteger(0);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const BigInteger *a, *b; // Makes a > b
|
const BigInteger *a, *b; // Makes a > b
|
||||||
bool ret;
|
bool ret;
|
||||||
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
||||||
@ -269,12 +266,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static Type FullAdd(Type a, Type b, bool inCarry, bool* outCarry) {
|
|
||||||
Type c = a + b + (inCarry ? 1 : 0);
|
|
||||||
*outCarry = c < a;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
|
static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
|
||||||
static const size_t kCapacity = kBitCount / sizeof(Type);
|
static const size_t kCapacity = kBitCount / sizeof(Type);
|
||||||
static const size_t kTypeBit = sizeof(Type) * 8;
|
static const size_t kTypeBit = sizeof(Type) * 8;
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
#ifndef RAPIDJSON_DIYFP_H_
|
#ifndef RAPIDJSON_DIYFP_H_
|
||||||
#define RAPIDJSON_DIYFP_H_
|
#define RAPIDJSON_DIYFP_H_
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#if defined(_M_AMD64)
|
|
||||||
#pragma intrinsic(_BitScanReverse64)
|
#pragma intrinsic(_BitScanReverse64)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -135,25 +135,9 @@ struct DiyFp {
|
|||||||
double d;
|
double d;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
}u;
|
}u;
|
||||||
uint64_t significand = f;
|
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||||
int exponent = e;
|
static_cast<uint64_t>(e + kDpExponentBias);
|
||||||
while (significand > kDpHiddenBit + kDpSignificandMask) {
|
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||||
significand >>= 1;
|
|
||||||
exponent++;
|
|
||||||
}
|
|
||||||
while (exponent > kDpDenormalExponent && (significand & kDpHiddenBit) == 0) {
|
|
||||||
significand <<= 1;
|
|
||||||
exponent--;
|
|
||||||
}
|
|
||||||
if (exponent >= kDpMaxExponent) {
|
|
||||||
u.u64 = kDpExponentMask; // Infinity
|
|
||||||
return u.d;
|
|
||||||
}
|
|
||||||
else if (exponent < kDpDenormalExponent)
|
|
||||||
return 0.0;
|
|
||||||
const uint64_t be = (exponent == kDpDenormalExponent && (significand & kDpHiddenBit) == 0) ? 0 :
|
|
||||||
static_cast<uint64_t>(exponent + kDpExponentBias);
|
|
||||||
u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize);
|
|
||||||
return u.d;
|
return u.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +222,7 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
|||||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||||
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||||
int k = static_cast<int>(dk);
|
int k = static_cast<int>(dk);
|
||||||
if (k != dk)
|
if (dk - k > 0.0)
|
||||||
k++;
|
k++;
|
||||||
|
|
||||||
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "itoa.h" // GetDigitsLut()
|
#include "itoa.h" // GetDigitsLut()
|
||||||
#include "diyfp.h"
|
#include "diyfp.h"
|
||||||
|
#include "ieee754.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -49,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
|
|||||||
if (n < 1000000) return 6;
|
if (n < 1000000) return 6;
|
||||||
if (n < 10000000) return 7;
|
if (n < 10000000) return 7;
|
||||||
if (n < 100000000) return 8;
|
if (n < 100000000) return 8;
|
||||||
if (n < 1000000000) return 9;
|
// Will not reach 10 digits in DigitGen()
|
||||||
return 10;
|
//if (n < 1000000000) return 9;
|
||||||
|
//return 10;
|
||||||
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
||||||
@ -59,13 +62,12 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
|||||||
const DiyFp wp_w = Mp - W;
|
const DiyFp wp_w = Mp - W;
|
||||||
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
||||||
uint64_t p2 = Mp.f & (one.f - 1);
|
uint64_t p2 = Mp.f & (one.f - 1);
|
||||||
int kappa = CountDecimalDigit32(p1);
|
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
while (kappa > 0) {
|
while (kappa > 0) {
|
||||||
uint32_t d;
|
uint32_t d = 0;
|
||||||
switch (kappa) {
|
switch (kappa) {
|
||||||
case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
|
|
||||||
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
||||||
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
||||||
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
||||||
@ -75,14 +77,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
|||||||
case 3: d = p1 / 100; p1 %= 100; break;
|
case 3: d = p1 / 100; p1 %= 100; break;
|
||||||
case 2: d = p1 / 10; p1 %= 10; break;
|
case 2: d = p1 / 10; p1 %= 10; break;
|
||||||
case 1: d = p1; p1 = 0; break;
|
case 1: d = p1; p1 = 0; break;
|
||||||
default:
|
default:;
|
||||||
#if defined(_MSC_VER)
|
|
||||||
__assume(0);
|
|
||||||
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
|
||||||
__builtin_unreachable();
|
|
||||||
#else
|
|
||||||
d = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (d || *len)
|
if (d || *len)
|
||||||
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
||||||
@ -192,7 +187,10 @@ inline char* Prettify(char* buffer, int length, int k) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline char* dtoa(double value, char* buffer) {
|
inline char* dtoa(double value, char* buffer) {
|
||||||
if (value == 0) {
|
Double d(value);
|
||||||
|
if (d.IsZero()) {
|
||||||
|
if (d.Sign())
|
||||||
|
*buffer++ = '-'; // -0.0, Issue #289
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
buffer[2] = '0';
|
buffer[2] = '0';
|
||||||
|
@ -34,14 +34,6 @@ public:
|
|||||||
return Double(u + 1).Value();
|
return Double(u + 1).Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
double PreviousPositiveDouble() const {
|
|
||||||
RAPIDJSON_ASSERT(!Sign());
|
|
||||||
if (d == 0.0)
|
|
||||||
return 0.0;
|
|
||||||
else
|
|
||||||
return Double(u - 1).Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sign() const { return (u & kSignMask) != 0; }
|
bool Sign() const { return (u & kSignMask) != 0; }
|
||||||
uint64_t Significand() const { return u & kSignificandMask; }
|
uint64_t Significand() const { return u & kSignificandMask; }
|
||||||
int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
|
int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
|
||||||
@ -49,6 +41,7 @@ public:
|
|||||||
bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; }
|
bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||||
bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; }
|
bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||||
bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; }
|
bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; }
|
||||||
|
bool IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; }
|
||||||
|
|
||||||
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
||||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef RAPIDJSON_ITOA_
|
#ifndef RAPIDJSON_ITOA_
|
||||||
#define RAPIDJSON_ITOA_
|
#define RAPIDJSON_ITOA_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -109,12 +111,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline char* i32toa(int32_t value, char* buffer) {
|
inline char* i32toa(int32_t value, char* buffer) {
|
||||||
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
value = -value;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return u32toa(static_cast<uint32_t>(value), buffer);
|
return u32toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* u64toa(uint64_t value, char* buffer) {
|
inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
@ -286,12 +289,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline char* i64toa(int64_t value, char* buffer) {
|
inline char* i64toa(int64_t value, char* buffer) {
|
||||||
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
value = -value;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return u64toa(static_cast<uint64_t>(value), buffer);
|
return u64toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -15,9 +15,7 @@
|
|||||||
#ifndef RAPIDJSON_INTERNAL_META_H_
|
#ifndef RAPIDJSON_INTERNAL_META_H_
|
||||||
#define RAPIDJSON_INTERNAL_META_H_
|
#define RAPIDJSON_INTERNAL_META_H_
|
||||||
|
|
||||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
#include "../rapidjson.h"
|
||||||
#error <rapidjson.h> not yet included. Do not include this file directly.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef RAPIDJSON_POW10_
|
#ifndef RAPIDJSON_POW10_
|
||||||
#define RAPIDJSON_POW10_
|
#define RAPIDJSON_POW10_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||||
#define RAPIDJSON_INTERNAL_STACK_H_
|
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ inline T Min3(T a, T b, T c) {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adjustToNegative) {
|
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||||
const Double db(b);
|
const Double db(b);
|
||||||
const uint64_t bInt = db.IntegerSignificand();
|
const uint64_t bInt = db.IntegerSignificand();
|
||||||
const int bExp = db.IntegerExponent();
|
const int bExp = db.IntegerExponent();
|
||||||
@ -104,19 +104,9 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adj
|
|||||||
hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
|
hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
|
||||||
|
|
||||||
BigInteger delta(0);
|
BigInteger delta(0);
|
||||||
*adjustToNegative = dS.Difference(bS, &delta);
|
dS.Difference(bS, &delta);
|
||||||
|
|
||||||
int cmp = delta.Compare(hS);
|
return delta.Compare(hS);
|
||||||
// If delta is within 1/2 ULP, check for special case when significand is power of two.
|
|
||||||
// In this case, need to compare with 1/2h in the lower bound.
|
|
||||||
if (cmp < 0 && *adjustToNegative && // within and dS < bS
|
|
||||||
db.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2
|
|
||||||
db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this
|
|
||||||
{
|
|
||||||
delta <<= 1;
|
|
||||||
return delta.Compare(hS);
|
|
||||||
}
|
|
||||||
return cmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool StrtodFast(double d, int p, double* result) {
|
inline bool StrtodFast(double d, int p, double* result) {
|
||||||
@ -213,24 +203,18 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
|
|||||||
const BigInteger dInt(decimals, length);
|
const BigInteger dInt(decimals, length);
|
||||||
const int dExp = (int)decimalPosition - (int)length + exp;
|
const int dExp = (int)decimalPosition - (int)length + exp;
|
||||||
Double a(approx);
|
Double a(approx);
|
||||||
for (int i = 0; i < 10; i++) {
|
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||||
bool adjustToNegative;
|
if (cmp < 0)
|
||||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative);
|
return a.Value(); // within half ULP
|
||||||
if (cmp < 0)
|
else if (cmp == 0) {
|
||||||
return a.Value(); // within half ULP
|
// Round towards even
|
||||||
else if (cmp == 0) {
|
if (a.Significand() & 1)
|
||||||
// Round towards even
|
return a.NextPositiveDouble();
|
||||||
if (a.Significand() & 1)
|
else
|
||||||
return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
|
return a.Value();
|
||||||
else
|
|
||||||
return a.Value();
|
|
||||||
}
|
|
||||||
else // adjustment
|
|
||||||
a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
|
|
||||||
}
|
}
|
||||||
|
else // adjustment
|
||||||
// This should not happen, but in case there is really a bug, break the infinite-loop
|
return a.NextPositiveDouble();
|
||||||
return a.Value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||||
@ -258,7 +242,9 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
|||||||
// Trim right-most digits
|
// Trim right-most digits
|
||||||
const int kMaxDecimalDigit = 780;
|
const int kMaxDecimalDigit = 780;
|
||||||
if ((int)length > kMaxDecimalDigit) {
|
if ((int)length > kMaxDecimalDigit) {
|
||||||
exp += (int(length) - kMaxDecimalDigit);
|
int delta = (int(length) - kMaxDecimalDigit);
|
||||||
|
exp += delta;
|
||||||
|
decimalPosition -= delta;
|
||||||
length = kMaxDecimalDigit;
|
length = kMaxDecimalDigit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
bool String(const std::basic_string<Ch>& str) {
|
bool String(const std::basic_string<Ch>& str) {
|
||||||
return String(str.data(), SizeType(str.size()));
|
return String(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -100,8 +100,9 @@ public:
|
|||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
if (!Base::WriteEndObject())
|
bool ret = Base::WriteEndObject();
|
||||||
return false;
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
if (Base::level_stack_.Empty()) // end of json text
|
if (Base::level_stack_.Empty()) // end of json text
|
||||||
Base::os_->Flush();
|
Base::os_->Flush();
|
||||||
return true;
|
return true;
|
||||||
@ -123,8 +124,9 @@ public:
|
|||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
if (!Base::WriteEndArray())
|
bool ret = Base::WriteEndArray();
|
||||||
return false;
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
if (Base::level_stack_.Empty()) // end of json text
|
if (Base::level_stack_.Empty()) // end of json text
|
||||||
Base::os_->Flush();
|
Base::os_->Flush();
|
||||||
return true;
|
return true;
|
||||||
|
@ -15,12 +15,9 @@
|
|||||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
#ifndef RAPIDJSON_RAPIDJSON_H_
|
||||||
#define RAPIDJSON_RAPIDJSON_H_
|
#define RAPIDJSON_RAPIDJSON_H_
|
||||||
|
|
||||||
// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
|
|
||||||
// Version 0.1
|
|
||||||
|
|
||||||
/*!\file rapidjson.h
|
/*!\file rapidjson.h
|
||||||
\brief common definitions and configuration
|
\brief common definitions and configuration
|
||||||
|
|
||||||
\see RAPIDJSON_CONFIG
|
\see RAPIDJSON_CONFIG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -42,6 +39,40 @@
|
|||||||
#include <cstdlib> // malloc(), realloc(), free(), size_t
|
#include <cstdlib> // malloc(), realloc(), free(), size_t
|
||||||
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_VERSION_STRING
|
||||||
|
//
|
||||||
|
// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
|
||||||
|
//
|
||||||
|
|
||||||
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
|
// token stringification
|
||||||
|
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
||||||
|
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
||||||
|
//!@endcond
|
||||||
|
|
||||||
|
/*! \def RAPIDJSON_MAJOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Major version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_MINOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Minor version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_PATCH_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Patch version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_VERSION_STRING
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
|
||||||
|
*/
|
||||||
|
#define RAPIDJSON_MAJOR_VERSION 1
|
||||||
|
#define RAPIDJSON_MINOR_VERSION 0
|
||||||
|
#define RAPIDJSON_PATCH_VERSION 1
|
||||||
|
#define RAPIDJSON_VERSION_STRING \
|
||||||
|
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_NAMESPACE_(BEGIN|END)
|
// RAPIDJSON_NAMESPACE_(BEGIN|END)
|
||||||
/*! \def RAPIDJSON_NAMESPACE
|
/*! \def RAPIDJSON_NAMESPACE
|
||||||
@ -122,9 +153,9 @@
|
|||||||
|
|
||||||
#ifndef RAPIDJSON_FORCEINLINE
|
#ifndef RAPIDJSON_FORCEINLINE
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||||
#define RAPIDJSON_FORCEINLINE __forceinline
|
#define RAPIDJSON_FORCEINLINE __forceinline
|
||||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
|
||||||
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_FORCEINLINE
|
#define RAPIDJSON_FORCEINLINE
|
||||||
@ -356,10 +387,6 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||||
(((x)*100000) + ((y)*100) + (z))
|
(((x)*100000) + ((y)*100) + (z))
|
||||||
|
|
||||||
// token stringification
|
|
||||||
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
|
||||||
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
||||||
|
|
||||||
|
@ -255,23 +255,23 @@ void SkipWhitespace(InputStream& is) {
|
|||||||
#ifdef RAPIDJSON_SSE42
|
#ifdef RAPIDJSON_SSE42
|
||||||
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
||||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// 16-byte align to the next boundary
|
// 16-byte align to the next boundary
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
||||||
while (p != nextAligned)
|
while (p != nextAligned)
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// The rest of string using SIMD
|
// The rest of string using SIMD
|
||||||
static const char whitespace[16] = " \n\r\t";
|
static const char whitespace[16] = " \n\r\t";
|
||||||
const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
|
const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const __m128i s = _mm_load_si128((const __m128i *)p);
|
const __m128i s = _mm_load_si128((const __m128i *)p);
|
||||||
@ -292,31 +292,31 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
|||||||
|
|
||||||
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
||||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// 16-byte align to the next boundary
|
// 16-byte align to the next boundary
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
||||||
while (p != nextAligned)
|
while (p != nextAligned)
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// The rest of string
|
// The rest of string
|
||||||
static const char whitespaces[4][17] = {
|
static const char whitespaces[4][17] = {
|
||||||
" ",
|
" ",
|
||||||
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||||
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
|
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
|
||||||
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
|
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
|
||||||
|
|
||||||
const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
|
const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
|
||||||
const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
|
const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
|
||||||
const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
|
const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
|
||||||
const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
|
const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const __m128i s = _mm_load_si128((const __m128i *)p);
|
const __m128i s = _mm_load_si128((const __m128i *)p);
|
||||||
@ -689,11 +689,13 @@ private:
|
|||||||
}
|
}
|
||||||
else if (e == 'u') { // Unicode
|
else if (e == 'u') { // Unicode
|
||||||
unsigned codepoint = ParseHex4(is);
|
unsigned codepoint = ParseHex4(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
|
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
|
||||||
// Handle UTF-16 surrogate pair
|
// Handle UTF-16 surrogate pair
|
||||||
if (is.Take() != '\\' || is.Take() != 'u')
|
if (is.Take() != '\\' || is.Take() != 'u')
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
||||||
unsigned codepoint2 = ParseHex4(is);
|
unsigned codepoint2 = ParseHex4(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
|
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
||||||
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
||||||
@ -894,7 +896,7 @@ private:
|
|||||||
if (significandDigit < 17) {
|
if (significandDigit < 17) {
|
||||||
d = d * 10.0 + (s.TakePush() - '0');
|
d = d * 10.0 + (s.TakePush() - '0');
|
||||||
--expFrac;
|
--expFrac;
|
||||||
if (d != 0.0)
|
if (d > 0.0)
|
||||||
significandDigit++;
|
significandDigit++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -923,10 +925,22 @@ private:
|
|||||||
|
|
||||||
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
exp = s.Take() - '0';
|
exp = s.Take() - '0';
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
if (expMinus) {
|
||||||
exp = exp * 10 + (s.Take() - '0');
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
|
exp = exp * 10 + (s.Take() - '0');
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
if (exp >= 214748364) { // Issue #313: prevent overflow exponent
|
||||||
|
while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent
|
||||||
|
s.Take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // positive exp
|
||||||
|
int maxExp = 308 - expFrac;
|
||||||
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
|
exp = exp * 10 + (s.Take() - '0');
|
||||||
|
if (exp > maxExp)
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1225,14 +1239,9 @@ private:
|
|||||||
// May return a new state on state pop.
|
// May return a new state on state pop.
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template <unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
|
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
|
||||||
|
(void)token;
|
||||||
|
|
||||||
switch (dst) {
|
switch (dst) {
|
||||||
case IterativeParsingStartState:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
|
|
||||||
case IterativeParsingFinishState:
|
|
||||||
return dst;
|
|
||||||
|
|
||||||
case IterativeParsingErrorState:
|
case IterativeParsingErrorState:
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
@ -1271,12 +1280,9 @@ private:
|
|||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
case IterativeParsingKeyValueDelimiterState:
|
case IterativeParsingKeyValueDelimiterState:
|
||||||
if (token == ColonToken) {
|
RAPIDJSON_ASSERT(token == ColonToken);
|
||||||
is.Take();
|
is.Take();
|
||||||
return dst;
|
return dst;
|
||||||
}
|
|
||||||
else
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
|
|
||||||
case IterativeParsingMemberValueState:
|
case IterativeParsingMemberValueState:
|
||||||
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
||||||
@ -1351,17 +1357,25 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case IterativeParsingValueState:
|
default:
|
||||||
|
// This branch is for IterativeParsingValueState actually.
|
||||||
|
// Use `default:` rather than
|
||||||
|
// `case IterativeParsingValueState:` is for code coverage.
|
||||||
|
|
||||||
|
// The IterativeParsingStartState is not enumerated in this switch-case.
|
||||||
|
// It is impossible for that case. And it can be caught by following assertion.
|
||||||
|
|
||||||
|
// The IterativeParsingFinishState is not enumerated in this switch-case either.
|
||||||
|
// It is a "derivative" state which cannot triggered from Predict() directly.
|
||||||
|
// Therefore it cannot happen here. And it can be caught by following assertion.
|
||||||
|
RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
|
||||||
|
|
||||||
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
||||||
ParseValue<parseFlags>(is, handler);
|
ParseValue<parseFlags>(is, handler);
|
||||||
if (HasParseError()) {
|
if (HasParseError()) {
|
||||||
return IterativeParsingErrorState;
|
return IterativeParsingErrorState;
|
||||||
}
|
}
|
||||||
return IterativeParsingFinishState;
|
return IterativeParsingFinishState;
|
||||||
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ public:
|
|||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
bool String(const std::basic_string<Ch>& str) {
|
bool String(const std::basic_string<Ch>& str) {
|
||||||
return String(str.data(), SizeType(str.size()));
|
return String(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -272,7 +272,8 @@ protected:
|
|||||||
os_->Put(hexDigits[(codepoint >> 4) & 15]);
|
os_->Put(hexDigits[(codepoint >> 4) & 15]);
|
||||||
os_->Put(hexDigits[(codepoint ) & 15]);
|
os_->Put(hexDigits[(codepoint ) & 15]);
|
||||||
}
|
}
|
||||||
else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||||
// Surrogate pair
|
// Surrogate pair
|
||||||
unsigned s = codepoint - 0x010000;
|
unsigned s = codepoint - 0x010000;
|
||||||
unsigned lead = (s >> 10) + 0xD800;
|
unsigned lead = (s >> 10) + 0xD800;
|
||||||
@ -288,8 +289,6 @@ protected:
|
|||||||
os_->Put(hexDigits[(trail >> 4) & 15]);
|
os_->Put(hexDigits[(trail >> 4) & 15]);
|
||||||
os_->Put(hexDigits[(trail ) & 15]);
|
os_->Put(hexDigits[(trail ) & 15]);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false; // invalid code point
|
|
||||||
}
|
}
|
||||||
else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
|
else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
|
||||||
is.Take();
|
is.Take();
|
||||||
@ -303,7 +302,8 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
|
if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
os_->Put('\"');
|
os_->Put('\"');
|
||||||
return true;
|
return true;
|
||||||
|
17
readme.md
17
readme.md
@ -1,4 +1,7 @@
|
|||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## A fast JSON parser/generator for C++ with both SAX/DOM style API
|
## A fast JSON parser/generator for C++ with both SAX/DOM style API
|
||||||
|
|
||||||
Tencent is pleased to support the open source community by making RapidJSON available.
|
Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
@ -13,14 +16,16 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
|
|||||||
|
|
||||||
## Build status
|
## Build status
|
||||||
|
|
||||||
| [Linux][lin-link] | [Windows][win-link] |
|
| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] |
|
||||||
| :---------------: | :-----------------: |
|
| :---------------: | :-----------------: | :-------------------: |
|
||||||
| ![lin-badge] | ![win-badge] |
|
| ![lin-badge] | ![win-badge] | ![cov-badge] |
|
||||||
|
|
||||||
[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png "Travis build status"
|
[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status"
|
||||||
[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status"
|
[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status"
|
||||||
[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master?svg=true "AppVeyor build status"
|
[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status"
|
||||||
[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status"
|
[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status"
|
||||||
|
[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master
|
||||||
|
[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@ -28,7 +33,7 @@ RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](
|
|||||||
|
|
||||||
* RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code.
|
* RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code.
|
||||||
|
|
||||||
* RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.1 for acceleration.
|
* RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration.
|
||||||
|
|
||||||
* RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL.
|
* RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL.
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 高效的C++ JSON解析/生成器,提供SAX及DOM风格API
|
||||||
|
|
||||||
Tencent is pleased to support the open source community by making RapidJSON available.
|
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. All rights reserved.
|
||||||
@ -10,13 +14,26 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
|
|||||||
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/)
|
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/)
|
||||||
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI,但不含API参考手册。
|
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI,但不含API参考手册。
|
||||||
|
|
||||||
|
## Build 状态
|
||||||
|
|
||||||
|
| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] |
|
||||||
|
| :---------------: | :-----------------: | :-------------------: |
|
||||||
|
| ![lin-badge] | ![win-badge] | ![cov-badge] |
|
||||||
|
|
||||||
|
[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status"
|
||||||
|
[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status"
|
||||||
|
[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status"
|
||||||
|
[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status"
|
||||||
|
[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master
|
||||||
|
[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
|
|
||||||
RapidJSON是一个C++的JSON解析器及生成器。它的灵感来自[RapidXml](http://rapidxml.sourceforge.net/)。
|
RapidJSON是一个C++的JSON解析器及生成器。它的灵感来自[RapidXml](http://rapidxml.sourceforge.net/)。
|
||||||
|
|
||||||
* RapidJSON小而全。它同时支持SAX和DOM风格的API。SAX解析器只有约500行代码。
|
* RapidJSON小而全。它同时支持SAX和DOM风格的API。SAX解析器只有约500行代码。
|
||||||
|
|
||||||
* RapidJSON快。它的性能可与`strlen()`相比。可支持SSE2/SSE4.1加速。
|
* RapidJSON快。它的性能可与`strlen()`相比。可支持SSE2/SSE4.2加速。
|
||||||
|
|
||||||
* RapidJSON独立。它不依赖于BOOST等外部库。它甚至不依赖于STL。
|
* RapidJSON独立。它不依赖于BOOST等外部库。它甚至不依赖于STL。
|
||||||
|
|
||||||
@ -45,21 +62,21 @@ RapidJSON是跨平台的。以下是一些曾测试的平台/编译器组合
|
|||||||
|
|
||||||
RapidJSON是只有头文件的C++库。只需把`include/rapidjson`目录复制至系统或项目的include目录中。
|
RapidJSON是只有头文件的C++库。只需把`include/rapidjson`目录复制至系统或项目的include目录中。
|
||||||
|
|
||||||
|
RapidJSON依赖于以下软件:
|
||||||
|
* [CMake](http://www.cmake.org) 作为通用生成工具
|
||||||
|
* (optional)[Doxygen](http://www.doxygen.org)用于生成文档
|
||||||
|
* (optional)[googletest](https://code.google.com/p/googletest/)用于单元及性能测试
|
||||||
|
|
||||||
生成测试及例子的步骤:
|
生成测试及例子的步骤:
|
||||||
|
|
||||||
1. 执行 `git submodule update --init` 去获取 thirdparty submodules (google test)。
|
1. 执行 `git submodule update --init` 去获取 thirdparty submodules (google test)。
|
||||||
2. 下载 [premake4](http://industriousone.com/premake/download)。
|
2. 在rapidjson目渌下,建立一个`build`目录。
|
||||||
3. 复制 premake4 可执行文件至 `rapidjson/build` (或系统路径)。
|
3. 在`build`目录下执行`cmake ..`命令以设置生成。Windows用户可使用cmake-gui应用程序。
|
||||||
4. 进入`rapidjson/build/`目录,在Windows下执行`premake.bat`,在Linux或其他平台下执行`premake.sh`。
|
4. 在Windows下,编译生成在build目录中的solution。在Linux下,于build目录运行`make`。
|
||||||
5. 在Windows上,生成位于`rapidjson/build/vs2008/`或`/vs2010/`内的项目方案.
|
|
||||||
6. 在其他平台上,在`rapidjson/build/gmake/`目录执行GNU `make`(如 `make -f test.make config=release32`、`make -f example.make config=debug32`)。
|
|
||||||
7. 若成功,可执行文件会生成在`rapidjson/bin`目录。
|
|
||||||
|
|
||||||
生成[Doxygen](http://doxygen.org)文档的步骤:
|
成功生成后,你会在`bin`的目录下找到编译后的测试及例子可执行文件。而生成的文档将位于build下的`doc/html`目录。要执行测试,请在build下执行`make test`或`ctest`。使用`ctest -V`命令可获取详细的输出。
|
||||||
|
|
||||||
1. 下载及安装[Doxygen](http://doxygen.org/download.html)。
|
我们也可以把程序库安装至全系统中,只要在具管理權限下从build目录执行`make install`命令。这样会按系统的偏好设置安装所有文件。当安装RapidJSON后,其他的CMake项目需要使用它时,可以通过在`CMakeLists.txt`加入一句`find_package(RapidJSON)`。
|
||||||
2. 在顶层目录执行`doxygen build/Doxyfile`。
|
|
||||||
3. 在`doc/html`浏览文档。
|
|
||||||
|
|
||||||
## 用法一览
|
## 用法一览
|
||||||
|
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "perftest.h"
|
#include "perftest.h"
|
||||||
|
|
||||||
@ -768,7 +762,7 @@ template <typename Writer>
|
|||||||
void itoa_Writer_StringBufferVerify() {
|
void itoa_Writer_StringBufferVerify() {
|
||||||
rapidjson::StringBuffer sb;
|
rapidjson::StringBuffer sb;
|
||||||
Writer writer(sb);
|
Writer writer(sb);
|
||||||
for (int j = 0; j < randvalCount; j++) {
|
for (size_t j = 0; j < randvalCount; j++) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "%d", randval[j]);
|
sprintf(buffer, "%d", randval[j]);
|
||||||
writer.WriteInt(randval[j]);
|
writer.WriteInt(randval[j]);
|
||||||
@ -780,7 +774,7 @@ void itoa_Writer_StringBufferVerify() {
|
|||||||
template <typename Writer>
|
template <typename Writer>
|
||||||
void itoa_Writer_InsituStringStreamVerify() {
|
void itoa_Writer_InsituStringStreamVerify() {
|
||||||
Writer writer;
|
Writer writer;
|
||||||
for (int j = 0; j < randvalCount; j++) {
|
for (size_t j = 0; j < randvalCount; j++) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "%d", randval[j]);
|
sprintf(buffer, "%d", randval[j]);
|
||||||
char buffer2[32];
|
char buffer2[32];
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "perftest.h"
|
#include "perftest.h"
|
||||||
|
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#ifndef PERFTEST_H_
|
#ifndef PERFTEST_H_
|
||||||
#define PERFTEST_H_
|
#define PERFTEST_H_
|
||||||
@ -71,9 +65,20 @@ public:
|
|||||||
PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
|
PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
FILE *fp = fopen(filename_ = "data/sample.json", "rb");
|
|
||||||
if (!fp)
|
const char *paths[] = {
|
||||||
fp = fopen(filename_ = "../../bin/data/sample.json", "rb");
|
"data/sample.json",
|
||||||
|
"bin/data/sample.json",
|
||||||
|
"../bin/data/sample.json",
|
||||||
|
"../../bin/data/sample.json",
|
||||||
|
"../../../bin/data/sample.json"
|
||||||
|
};
|
||||||
|
FILE *fp = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
|
fp = fopen(filename_ = paths[i], "rb");
|
||||||
|
if (fp)
|
||||||
|
break;
|
||||||
|
}
|
||||||
ASSERT_TRUE(fp != 0);
|
ASSERT_TRUE(fp != 0);
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "perftest.h"
|
#include "perftest.h"
|
||||||
|
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "perftest.h"
|
#include "perftest.h"
|
||||||
|
|
||||||
@ -26,7 +20,6 @@
|
|||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
#include "rapidjson/prettywriter.h"
|
#include "rapidjson/prettywriter.h"
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
#include "rapidjson/filestream.h"
|
|
||||||
#include "rapidjson/filereadstream.h"
|
#include "rapidjson/filereadstream.h"
|
||||||
#include "rapidjson/encodedstream.h"
|
#include "rapidjson/encodedstream.h"
|
||||||
#include "rapidjson/memorystream.h"
|
#include "rapidjson/memorystream.h"
|
||||||
@ -324,17 +317,6 @@ TEST_F(RapidJson, UTF8_Validate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated.
|
|
||||||
//TEST_F(RapidJson, FileStream_Read) {
|
|
||||||
// for (size_t i = 0; i < kTrialCount; i++) {
|
|
||||||
// FILE *fp = fopen(filename_, "rb");
|
|
||||||
// FileStream s(fp);
|
|
||||||
// while (s.Take() != '\0')
|
|
||||||
// ;
|
|
||||||
// fclose(fp);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
TEST_F(RapidJson, FileReadStream) {
|
TEST_F(RapidJson, FileReadStream) {
|
||||||
for (size_t i = 0; i < kTrialCount; i++) {
|
for (size_t i = 0; i < kTrialCount; i++) {
|
||||||
FILE *fp = fopen(filename_, "rb");
|
FILE *fp = fopen(filename_, "rb");
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
set(UNITTEST_SOURCES
|
set(UNITTEST_SOURCES
|
||||||
|
allocatorstest.cpp
|
||||||
bigintegertest.cpp
|
bigintegertest.cpp
|
||||||
documenttest.cpp
|
documenttest.cpp
|
||||||
encodedstreamtest.cpp
|
encodedstreamtest.cpp
|
||||||
encodingstest.cpp
|
encodingstest.cpp
|
||||||
filestreamtest.cpp
|
filestreamtest.cpp
|
||||||
|
itoatest.cpp
|
||||||
jsoncheckertest.cpp
|
jsoncheckertest.cpp
|
||||||
namespacetest.cpp
|
namespacetest.cpp
|
||||||
|
<<<<<<< HEAD
|
||||||
pointertest.cpp
|
pointertest.cpp
|
||||||
|
=======
|
||||||
|
prettywritertest.cpp
|
||||||
|
>>>>>>> master
|
||||||
readertest.cpp
|
readertest.cpp
|
||||||
|
simdtest.cpp
|
||||||
stringbuffertest.cpp
|
stringbuffertest.cpp
|
||||||
strtodtest.cpp
|
strtodtest.cpp
|
||||||
unittest.cpp
|
unittest.cpp
|
||||||
@ -15,9 +22,9 @@ set(UNITTEST_SOURCES
|
|||||||
writertest.cpp)
|
writertest.cpp)
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Weffc++ -Wswitch-default")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Weffc++ -Wswitch-default")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
|
||||||
endif()
|
endif()
|
||||||
@ -36,8 +43,9 @@ add_test(NAME unittest
|
|||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
|
# Not running SIMD.* unit test cases for Valgrind
|
||||||
add_test(NAME valgrind_unittest
|
add_test(NAME valgrind_unittest
|
||||||
COMMAND valgrind --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest
|
COMMAND valgrind --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.*
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
60
test/unittest/allocatorstest.cpp
Normal file
60
test/unittest/allocatorstest.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "unittest.h"
|
||||||
|
|
||||||
|
#include "rapidjson/allocators.h"
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
template <typename Allocator>
|
||||||
|
void TestAllocator(Allocator& a) {
|
||||||
|
EXPECT_TRUE(a.Malloc(0) == 0);
|
||||||
|
|
||||||
|
uint8_t* p = (uint8_t*)a.Malloc(100);
|
||||||
|
EXPECT_TRUE(p != 0);
|
||||||
|
for (size_t i = 0; i < 100; i++)
|
||||||
|
p[i] = (uint8_t)i;
|
||||||
|
|
||||||
|
// Expand
|
||||||
|
uint8_t* q = (uint8_t*)a.Realloc(p, 100, 200);
|
||||||
|
EXPECT_TRUE(q != 0);
|
||||||
|
for (size_t i = 0; i < 100; i++)
|
||||||
|
EXPECT_EQ(i, q[i]);
|
||||||
|
for (size_t i = 100; i < 200; i++)
|
||||||
|
q[i] = (uint8_t)i;
|
||||||
|
|
||||||
|
// Shrink
|
||||||
|
uint8_t *r = (uint8_t*)a.Realloc(q, 200, 150);
|
||||||
|
EXPECT_TRUE(r != 0);
|
||||||
|
for (size_t i = 0; i < 150; i++)
|
||||||
|
EXPECT_EQ(i, r[i]);
|
||||||
|
|
||||||
|
Allocator::Free(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Allocator, CrtAllocator) {
|
||||||
|
CrtAllocator a;
|
||||||
|
TestAllocator(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Allocator, MemoryPoolAllocator) {
|
||||||
|
MemoryPoolAllocator<> a;
|
||||||
|
TestAllocator(a);
|
||||||
|
|
||||||
|
for (int i = 1; i < 1000; i++) {
|
||||||
|
EXPECT_TRUE(a.Malloc(i) != 0);
|
||||||
|
EXPECT_LE(a.Size(), a.Capacity());
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
@ -28,13 +22,11 @@
|
|||||||
|
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
template <typename Allocator, typename StackAllocator>
|
template <typename DocumentType>
|
||||||
void ParseTest() {
|
void ParseCheck(DocumentType& doc) {
|
||||||
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
|
|
||||||
typedef typename DocumentType::ValueType ValueType;
|
typedef typename DocumentType::ValueType ValueType;
|
||||||
DocumentType doc;
|
|
||||||
|
|
||||||
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
|
EXPECT_FALSE(doc.HasParseError());
|
||||||
|
|
||||||
EXPECT_TRUE(doc.IsObject());
|
EXPECT_TRUE(doc.IsObject());
|
||||||
|
|
||||||
@ -63,7 +55,7 @@ void ParseTest() {
|
|||||||
EXPECT_TRUE(doc.HasMember("pi"));
|
EXPECT_TRUE(doc.HasMember("pi"));
|
||||||
const ValueType& pi = doc["pi"];
|
const ValueType& pi = doc["pi"];
|
||||||
EXPECT_TRUE(pi.IsNumber());
|
EXPECT_TRUE(pi.IsNumber());
|
||||||
EXPECT_EQ(3.1416, pi.GetDouble());
|
EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
|
||||||
|
|
||||||
EXPECT_TRUE(doc.HasMember("a"));
|
EXPECT_TRUE(doc.HasMember("a"));
|
||||||
const ValueType& a = doc["a"];
|
const ValueType& a = doc["a"];
|
||||||
@ -73,6 +65,28 @@ void ParseTest() {
|
|||||||
EXPECT_EQ(i + 1, a[i].GetUint());
|
EXPECT_EQ(i + 1, a[i].GetUint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Allocator, typename StackAllocator>
|
||||||
|
void ParseTest() {
|
||||||
|
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
|
||||||
|
DocumentType doc;
|
||||||
|
|
||||||
|
const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
|
||||||
|
|
||||||
|
doc.Parse(json);
|
||||||
|
ParseCheck(doc);
|
||||||
|
|
||||||
|
doc.SetNull();
|
||||||
|
StringStream s(json);
|
||||||
|
doc.template ParseStream<0>(s);
|
||||||
|
ParseCheck(doc);
|
||||||
|
|
||||||
|
doc.SetNull();
|
||||||
|
char *buffer = strdup(json);
|
||||||
|
doc.ParseInsitu(buffer);
|
||||||
|
ParseCheck(doc);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Document, Parse) {
|
TEST(Document, Parse) {
|
||||||
ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
|
ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
|
||||||
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
|
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
|
||||||
@ -81,14 +95,21 @@ TEST(Document, Parse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static FILE* OpenEncodedFile(const char* filename) {
|
static FILE* OpenEncodedFile(const char* filename) {
|
||||||
|
const char *paths[] = {
|
||||||
|
"encodings/%s",
|
||||||
|
"bin/encodings/%s",
|
||||||
|
"../bin/encodings/%s",
|
||||||
|
"../../bin/encodings/%s",
|
||||||
|
"../../../bin/encodings/%s"
|
||||||
|
};
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
sprintf(buffer, "encodings/%s", filename);
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
FILE *fp = fopen(buffer, "rb");
|
sprintf(buffer, paths[i], filename);
|
||||||
if (!fp) {
|
FILE *fp = fopen(buffer, "rb");
|
||||||
sprintf(buffer, "../../bin/encodings/%s", filename);
|
if (fp)
|
||||||
fp = fopen(buffer, "rb");
|
return fp;
|
||||||
}
|
}
|
||||||
return fp;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Document, ParseStream_EncodedInputStream) {
|
TEST(Document, ParseStream_EncodedInputStream) {
|
||||||
@ -223,6 +244,10 @@ TEST(Document, UserBuffer) {
|
|||||||
EXPECT_FALSE(doc.HasParseError());
|
EXPECT_FALSE(doc.HasParseError());
|
||||||
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
|
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
|
||||||
EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
|
EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
|
||||||
|
|
||||||
|
// Cover MemoryPoolAllocator::Capacity()
|
||||||
|
EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity());
|
||||||
|
EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 226: Value of string type should not point to NULL
|
// Issue 226: Value of string type should not point to NULL
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/filereadstream.h"
|
#include "rapidjson/filereadstream.h"
|
||||||
@ -47,14 +41,21 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static FILE* Open(const char* filename) {
|
static FILE* Open(const char* filename) {
|
||||||
|
const char *paths[] = {
|
||||||
|
"encodings/%s",
|
||||||
|
"bin/encodings/%s",
|
||||||
|
"../bin/encodings/%s",
|
||||||
|
"../../bin/encodings/%s",
|
||||||
|
"../../../bin/encodings/%s"
|
||||||
|
};
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
sprintf(buffer, "encodings/%s", filename);
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
FILE *fp = fopen(buffer, "rb");
|
sprintf(buffer, paths[i], filename);
|
||||||
if (!fp) {
|
FILE *fp = fopen(buffer, "rb");
|
||||||
sprintf(buffer, "../../bin/encodings/%s", filename);
|
if (fp)
|
||||||
fp = fopen(buffer, "rb");
|
return fp;
|
||||||
}
|
}
|
||||||
return fp;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ReadFile(const char* filename, bool appendPath, size_t* outLength) {
|
static char *ReadFile(const char* filename, bool appendPath, size_t* outLength) {
|
||||||
@ -112,10 +113,11 @@ protected:
|
|||||||
}
|
}
|
||||||
EXPECT_EQ('\0', s.Peek());
|
EXPECT_EQ('\0', s.Peek());
|
||||||
free(data);
|
free(data);
|
||||||
|
EXPECT_EQ(size, eis.Tell());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAutoUTFInputStream(const char *filename) {
|
void TestAutoUTFInputStream(const char *filename, bool expectHasBOM) {
|
||||||
// Test FileReadStream
|
// Test FileReadStream
|
||||||
{
|
{
|
||||||
char buffer[16];
|
char buffer[16];
|
||||||
@ -123,6 +125,7 @@ protected:
|
|||||||
ASSERT_TRUE(fp != 0);
|
ASSERT_TRUE(fp != 0);
|
||||||
FileReadStream fs(fp, buffer, sizeof(buffer));
|
FileReadStream fs(fp, buffer, sizeof(buffer));
|
||||||
AutoUTFInputStream<unsigned, FileReadStream> eis(fs);
|
AutoUTFInputStream<unsigned, FileReadStream> eis(fs);
|
||||||
|
EXPECT_EQ(expectHasBOM, eis.HasBOM());
|
||||||
StringStream s(json_);
|
StringStream s(json_);
|
||||||
while (eis.Peek() != '\0') {
|
while (eis.Peek() != '\0') {
|
||||||
unsigned expected, actual;
|
unsigned expected, actual;
|
||||||
@ -140,6 +143,7 @@ protected:
|
|||||||
char* data = ReadFile(filename, true, &size);
|
char* data = ReadFile(filename, true, &size);
|
||||||
MemoryStream ms(data, size);
|
MemoryStream ms(data, size);
|
||||||
AutoUTFInputStream<unsigned, MemoryStream> eis(ms);
|
AutoUTFInputStream<unsigned, MemoryStream> eis(ms);
|
||||||
|
EXPECT_EQ(expectHasBOM, eis.HasBOM());
|
||||||
StringStream s(json_);
|
StringStream s(json_);
|
||||||
|
|
||||||
while (eis.Peek() != '\0') {
|
while (eis.Peek() != '\0') {
|
||||||
@ -150,6 +154,7 @@ protected:
|
|||||||
}
|
}
|
||||||
EXPECT_EQ('\0', s.Peek());
|
EXPECT_EQ('\0', s.Peek());
|
||||||
free(data);
|
free(data);
|
||||||
|
EXPECT_EQ(size, eis.Tell());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,16 +262,25 @@ TEST_F(EncodedStreamTest, EncodedInputStream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EncodedStreamTest, AutoUTFInputStream) {
|
TEST_F(EncodedStreamTest, AutoUTFInputStream) {
|
||||||
TestAutoUTFInputStream("utf8.json");
|
TestAutoUTFInputStream("utf8.json", false);
|
||||||
TestAutoUTFInputStream("utf8bom.json");
|
TestAutoUTFInputStream("utf8bom.json", true);
|
||||||
TestAutoUTFInputStream("utf16le.json");
|
TestAutoUTFInputStream("utf16le.json", false);
|
||||||
TestAutoUTFInputStream("utf16lebom.json");
|
TestAutoUTFInputStream("utf16lebom.json",true);
|
||||||
TestAutoUTFInputStream("utf16be.json");
|
TestAutoUTFInputStream("utf16be.json", false);
|
||||||
TestAutoUTFInputStream("utf16bebom.json");
|
TestAutoUTFInputStream("utf16bebom.json",true);
|
||||||
TestAutoUTFInputStream("utf32le.json");
|
TestAutoUTFInputStream("utf32le.json", false);
|
||||||
TestAutoUTFInputStream("utf32lebom.json");
|
TestAutoUTFInputStream("utf32lebom.json",true);
|
||||||
TestAutoUTFInputStream("utf32be.json");
|
TestAutoUTFInputStream("utf32be.json", false);
|
||||||
TestAutoUTFInputStream("utf32bebom.json");
|
TestAutoUTFInputStream("utf32bebom.json", true);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Auto detection fail, use user defined UTF type
|
||||||
|
const char json[] = "{ }";
|
||||||
|
MemoryStream ms(json, sizeof(json));
|
||||||
|
AutoUTFInputStream<unsigned, MemoryStream> eis(ms, kUTF8);
|
||||||
|
EXPECT_FALSE(eis.HasBOM());
|
||||||
|
EXPECT_EQ(kUTF8, eis.GetType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EncodedStreamTest, EncodedOutputStream) {
|
TEST_F(EncodedStreamTest, EncodedOutputStream) {
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/filereadstream.h"
|
#include "rapidjson/filereadstream.h"
|
||||||
|
@ -1,25 +1,18 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/filestream.h"
|
|
||||||
#include "rapidjson/filereadstream.h"
|
#include "rapidjson/filereadstream.h"
|
||||||
#include "rapidjson/filewritestream.h"
|
#include "rapidjson/filewritestream.h"
|
||||||
#include "rapidjson/encodedstream.h"
|
#include "rapidjson/encodedstream.h"
|
||||||
@ -31,9 +24,21 @@ public:
|
|||||||
FileStreamTest() : filename_(), json_(), length_() {}
|
FileStreamTest() : filename_(), json_(), length_() {}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
FILE *fp = fopen(filename_ = "data/sample.json", "rb");
|
const char *paths[] = {
|
||||||
if (!fp)
|
"data/sample.json",
|
||||||
fp = fopen(filename_ = "../../bin/data/sample.json", "rb");
|
"bin/data/sample.json",
|
||||||
|
"../bin/data/sample.json",
|
||||||
|
"../../bin/data/sample.json",
|
||||||
|
"../../../bin/data/sample.json"
|
||||||
|
};
|
||||||
|
FILE* fp = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
|
fp = fopen(paths[i], "rb");
|
||||||
|
if (fp) {
|
||||||
|
filename_ = paths[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
ASSERT_TRUE(fp != 0);
|
ASSERT_TRUE(fp != 0);
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
@ -60,24 +65,6 @@ protected:
|
|||||||
size_t length_;
|
size_t length_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Deprecated
|
|
||||||
//TEST_F(FileStreamTest, FileStream_Read) {
|
|
||||||
// FILE *fp = fopen(filename_, "rb");
|
|
||||||
// ASSERT_TRUE(fp != 0);
|
|
||||||
// FileStream s(fp);
|
|
||||||
//
|
|
||||||
// for (size_t i = 0; i < length_; i++) {
|
|
||||||
// EXPECT_EQ(json_[i], s.Peek());
|
|
||||||
// EXPECT_EQ(json_[i], s.Peek()); // 2nd time should be the same
|
|
||||||
// EXPECT_EQ(json_[i], s.Take());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// EXPECT_EQ(length_, s.Tell());
|
|
||||||
// EXPECT_EQ('\0', s.Peek());
|
|
||||||
//
|
|
||||||
// fclose(fp);
|
|
||||||
//}
|
|
||||||
|
|
||||||
TEST_F(FileStreamTest, FileReadStream) {
|
TEST_F(FileStreamTest, FileReadStream) {
|
||||||
FILE *fp = fopen(filename_, "rb");
|
FILE *fp = fopen(filename_, "rb");
|
||||||
ASSERT_TRUE(fp != 0);
|
ASSERT_TRUE(fp != 0);
|
||||||
|
158
test/unittest/itoatest.cpp
Normal file
158
test/unittest/itoatest.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "unittest.h"
|
||||||
|
#include "rapidjson/internal/itoa.h"
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(type-limits)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace rapidjson::internal;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Traits {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Traits<uint32_t> {
|
||||||
|
enum { kBufferSize = 11 };
|
||||||
|
enum { kMaxDigit = 10 };
|
||||||
|
static uint32_t Negate(uint32_t x) { return x; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Traits<int32_t> {
|
||||||
|
enum { kBufferSize = 12 };
|
||||||
|
enum { kMaxDigit = 10 };
|
||||||
|
static int32_t Negate(int32_t x) { return -x; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Traits<uint64_t> {
|
||||||
|
enum { kBufferSize = 21 };
|
||||||
|
enum { kMaxDigit = 20 };
|
||||||
|
static uint64_t Negate(uint64_t x) { return x; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Traits<int64_t> {
|
||||||
|
enum { kBufferSize = 22 };
|
||||||
|
enum { kMaxDigit = 20 };
|
||||||
|
static int64_t Negate(int64_t x) { return -x; };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) {
|
||||||
|
char buffer1[Traits<T>::kBufferSize];
|
||||||
|
char buffer2[Traits<T>::kBufferSize];
|
||||||
|
|
||||||
|
f(value, buffer1);
|
||||||
|
*g(value, buffer2) = '\0';
|
||||||
|
|
||||||
|
|
||||||
|
EXPECT_STREQ(buffer1, buffer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) {
|
||||||
|
// Boundary cases
|
||||||
|
VerifyValue<T>(0, f, g);
|
||||||
|
VerifyValue<T>(std::numeric_limits<T>::min(), f, g);
|
||||||
|
VerifyValue<T>(std::numeric_limits<T>::max(), f, g);
|
||||||
|
|
||||||
|
// 2^n - 1, 2^n, 10^n - 1, 10^n until overflow
|
||||||
|
for (uint32_t power = 2; power <= 10; power += 8) {
|
||||||
|
T i = 1, last;
|
||||||
|
do {
|
||||||
|
VerifyValue<T>(i - 1, f, g);
|
||||||
|
VerifyValue<T>(i, f, g);
|
||||||
|
if (std::numeric_limits<T>::min() < 0) {
|
||||||
|
VerifyValue<T>(Traits<T>::Negate(i), f, g);
|
||||||
|
VerifyValue<T>(Traits<T>::Negate(i + 1), f, g);
|
||||||
|
}
|
||||||
|
last = i;
|
||||||
|
i *= power;
|
||||||
|
} while (last < i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void u32toa_naive(uint32_t value, char* buffer) {
|
||||||
|
char temp[10];
|
||||||
|
char *p = temp;
|
||||||
|
do {
|
||||||
|
*p++ = char(value % 10) + '0';
|
||||||
|
value /= 10;
|
||||||
|
} while (value > 0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
*buffer++ = *--p;
|
||||||
|
} while (p != temp);
|
||||||
|
|
||||||
|
*buffer = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i32toa_naive(int32_t value, char* buffer) {
|
||||||
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
|
if (value < 0) {
|
||||||
|
*buffer++ = '-';
|
||||||
|
u = ~u + 1;
|
||||||
|
}
|
||||||
|
u32toa_naive(u, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void u64toa_naive(uint64_t value, char* buffer) {
|
||||||
|
char temp[20];
|
||||||
|
char *p = temp;
|
||||||
|
do {
|
||||||
|
*p++ = char(value % 10) + '0';
|
||||||
|
value /= 10;
|
||||||
|
} while (value > 0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
*buffer++ = *--p;
|
||||||
|
} while (p != temp);
|
||||||
|
|
||||||
|
*buffer = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i64toa_naive(int64_t value, char* buffer) {
|
||||||
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
|
if (value < 0) {
|
||||||
|
*buffer++ = '-';
|
||||||
|
u = ~u + 1;
|
||||||
|
}
|
||||||
|
u64toa_naive(u, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(itoa, u32toa) {
|
||||||
|
Verify(u32toa_naive, u32toa);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(itoa, i32toa) {
|
||||||
|
Verify(i32toa_naive, i32toa);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(itoa, u64toa) {
|
||||||
|
Verify(u64toa_naive, u64toa);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(itoa, i64toa) {
|
||||||
|
Verify(i64toa_naive, i64toa);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
@ -25,9 +19,22 @@
|
|||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
|
|
||||||
static char* ReadFile(const char* filename, size_t& length) {
|
static char* ReadFile(const char* filename, size_t& length) {
|
||||||
FILE *fp = fopen(filename, "rb");
|
const char *paths[] = {
|
||||||
if (!fp)
|
"jsonchecker/%s",
|
||||||
fp = fopen(filename, "rb");
|
"bin/jsonchecker/%s",
|
||||||
|
"../bin/jsonchecker/%s",
|
||||||
|
"../../bin/jsonchecker/%s",
|
||||||
|
"../../../bin/jsonchecker/%s"
|
||||||
|
};
|
||||||
|
char buffer[1024];
|
||||||
|
FILE *fp = 0;
|
||||||
|
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
|
||||||
|
sprintf(buffer, paths[i], filename);
|
||||||
|
fp = fopen(buffer, "rb");
|
||||||
|
if (fp)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -51,17 +58,13 @@ TEST(JsonChecker, Reader) {
|
|||||||
if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting.
|
if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sprintf(filename, "jsonchecker/fail%d.json", i);
|
sprintf(filename, "fail%d.json", i);
|
||||||
size_t length;
|
size_t length;
|
||||||
char* json = ReadFile(filename, length);
|
char* json = ReadFile(filename, length);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
sprintf(filename, "../../bin/jsonchecker/fail%d.json", i);
|
printf("jsonchecker file %s not found", filename);
|
||||||
json = ReadFile(filename, length);
|
ADD_FAILURE();
|
||||||
if (!json) {
|
continue;
|
||||||
printf("jsonchecker file %s not found", filename);
|
|
||||||
ADD_FAILURE();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
|
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
|
||||||
@ -76,16 +79,12 @@ TEST(JsonChecker, Reader) {
|
|||||||
|
|
||||||
// passX.json
|
// passX.json
|
||||||
for (int i = 1; i <= 3; i++) {
|
for (int i = 1; i <= 3; i++) {
|
||||||
sprintf(filename, "jsonchecker/pass%d.json", i);
|
sprintf(filename, "pass%d.json", i);
|
||||||
size_t length;
|
size_t length;
|
||||||
char* json = ReadFile(filename, length);
|
char* json = ReadFile(filename, length);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
sprintf(filename, "../../bin/jsonchecker/pass%d.json", i);
|
printf("jsonchecker file %s not found", filename);
|
||||||
json = ReadFile(filename, length);
|
continue;
|
||||||
if (!json) {
|
|
||||||
printf("jsonchecker file %s not found", filename);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
|
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
|
161
test/unittest/prettywritertest.cpp
Normal file
161
test/unittest/prettywritertest.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "unittest.h"
|
||||||
|
#include "rapidjson/reader.h"
|
||||||
|
#include "rapidjson/prettywriter.h"
|
||||||
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/filewritestream.h"
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}";
|
||||||
|
static const char kPrettyJson[] =
|
||||||
|
"{\n"
|
||||||
|
" \"hello\": \"world\",\n"
|
||||||
|
" \"t\": true,\n"
|
||||||
|
" \"f\": false,\n"
|
||||||
|
" \"n\": null,\n"
|
||||||
|
" \"i\": 123,\n"
|
||||||
|
" \"pi\": 3.1416,\n"
|
||||||
|
" \"a\": [\n"
|
||||||
|
" 1,\n"
|
||||||
|
" 2,\n"
|
||||||
|
" 3,\n"
|
||||||
|
" -1\n"
|
||||||
|
" ],\n"
|
||||||
|
" \"u64\": 1234567890123456789,\n"
|
||||||
|
" \"i64\": -1234567890123456789\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
TEST(PrettyWriter, Basic) {
|
||||||
|
StringBuffer buffer;
|
||||||
|
PrettyWriter<StringBuffer> writer(buffer);
|
||||||
|
Reader reader;
|
||||||
|
StringStream s(kJson);
|
||||||
|
reader.Parse(s, writer);
|
||||||
|
EXPECT_STREQ(kPrettyJson, buffer.GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(PrettyWriter, SetIndent) {
|
||||||
|
StringBuffer buffer;
|
||||||
|
PrettyWriter<StringBuffer> writer(buffer);
|
||||||
|
writer.SetIndent('\t', 1);
|
||||||
|
Reader reader;
|
||||||
|
StringStream s(kJson);
|
||||||
|
reader.Parse(s, writer);
|
||||||
|
EXPECT_STREQ(
|
||||||
|
"{\n"
|
||||||
|
"\t\"hello\": \"world\",\n"
|
||||||
|
"\t\"t\": true,\n"
|
||||||
|
"\t\"f\": false,\n"
|
||||||
|
"\t\"n\": null,\n"
|
||||||
|
"\t\"i\": 123,\n"
|
||||||
|
"\t\"pi\": 3.1416,\n"
|
||||||
|
"\t\"a\": [\n"
|
||||||
|
"\t\t1,\n"
|
||||||
|
"\t\t2,\n"
|
||||||
|
"\t\t3,\n"
|
||||||
|
"\t\t-1\n"
|
||||||
|
"\t],\n"
|
||||||
|
"\t\"u64\": 1234567890123456789,\n"
|
||||||
|
"\t\"i64\": -1234567890123456789\n"
|
||||||
|
"}",
|
||||||
|
buffer.GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(PrettyWriter, String) {
|
||||||
|
StringBuffer buffer;
|
||||||
|
PrettyWriter<StringBuffer> writer(buffer);
|
||||||
|
EXPECT_TRUE(writer.StartArray());
|
||||||
|
EXPECT_TRUE(writer.String("Hello\n"));
|
||||||
|
EXPECT_TRUE(writer.EndArray());
|
||||||
|
EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
TEST(PrettyWriter, String_STDSTRING) {
|
||||||
|
StringBuffer buffer;
|
||||||
|
PrettyWriter<StringBuffer> writer(buffer);
|
||||||
|
EXPECT_TRUE(writer.StartArray());
|
||||||
|
EXPECT_TRUE(writer.String(std::string("Hello\n")));
|
||||||
|
EXPECT_TRUE(writer.EndArray());
|
||||||
|
EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class OStreamWrapper {
|
||||||
|
public:
|
||||||
|
typedef char Ch;
|
||||||
|
|
||||||
|
OStreamWrapper(std::ostream& os) : os_(os) {}
|
||||||
|
|
||||||
|
Ch Peek() const { assert(false); return '\0'; }
|
||||||
|
Ch Take() { assert(false); return '\0'; }
|
||||||
|
size_t Tell() const { return 0; }
|
||||||
|
|
||||||
|
Ch* PutBegin() { assert(false); return 0; }
|
||||||
|
void Put(Ch c) { os_.put(c); }
|
||||||
|
void Flush() { os_.flush(); }
|
||||||
|
size_t PutEnd(Ch*) { assert(false); return 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
OStreamWrapper(const OStreamWrapper&);
|
||||||
|
OStreamWrapper& operator=(const OStreamWrapper&);
|
||||||
|
|
||||||
|
std::ostream& os_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For covering PutN() generic version
|
||||||
|
TEST(PrettyWriter, OStreamWrapper) {
|
||||||
|
StringStream s(kJson);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
OStreamWrapper os(ss);
|
||||||
|
|
||||||
|
PrettyWriter<OStreamWrapper> writer(os);
|
||||||
|
|
||||||
|
Reader reader;
|
||||||
|
reader.Parse(s, writer);
|
||||||
|
|
||||||
|
std::string actual = ss.str();
|
||||||
|
EXPECT_STREQ(kPrettyJson, actual.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// For covering FileWriteStream::PutN()
|
||||||
|
TEST(PrettyWriter, FileWriteStream) {
|
||||||
|
char filename[L_tmpnam];
|
||||||
|
FILE* fp = TempFile(filename);
|
||||||
|
char buffer[16];
|
||||||
|
FileWriteStream os(fp, buffer, sizeof(buffer));
|
||||||
|
PrettyWriter<FileWriteStream> writer(os);
|
||||||
|
Reader reader;
|
||||||
|
StringStream s(kJson);
|
||||||
|
reader.Parse(s, writer);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
fp = fopen(filename, "rb");
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
size_t size = (size_t)ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
char* json = (char*)malloc(size + 1);
|
||||||
|
size_t readLength = fread(json, 1, size, fp);
|
||||||
|
json[readLength] = '\0';
|
||||||
|
fclose(fp);
|
||||||
|
remove(filename);
|
||||||
|
EXPECT_STREQ(kPrettyJson, json);
|
||||||
|
free(json);
|
||||||
|
}
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
@ -30,6 +24,7 @@ using namespace rapidjson;
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
RAPIDJSON_DIAG_OFF(float-equal)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<bool expect>
|
template<bool expect>
|
||||||
@ -187,16 +182,20 @@ static void TestParseDouble() {
|
|||||||
Reader reader; \
|
Reader reader; \
|
||||||
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code()); \
|
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code()); \
|
||||||
EXPECT_EQ(1u, h.step_); \
|
EXPECT_EQ(1u, h.step_); \
|
||||||
|
internal::Double e(x), a(h.actual_); \
|
||||||
if (fullPrecision) { \
|
if (fullPrecision) { \
|
||||||
EXPECT_EQ(x, h.actual_); \
|
EXPECT_EQ(e.Uint64Value(), a.Uint64Value()); \
|
||||||
if (x != h.actual_) \
|
if (e.Uint64Value() != a.Uint64Value()) \
|
||||||
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", str, h.actual_, x); \
|
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", str, h.actual_, x); \
|
||||||
} \
|
} \
|
||||||
else \
|
else { \
|
||||||
|
EXPECT_EQ(e.Sign(), a.Sign()); /* for 0.0 != -0.0 */ \
|
||||||
EXPECT_DOUBLE_EQ(x, h.actual_); \
|
EXPECT_DOUBLE_EQ(x, h.actual_); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_DOUBLE(fullPrecision, "0.0", 0.0);
|
TEST_DOUBLE(fullPrecision, "0.0", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "-0.0", -0.0); // For checking issue #289
|
||||||
TEST_DOUBLE(fullPrecision, "1.0", 1.0);
|
TEST_DOUBLE(fullPrecision, "1.0", 1.0);
|
||||||
TEST_DOUBLE(fullPrecision, "-1.0", -1.0);
|
TEST_DOUBLE(fullPrecision, "-1.0", -1.0);
|
||||||
TEST_DOUBLE(fullPrecision, "1.5", 1.5);
|
TEST_DOUBLE(fullPrecision, "1.5", 1.5);
|
||||||
@ -220,13 +219,19 @@ static void TestParseDouble() {
|
|||||||
TEST_DOUBLE(fullPrecision, "2.2250738585072009e-308", 2.2250738585072009e-308); // Max subnormal double
|
TEST_DOUBLE(fullPrecision, "2.2250738585072009e-308", 2.2250738585072009e-308); // Max subnormal double
|
||||||
TEST_DOUBLE(fullPrecision, "2.2250738585072014e-308", 2.2250738585072014e-308); // Min normal positive double
|
TEST_DOUBLE(fullPrecision, "2.2250738585072014e-308", 2.2250738585072014e-308); // Min normal positive double
|
||||||
TEST_DOUBLE(fullPrecision, "1.7976931348623157e+308", 1.7976931348623157e+308); // Max double
|
TEST_DOUBLE(fullPrecision, "1.7976931348623157e+308", 1.7976931348623157e+308); // Max double
|
||||||
TEST_DOUBLE(fullPrecision, "1e-10000", 0.0); // must underflow
|
TEST_DOUBLE(fullPrecision, "1e-10000", 0.0); // must underflow
|
||||||
TEST_DOUBLE(fullPrecision, "18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double)
|
TEST_DOUBLE(fullPrecision, "18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double)
|
||||||
TEST_DOUBLE(fullPrecision, "-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double)
|
TEST_DOUBLE(fullPrecision, "-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double)
|
||||||
TEST_DOUBLE(fullPrecision, "0.9868011474609375", 0.9868011474609375); // https://github.com/miloyip/rapidjson/issues/120
|
TEST_DOUBLE(fullPrecision, "0.9868011474609375", 0.9868011474609375); // https://github.com/miloyip/rapidjson/issues/120
|
||||||
TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise
|
TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise
|
||||||
TEST_DOUBLE(fullPrecision, "45913141877270640000.0", 45913141877270640000.0);
|
TEST_DOUBLE(fullPrecision, "45913141877270640000.0", 45913141877270640000.0);
|
||||||
TEST_DOUBLE(fullPrecision, "2.2250738585072011e-308", 2.2250738585072011e-308); // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
|
TEST_DOUBLE(fullPrecision, "2.2250738585072011e-308", 2.2250738585072011e-308); // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-00011111111111", 0.0); // Issue #313
|
||||||
|
TEST_DOUBLE(fullPrecision, "-1e-00011111111111", -0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-214748363", 0.0); // Maximum supported negative exponent
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-214748364", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "1e-21474836311", 0.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form
|
||||||
|
|
||||||
// Since
|
// Since
|
||||||
// abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
|
// abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
|
||||||
@ -249,6 +254,32 @@ static void TestParseDouble() {
|
|||||||
TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203124", 1.0); // previous double
|
TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203124", 1.0); // previous double
|
||||||
TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203126", 1.00000000000000022); // next double
|
TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203126", 1.00000000000000022); // next double
|
||||||
|
|
||||||
|
// Numbers from https://github.com/floitsch/double-conversion/blob/master/test/cctest/test-strtod.cc
|
||||||
|
|
||||||
|
TEST_DOUBLE(fullPrecision, "72057594037927928.0", 72057594037927928.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "72057594037927936.0", 72057594037927936.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "72057594037927932.0", 72057594037927936.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "7205759403792793199999e-5", 72057594037927928.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "7205759403792793200001e-5", 72057594037927936.0);
|
||||||
|
|
||||||
|
TEST_DOUBLE(fullPrecision, "9223372036854774784.0", 9223372036854774784.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "9223372036854775808.0", 9223372036854775808.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "9223372036854775296.0", 9223372036854775808.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "922337203685477529599999e-5", 9223372036854774784.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "922337203685477529600001e-5", 9223372036854775808.0);
|
||||||
|
|
||||||
|
TEST_DOUBLE(fullPrecision, "10141204801825834086073718800384", 10141204801825834086073718800384.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "10141204801825835211973625643008", 10141204801825835211973625643008.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "10141204801825834649023672221696", 10141204801825835211973625643008.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "1014120480182583464902367222169599999e-5", 10141204801825834086073718800384.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "1014120480182583464902367222169600001e-5", 10141204801825835211973625643008.0);
|
||||||
|
|
||||||
|
TEST_DOUBLE(fullPrecision, "5708990770823838890407843763683279797179383808", 5708990770823838890407843763683279797179383808.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "5708990770823839524233143877797980545530986496", 5708990770823839524233143877797980545530986496.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185152", 5708990770823839524233143877797980545530986496.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185151999e-3", 5708990770823838890407843763683279797179383808.0);
|
||||||
|
TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185152001e-3", 5708990770823839524233143877797980545530986496.0);
|
||||||
|
|
||||||
{
|
{
|
||||||
char n1e308[310]; // '1' followed by 308 '0'
|
char n1e308[310]; // '1' followed by 308 '0'
|
||||||
n1e308[0] = '1';
|
n1e308[0] = '1';
|
||||||
@ -258,28 +289,53 @@ static void TestParseDouble() {
|
|||||||
TEST_DOUBLE(fullPrecision, n1e308, 1E308);
|
TEST_DOUBLE(fullPrecision, n1e308, 1E308);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // Very slow
|
// Cover trimming
|
||||||
static const unsigned count = 10000000;
|
TEST_DOUBLE(fullPrecision,
|
||||||
// Random test for double
|
"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
|
||||||
|
"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
|
||||||
|
"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
|
||||||
|
"6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505"
|
||||||
|
"1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621"
|
||||||
|
"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
|
||||||
|
"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
|
||||||
|
"7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
|
||||||
|
"e-308",
|
||||||
|
2.2250738585072014e-308);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
static const unsigned count = 100; // Tested with 1000000 locally
|
||||||
Random r;
|
Random r;
|
||||||
|
Reader reader; // Reusing reader to prevent heap allocation
|
||||||
|
|
||||||
for (unsigned i = 0; i < count; i++) {
|
// Exhaustively test different exponents with random significant
|
||||||
internal::Double d;
|
for (uint64_t exp = 0; exp < 2047; exp++) {
|
||||||
do {
|
;
|
||||||
|
for (unsigned i = 0; i < count; i++) {
|
||||||
// Need to call r() in two statements for cross-platform coherent sequence.
|
// Need to call r() in two statements for cross-platform coherent sequence.
|
||||||
uint64_t u = uint64_t(r()) << 32;
|
uint64_t u = (exp << 52) | uint64_t(r() & 0x000FFFFF) << 32;
|
||||||
u |= uint64_t(r());
|
u |= uint64_t(r());
|
||||||
d = internal::Double(u);
|
internal::Double d = internal::Double(u);
|
||||||
} while (d.IsNan() || d.IsInf()/* || !d.IsNormal()*/); // Also work for subnormal now
|
|
||||||
|
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
*internal::dtoa(d.Value(), buffer) = '\0';
|
*internal::dtoa(d.Value(), buffer) = '\0';
|
||||||
TEST_DOUBLE(fullPrecision, buffer, d.Value());
|
|
||||||
|
StringStream s(buffer);
|
||||||
|
ParseDoubleHandler h;
|
||||||
|
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code());
|
||||||
|
EXPECT_EQ(1u, h.step_);
|
||||||
|
internal::Double a(h.actual_);
|
||||||
|
if (fullPrecision) {
|
||||||
|
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
||||||
|
if (d.Uint64Value() != a.Uint64Value())
|
||||||
|
printf(" String: %sn Actual: %.17gnExpected: %.17gn", buffer, h.actual_, d.Value());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EXPECT_EQ(d.Sign(), a.Sign()); /* for 0.0 != -0.0 */
|
||||||
|
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef TEST_DOUBLE
|
#undef TEST_DOUBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,6 +538,17 @@ TEST(Reader, ParseString_Transcoding) {
|
|||||||
EXPECT_EQ(StrLen(e), h.length_);
|
EXPECT_EQ(StrLen(e), h.length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Reader, ParseString_TranscodingWithValidation) {
|
||||||
|
const char* x = "\"Hello\"";
|
||||||
|
const wchar_t* e = L"Hello";
|
||||||
|
GenericStringStream<UTF8<> > is(x);
|
||||||
|
GenericReader<UTF8<>, UTF16<> > reader;
|
||||||
|
ParseStringHandler<UTF16<> > h;
|
||||||
|
reader.Parse<kParseValidateEncodingFlag>(is, h);
|
||||||
|
EXPECT_EQ(0, StrCmp<UTF16<>::Ch>(e, h.str_));
|
||||||
|
EXPECT_EQ(StrLen(e), h.length_);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Reader, ParseString_NonDestructive) {
|
TEST(Reader, ParseString_NonDestructive) {
|
||||||
StringStream s("\"Hello\\nWorld\"");
|
StringStream s("\"Hello\\nWorld\"");
|
||||||
ParseStringHandler<UTF8<> > h;
|
ParseStringHandler<UTF8<> > h;
|
||||||
@ -491,24 +558,31 @@ TEST(Reader, ParseString_NonDestructive) {
|
|||||||
EXPECT_EQ(11u, h.length_);
|
EXPECT_EQ(11u, h.length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseErrorCode TestString(const char* str) {
|
template <typename Encoding>
|
||||||
StringStream s(str);
|
ParseErrorCode TestString(const typename Encoding::Ch* str) {
|
||||||
BaseReaderHandler<> h;
|
GenericStringStream<Encoding> s(str);
|
||||||
Reader reader;
|
BaseReaderHandler<Encoding> h;
|
||||||
reader.Parse<kParseValidateEncodingFlag>(s, h);
|
GenericReader<Encoding, Encoding> reader;
|
||||||
|
reader.template Parse<kParseValidateEncodingFlag>(s, h);
|
||||||
return reader.GetParseErrorCode();
|
return reader.GetParseErrorCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Reader, ParseString_Error) {
|
TEST(Reader, ParseString_Error) {
|
||||||
#define TEST_STRING_ERROR(errorCode, str)\
|
#define TEST_STRING_ERROR(errorCode, str)\
|
||||||
EXPECT_EQ(errorCode, TestString(str))
|
EXPECT_EQ(errorCode, TestString<UTF8<> >(str))
|
||||||
|
|
||||||
#define ARRAY(...) { __VA_ARGS__ }
|
#define ARRAY(...) { __VA_ARGS__ }
|
||||||
#define TEST_STRINGENCODING_ERROR(Encoding, utype, array) \
|
#define TEST_STRINGENCODING_ERROR(Encoding, TargetEncoding, utype, array) \
|
||||||
{ \
|
{ \
|
||||||
static const utype ue[] = array; \
|
static const utype ue[] = array; \
|
||||||
static const Encoding::Ch* e = reinterpret_cast<const Encoding::Ch *>(&ue[0]); \
|
static const Encoding::Ch* e = reinterpret_cast<const Encoding::Ch *>(&ue[0]); \
|
||||||
EXPECT_EQ(kParseErrorStringInvalidEncoding, TestString(e));\
|
EXPECT_EQ(kParseErrorStringInvalidEncoding, TestString<Encoding>(e));\
|
||||||
|
/* decode error */\
|
||||||
|
GenericStringStream<Encoding> s(e);\
|
||||||
|
BaseReaderHandler<TargetEncoding> h;\
|
||||||
|
GenericReader<Encoding, TargetEncoding> reader;\
|
||||||
|
reader.Parse(s, h);\
|
||||||
|
EXPECT_EQ(kParseErrorStringInvalidEncoding, reader.GetParseErrorCode());\
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalid escape character in string.
|
// Invalid escape character in string.
|
||||||
@ -517,6 +591,10 @@ TEST(Reader, ParseString_Error) {
|
|||||||
// Incorrect hex digit after \\u escape in string.
|
// Incorrect hex digit after \\u escape in string.
|
||||||
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uABCG\"]");
|
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uABCG\"]");
|
||||||
|
|
||||||
|
// Quotation in \\u escape in string (Issue #288)
|
||||||
|
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uaaa\"]");
|
||||||
|
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uD800\\uFFF\"]");
|
||||||
|
|
||||||
// The surrogate pair in string is invalid.
|
// The surrogate pair in string is invalid.
|
||||||
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]");
|
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]");
|
||||||
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]");
|
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]");
|
||||||
@ -533,7 +611,7 @@ TEST(Reader, ParseString_Error) {
|
|||||||
char e[] = { '[', '\"', 0, '\"', ']', '\0' };
|
char e[] = { '[', '\"', 0, '\"', ']', '\0' };
|
||||||
for (unsigned char c = 0x80u; c <= 0xBFu; c++) {
|
for (unsigned char c = 0x80u; c <= 0xBFu; c++) {
|
||||||
e[2] = c;
|
e[2] = c;
|
||||||
ParseErrorCode error = TestString(e);
|
ParseErrorCode error = TestString<UTF8<> >(e);
|
||||||
EXPECT_EQ(kParseErrorStringInvalidEncoding, error);
|
EXPECT_EQ(kParseErrorStringInvalidEncoding, error);
|
||||||
if (error != kParseErrorStringInvalidEncoding)
|
if (error != kParseErrorStringInvalidEncoding)
|
||||||
std::cout << (unsigned)(unsigned char)c << std::endl;
|
std::cout << (unsigned)(unsigned char)c << std::endl;
|
||||||
@ -552,30 +630,40 @@ TEST(Reader, ParseString_Error) {
|
|||||||
// 4 Overlong sequences
|
// 4 Overlong sequences
|
||||||
|
|
||||||
// 4.1 Examples of an overlong ASCII character
|
// 4.1 Examples of an overlong ASCII character
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
||||||
|
|
||||||
// 4.2 Maximum overlong sequences
|
// 4.2 Maximum overlong sequences
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
||||||
|
|
||||||
// 4.3 Overlong representation of the NUL character
|
// 4.3 Overlong representation of the NUL character
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
|
||||||
|
|
||||||
// 5 Illegal code positions
|
// 5 Illegal code positions
|
||||||
|
|
||||||
// 5.1 Single UTF-16 surrogates
|
// 5.1 Single UTF-16 surrogates
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xA0u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xA0u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBEu, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBEu, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
||||||
|
|
||||||
|
// Malform UTF-16 sequences
|
||||||
|
TEST_STRINGENCODING_ERROR(UTF16<>, UTF8<>, wchar_t, ARRAY('[', '\"', 0xDC00, 0xDC00, '\"', ']', '\0'));
|
||||||
|
TEST_STRINGENCODING_ERROR(UTF16<>, UTF8<>, wchar_t, ARRAY('[', '\"', 0xD800, 0xD800, '\"', ']', '\0'));
|
||||||
|
|
||||||
|
// Malform UTF-32 sequence
|
||||||
|
TEST_STRINGENCODING_ERROR(UTF32<>, UTF8<>, unsigned, ARRAY('[', '\"', 0x110000, '\"', ']', '\0'));
|
||||||
|
|
||||||
|
// Malform ASCII sequence
|
||||||
|
TEST_STRINGENCODING_ERROR(ASCII<>, UTF8<>, char, ARRAY('[', '\"', char(0x80), '\"', ']', '\0'));
|
||||||
|
|
||||||
#undef ARRAY
|
#undef ARRAY
|
||||||
#undef TEST_STRINGARRAY_ERROR
|
#undef TEST_STRINGARRAY_ERROR
|
||||||
@ -655,7 +743,7 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Uint(unsigned i) { return Int(i); }
|
bool Uint(unsigned i) { return Int(i); }
|
||||||
bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; return true; }
|
bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; }
|
||||||
bool String(const char* str, size_t, bool) {
|
bool String(const char* str, size_t, bool) {
|
||||||
switch(step_) {
|
switch(step_) {
|
||||||
case 1: EXPECT_STREQ("hello", str); step_++; return true;
|
case 1: EXPECT_STREQ("hello", str); step_++; return true;
|
||||||
@ -965,6 +1053,17 @@ TEST(Reader, IterativeParsing_ErrorHandling) {
|
|||||||
TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u);
|
TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u);
|
||||||
TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u);
|
TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u);
|
||||||
TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u);
|
TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u);
|
||||||
|
TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 5u);
|
||||||
|
|
||||||
|
// Any JSON value can be a valid root element in RFC7159.
|
||||||
|
TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 2u);
|
||||||
|
TESTERRORHANDLING("truE", kParseErrorValueInvalid, 3u);
|
||||||
|
TESTERRORHANDLING("False", kParseErrorValueInvalid, 0u);
|
||||||
|
TESTERRORHANDLING("true, false", kParseErrorDocumentRootNotSingular, 4u);
|
||||||
|
TESTERRORHANDLING("false, false", kParseErrorDocumentRootNotSingular, 5u);
|
||||||
|
TESTERRORHANDLING("nulL", kParseErrorValueInvalid, 3u);
|
||||||
|
TESTERRORHANDLING("null , null", kParseErrorDocumentRootNotSingular, 5u);
|
||||||
|
TESTERRORHANDLING("1a", kParseErrorDocumentRootNotSingular, 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Encoding = UTF8<> >
|
template<typename Encoding = UTF8<> >
|
||||||
@ -1168,6 +1267,59 @@ TEST(Reader, IterativeParsing_ShortCircuit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For covering BaseReaderHandler default functions
|
||||||
|
TEST(Reader, BaseReaderHandler_Default) {
|
||||||
|
BaseReaderHandler<> h;
|
||||||
|
Reader reader;
|
||||||
|
StringStream is("[null, true, -1, 1, -1234567890123456789, 1234567890123456789, 3.14, \"s\", { \"a\" : 1 }]");
|
||||||
|
EXPECT_TRUE(reader.Parse(is, h));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int e>
|
||||||
|
struct TerminateHandler {
|
||||||
|
bool Null() { return e != 0; }
|
||||||
|
bool Bool(bool) { return e != 1; }
|
||||||
|
bool Int(int) { return e != 2; }
|
||||||
|
bool Uint(unsigned) { return e != 3; }
|
||||||
|
bool Int64(int64_t) { return e != 4; }
|
||||||
|
bool Uint64(uint64_t) { return e != 5; }
|
||||||
|
bool Double(double) { return e != 6; }
|
||||||
|
bool String(const char*, SizeType, bool) { return e != 7; }
|
||||||
|
bool StartObject() { return e != 8; }
|
||||||
|
bool Key(const char*, SizeType, bool) { return e != 9; }
|
||||||
|
bool EndObject(SizeType) { return e != 10; }
|
||||||
|
bool StartArray() { return e != 11; }
|
||||||
|
bool EndArray(SizeType) { return e != 12; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_TERMINATION(e, json)\
|
||||||
|
{\
|
||||||
|
Reader reader;\
|
||||||
|
TerminateHandler<e> h;\
|
||||||
|
StringStream is(json);\
|
||||||
|
EXPECT_FALSE(reader.Parse(is, h));\
|
||||||
|
EXPECT_EQ(kParseErrorTermination, reader.GetParseErrorCode());\
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Reader, ParseTerminationByHandler) {
|
||||||
|
TEST_TERMINATION(0, "[null");
|
||||||
|
TEST_TERMINATION(1, "[true");
|
||||||
|
TEST_TERMINATION(1, "[false");
|
||||||
|
TEST_TERMINATION(2, "[-1");
|
||||||
|
TEST_TERMINATION(3, "[1");
|
||||||
|
TEST_TERMINATION(4, "[-1234567890123456789");
|
||||||
|
TEST_TERMINATION(5, "[1234567890123456789");
|
||||||
|
TEST_TERMINATION(6, "[0.5]");
|
||||||
|
TEST_TERMINATION(7, "[\"a\"");
|
||||||
|
TEST_TERMINATION(8, "[{");
|
||||||
|
TEST_TERMINATION(9, "[{\"a\"");
|
||||||
|
TEST_TERMINATION(10, "[{}");
|
||||||
|
TEST_TERMINATION(10, "[{\"a\":1}"); // non-empty object
|
||||||
|
TEST_TERMINATION(11, "{\"a\":[");
|
||||||
|
TEST_TERMINATION(12, "{\"a\":[]");
|
||||||
|
TEST_TERMINATION(12, "{\"a\":[1]"); // non-empty array
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
68
test/unittest/simdtest.cpp
Normal file
68
test/unittest/simdtest.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2
|
||||||
|
// The unit tests prefix with SIMD should be skipped by Valgrind test
|
||||||
|
|
||||||
|
// __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.
|
||||||
|
#if defined(__SSE4_2__)
|
||||||
|
# define RAPIDJSON_SSE42
|
||||||
|
#elif defined(__SSE2__)
|
||||||
|
# define RAPIDJSON_SSE2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RAPIDJSON_NAMESPACE rapidjson_simd
|
||||||
|
|
||||||
|
#include "unittest.h"
|
||||||
|
|
||||||
|
#include "rapidjson/reader.h"
|
||||||
|
|
||||||
|
using namespace rapidjson_simd;
|
||||||
|
|
||||||
|
#ifdef RAPIDJSON_SSE2
|
||||||
|
#define SIMD_SUFFIX(name) name##_SSE2
|
||||||
|
#elif defined(RAPIDJSON_SSE42)
|
||||||
|
#define SIMD_SUFFIX(name) name##_SSE42
|
||||||
|
#else
|
||||||
|
#define SIMD_SUFFIX(name) name
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename StreamType>
|
||||||
|
void TestSkipWhitespace() {
|
||||||
|
for (int step = 1; step < 32; step++) {
|
||||||
|
char buffer[1025];
|
||||||
|
for (size_t i = 0; i < 1024; i++)
|
||||||
|
buffer[i] = " \t\r\n"[i % 4];
|
||||||
|
for (size_t i = 0; i < 1024; i += step)
|
||||||
|
buffer[i] = 'X';
|
||||||
|
buffer[1024] = '\0';
|
||||||
|
|
||||||
|
StreamType s(buffer);
|
||||||
|
size_t i = 0;
|
||||||
|
for (;;) {
|
||||||
|
SkipWhitespace(s);
|
||||||
|
if (s.Peek() == '\0')
|
||||||
|
break;
|
||||||
|
EXPECT_EQ(i, s.Tell());
|
||||||
|
EXPECT_EQ('X', s.Take());
|
||||||
|
i += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) {
|
||||||
|
TestSkipWhitespace<StringStream>();
|
||||||
|
TestSkipWhitespace<InsituStringStream>();
|
||||||
|
}
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
@ -54,6 +48,10 @@ TEST(StringBuffer, Push) {
|
|||||||
buffer.Push(5);
|
buffer.Push(5);
|
||||||
|
|
||||||
EXPECT_EQ(5u, buffer.GetSize());
|
EXPECT_EQ(5u, buffer.GetSize());
|
||||||
|
|
||||||
|
// Causes sudden expansion to make the stack's capacity equal to size
|
||||||
|
buffer.Push(65536u);
|
||||||
|
EXPECT_EQ(5u + 65536u, buffer.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringBuffer, Pop) {
|
TEST(StringBuffer, Pop) {
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
|
@ -1,28 +1,25 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
#include "rapidjson/rapidjson.h"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
|
std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl;
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
_CrtMemState memoryState = { 0 };
|
_CrtMemState memoryState = { 0 };
|
||||||
_CrtMemCheckpoint(&memoryState);
|
_CrtMemCheckpoint(&memoryState);
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#ifndef UNITTEST_H_
|
#ifndef UNITTEST_H_
|
||||||
#define UNITTEST_H_
|
#define UNITTEST_H_
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
@ -203,12 +197,28 @@ TEST(Value, EqualtoOperator) {
|
|||||||
EXPECT_TRUE(z.RemoveMember("t"));
|
EXPECT_TRUE(z.RemoveMember("t"));
|
||||||
TestUnequal(x, z);
|
TestUnequal(x, z);
|
||||||
TestEqual(y, z);
|
TestEqual(y, z);
|
||||||
y.AddMember("t", true, crtAllocator);
|
y.AddMember("t", false, crtAllocator);
|
||||||
z.AddMember("t", true, z.GetAllocator());
|
z.AddMember("t", false, z.GetAllocator());
|
||||||
|
TestUnequal(x, y);
|
||||||
|
TestUnequal(z, x);
|
||||||
|
y["t"] = true;
|
||||||
|
z["t"] = true;
|
||||||
TestEqual(x, y);
|
TestEqual(x, y);
|
||||||
TestEqual(y, z);
|
TestEqual(y, z);
|
||||||
TestEqual(z, x);
|
TestEqual(z, x);
|
||||||
|
|
||||||
|
// Swapping element order is not OK
|
||||||
|
x["a"][0].Swap(x["a"][1]);
|
||||||
|
TestUnequal(x, y);
|
||||||
|
x["a"][0].Swap(x["a"][1]);
|
||||||
|
TestEqual(x, y);
|
||||||
|
|
||||||
|
// Array of different size
|
||||||
|
x["a"].PushBack(4, allocator);
|
||||||
|
TestUnequal(x, y);
|
||||||
|
x["a"].PopBack();
|
||||||
|
TestEqual(x, y);
|
||||||
|
|
||||||
// Issue #129: compare Uint64
|
// Issue #129: compare Uint64
|
||||||
x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0));
|
x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0));
|
||||||
y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF));
|
y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF));
|
||||||
@ -229,6 +239,13 @@ void TestCopyFrom() {
|
|||||||
EXPECT_STREQ(v1.GetString(), v2.GetString());
|
EXPECT_STREQ(v1.GetString(), v2.GetString());
|
||||||
EXPECT_EQ(v1.GetString(), v2.GetString()); // string NOT copied
|
EXPECT_EQ(v1.GetString(), v2.GetString()); // string NOT copied
|
||||||
|
|
||||||
|
v1.SetString("bar", a); // copy string
|
||||||
|
v2.CopyFrom(v1, a);
|
||||||
|
EXPECT_TRUE(v1.GetType() == v2.GetType());
|
||||||
|
EXPECT_STREQ(v1.GetString(), v2.GetString());
|
||||||
|
EXPECT_NE(v1.GetString(), v2.GetString()); // string copied
|
||||||
|
|
||||||
|
|
||||||
v1.SetArray().PushBack(1234, a);
|
v1.SetArray().PushBack(1234, a);
|
||||||
v2.CopyFrom(v1, a);
|
v2.CopyFrom(v1, a);
|
||||||
EXPECT_TRUE(v2.IsArray());
|
EXPECT_TRUE(v2.IsArray());
|
||||||
@ -339,7 +356,7 @@ TEST(Value, Int) {
|
|||||||
EXPECT_EQ(1234u, x.GetUint());
|
EXPECT_EQ(1234u, x.GetUint());
|
||||||
EXPECT_EQ(1234, x.GetInt64());
|
EXPECT_EQ(1234, x.GetInt64());
|
||||||
EXPECT_EQ(1234u, x.GetUint64());
|
EXPECT_EQ(1234u, x.GetUint64());
|
||||||
EXPECT_EQ(1234, x.GetDouble());
|
EXPECT_NEAR(1234.0, x.GetDouble(), 0.0);
|
||||||
//EXPECT_EQ(1234, (int)x);
|
//EXPECT_EQ(1234, (int)x);
|
||||||
//EXPECT_EQ(1234, (unsigned)x);
|
//EXPECT_EQ(1234, (unsigned)x);
|
||||||
//EXPECT_EQ(1234, (int64_t)x);
|
//EXPECT_EQ(1234, (int64_t)x);
|
||||||
@ -397,7 +414,7 @@ TEST(Value, Uint) {
|
|||||||
EXPECT_TRUE(x.IsUint());
|
EXPECT_TRUE(x.IsUint());
|
||||||
EXPECT_TRUE(x.IsInt64());
|
EXPECT_TRUE(x.IsInt64());
|
||||||
EXPECT_TRUE(x.IsUint64());
|
EXPECT_TRUE(x.IsUint64());
|
||||||
EXPECT_EQ(1234.0, x.GetDouble()); // Number can always be cast as double but !IsDouble().
|
EXPECT_NEAR(1234.0, x.GetDouble(), 0.0); // Number can always be cast as double but !IsDouble().
|
||||||
|
|
||||||
EXPECT_FALSE(x.IsDouble());
|
EXPECT_FALSE(x.IsDouble());
|
||||||
EXPECT_FALSE(x.IsNull());
|
EXPECT_FALSE(x.IsNull());
|
||||||
@ -462,10 +479,19 @@ TEST(Value, Int64) {
|
|||||||
z.SetInt64(2147483648LL); // 2^31, cannot cast as int
|
z.SetInt64(2147483648LL); // 2^31, cannot cast as int
|
||||||
EXPECT_FALSE(z.IsInt());
|
EXPECT_FALSE(z.IsInt());
|
||||||
EXPECT_TRUE(z.IsUint());
|
EXPECT_TRUE(z.IsUint());
|
||||||
|
EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0);
|
||||||
|
|
||||||
z.SetInt64(4294967296LL); // 2^32, cannot cast as uint
|
z.SetInt64(4294967296LL); // 2^32, cannot cast as uint
|
||||||
EXPECT_FALSE(z.IsInt());
|
EXPECT_FALSE(z.IsInt());
|
||||||
EXPECT_FALSE(z.IsUint());
|
EXPECT_FALSE(z.IsUint());
|
||||||
|
EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0);
|
||||||
|
|
||||||
|
z.SetInt64(-2147483649LL); // -2^31-1, cannot cast as int
|
||||||
|
EXPECT_FALSE(z.IsInt());
|
||||||
|
EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0);
|
||||||
|
|
||||||
|
z.SetInt64(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000)));
|
||||||
|
EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Value, Uint64) {
|
TEST(Value, Uint64) {
|
||||||
@ -508,16 +534,15 @@ TEST(Value, Uint64) {
|
|||||||
|
|
||||||
z.SetUint64(9223372036854775808uLL); // 2^63 cannot cast as int64
|
z.SetUint64(9223372036854775808uLL); // 2^63 cannot cast as int64
|
||||||
EXPECT_FALSE(z.IsInt64());
|
EXPECT_FALSE(z.IsInt64());
|
||||||
|
EXPECT_EQ(9223372036854775808uLL, z.GetUint64()); // Issue 48
|
||||||
// Issue 48
|
EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble());
|
||||||
EXPECT_EQ(9223372036854775808uLL, z.GetUint64());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Value, Double) {
|
TEST(Value, Double) {
|
||||||
// Constructor with double
|
// Constructor with double
|
||||||
Value x(12.34);
|
Value x(12.34);
|
||||||
EXPECT_EQ(kNumberType, x.GetType());
|
EXPECT_EQ(kNumberType, x.GetType());
|
||||||
EXPECT_EQ(12.34, x.GetDouble());
|
EXPECT_NEAR(12.34, x.GetDouble(), 0.0);
|
||||||
EXPECT_TRUE(x.IsNumber());
|
EXPECT_TRUE(x.IsNumber());
|
||||||
EXPECT_TRUE(x.IsDouble());
|
EXPECT_TRUE(x.IsDouble());
|
||||||
|
|
||||||
@ -533,10 +558,10 @@ TEST(Value, Double) {
|
|||||||
// SetDouble()
|
// SetDouble()
|
||||||
Value z;
|
Value z;
|
||||||
z.SetDouble(12.34);
|
z.SetDouble(12.34);
|
||||||
EXPECT_EQ(12.34, z.GetDouble());
|
EXPECT_NEAR(12.34, z.GetDouble(), 0.0);
|
||||||
|
|
||||||
z = 56.78;
|
z = 56.78;
|
||||||
EXPECT_EQ(56.78, z.GetDouble());
|
EXPECT_NEAR(56.78, z.GetDouble(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Value, String) {
|
TEST(Value, String) {
|
||||||
@ -977,6 +1002,7 @@ TEST(Value, Object) {
|
|||||||
EXPECT_STREQ("Banana", x["B"].GetString());
|
EXPECT_STREQ("Banana", x["B"].GetString());
|
||||||
EXPECT_STREQ("CherryD", x[C0D].GetString());
|
EXPECT_STREQ("CherryD", x[C0D].GetString());
|
||||||
EXPECT_STREQ("CherryD", x[othername].GetString());
|
EXPECT_STREQ("CherryD", x[othername].GetString());
|
||||||
|
EXPECT_THROW(x["nonexist"], AssertException);
|
||||||
|
|
||||||
// const operator[]
|
// const operator[]
|
||||||
EXPECT_STREQ("Apple", y["A"].GetString());
|
EXPECT_STREQ("Apple", y["A"].GetString());
|
||||||
@ -1041,13 +1067,15 @@ TEST(Value, Object) {
|
|||||||
EXPECT_FALSE(citr >= itr);
|
EXPECT_FALSE(citr >= itr);
|
||||||
|
|
||||||
// RemoveMember()
|
// RemoveMember()
|
||||||
x.RemoveMember("A");
|
EXPECT_TRUE(x.RemoveMember("A"));
|
||||||
EXPECT_FALSE(x.HasMember("A"));
|
EXPECT_FALSE(x.HasMember("A"));
|
||||||
|
|
||||||
x.RemoveMember("B");
|
EXPECT_TRUE(x.RemoveMember("B"));
|
||||||
EXPECT_FALSE(x.HasMember("B"));
|
EXPECT_FALSE(x.HasMember("B"));
|
||||||
|
|
||||||
x.RemoveMember(othername);
|
EXPECT_FALSE(x.RemoveMember("nonexist"));
|
||||||
|
|
||||||
|
EXPECT_TRUE(x.RemoveMember(othername));
|
||||||
EXPECT_FALSE(x.HasMember(name));
|
EXPECT_FALSE(x.HasMember(name));
|
||||||
|
|
||||||
EXPECT_TRUE(x.MemberBegin() == x.MemberEnd());
|
EXPECT_TRUE(x.MemberBegin() == x.MemberEnd());
|
||||||
@ -1237,3 +1265,46 @@ TEST(Value, AllocateShortString) {
|
|||||||
TestShortStringOptimization("123456789012345"); // edge case: 15 chars in 64-bit mode (=> short string)
|
TestShortStringOptimization("123456789012345"); // edge case: 15 chars in 64-bit mode (=> short string)
|
||||||
TestShortStringOptimization("1234567890123456"); // edge case: 16 chars in 64-bit mode (=> regular string)
|
TestShortStringOptimization("1234567890123456"); // edge case: 16 chars in 64-bit mode (=> regular string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int e>
|
||||||
|
struct TerminateHandler {
|
||||||
|
bool Null() { return e != 0; }
|
||||||
|
bool Bool(bool) { return e != 1; }
|
||||||
|
bool Int(int) { return e != 2; }
|
||||||
|
bool Uint(unsigned) { return e != 3; }
|
||||||
|
bool Int64(int64_t) { return e != 4; }
|
||||||
|
bool Uint64(uint64_t) { return e != 5; }
|
||||||
|
bool Double(double) { return e != 6; }
|
||||||
|
bool String(const char*, SizeType, bool) { return e != 7; }
|
||||||
|
bool StartObject() { return e != 8; }
|
||||||
|
bool Key(const char*, SizeType, bool) { return e != 9; }
|
||||||
|
bool EndObject(SizeType) { return e != 10; }
|
||||||
|
bool StartArray() { return e != 11; }
|
||||||
|
bool EndArray(SizeType) { return e != 12; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_TERMINATION(e, json)\
|
||||||
|
{\
|
||||||
|
Document d; \
|
||||||
|
EXPECT_FALSE(d.Parse(json).HasParseError()); \
|
||||||
|
Reader reader; \
|
||||||
|
TerminateHandler<e> h;\
|
||||||
|
EXPECT_FALSE(d.Accept(h));\
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Value, AcceptTerminationByHandler) {
|
||||||
|
TEST_TERMINATION(0, "[null]");
|
||||||
|
TEST_TERMINATION(1, "[true]");
|
||||||
|
TEST_TERMINATION(1, "[false]");
|
||||||
|
TEST_TERMINATION(2, "[-1]");
|
||||||
|
TEST_TERMINATION(3, "[2147483648]");
|
||||||
|
TEST_TERMINATION(4, "[-1234567890123456789]");
|
||||||
|
TEST_TERMINATION(5, "[9223372036854775808]");
|
||||||
|
TEST_TERMINATION(6, "[0.5]");
|
||||||
|
TEST_TERMINATION(7, "[\"a\"]");
|
||||||
|
TEST_TERMINATION(8, "[{}]");
|
||||||
|
TEST_TERMINATION(9, "[{\"a\":1}]");
|
||||||
|
TEST_TERMINATION(10, "[{}]");
|
||||||
|
TEST_TERMINATION(11, "{\"a\":[]}");
|
||||||
|
TEST_TERMINATION(12, "{\"a\":[]}");
|
||||||
|
}
|
||||||
|
@ -1,22 +1,16 @@
|
|||||||
// Copyright (C) 2011 Milo Yip
|
// 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.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
// 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
|
// http://opensource.org/licenses/MIT
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// specific language governing permissions and limitations under the License.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
|
|
||||||
@ -46,7 +40,7 @@ TEST(Writer, Compact) {
|
|||||||
StringBuffer buffer; \
|
StringBuffer buffer; \
|
||||||
Writer<StringBuffer> writer(buffer); \
|
Writer<StringBuffer> writer(buffer); \
|
||||||
Reader reader; \
|
Reader reader; \
|
||||||
reader.Parse<0>(s, writer); \
|
reader.Parse<kParseFullPrecisionFlag>(s, writer); \
|
||||||
EXPECT_STREQ(json, buffer.GetString()); \
|
EXPECT_STREQ(json, buffer.GetString()); \
|
||||||
EXPECT_TRUE(writer.IsComplete()); \
|
EXPECT_TRUE(writer.IsComplete()); \
|
||||||
}
|
}
|
||||||
@ -89,10 +83,27 @@ TEST(Writer, String) {
|
|||||||
TEST_ROUNDTRIP("[\"Hello\"]");
|
TEST_ROUNDTRIP("[\"Hello\"]");
|
||||||
TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
|
TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
|
||||||
TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
|
TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
writer.String(std::string("Hello\n"));
|
||||||
|
EXPECT_STREQ("\"Hello\\n\"", buffer.GetString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Writer, Double) {
|
TEST(Writer, Double) {
|
||||||
TEST_ROUNDTRIP("[1.2345,1.2345678,0.123456789012,1234567.8]");
|
TEST_ROUNDTRIP("[1.2345,1.2345678,0.123456789012,1234567.8]");
|
||||||
|
TEST_ROUNDTRIP("0.0");
|
||||||
|
TEST_ROUNDTRIP("-0.0"); // Issue #289
|
||||||
|
TEST_ROUNDTRIP("1e30");
|
||||||
|
TEST_ROUNDTRIP("1.0");
|
||||||
|
TEST_ROUNDTRIP("5e-324"); // Min subnormal positive double
|
||||||
|
TEST_ROUNDTRIP("2.225073858507201e-308"); // Max subnormal positive double
|
||||||
|
TEST_ROUNDTRIP("2.2250738585072014e-308"); // Min normal positive double
|
||||||
|
TEST_ROUNDTRIP("1.7976931348623157e308"); // Max double
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +163,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST(Writer, OStreamWrapper) {
|
TEST(Writer, OStreamWrapper) {
|
||||||
StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ");
|
StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"u64\": 1234567890123456789, \"i64\":-1234567890123456789 } ");
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
OStreamWrapper os(ss);
|
OStreamWrapper os(ss);
|
||||||
@ -163,7 +174,7 @@ TEST(Writer, OStreamWrapper) {
|
|||||||
reader.Parse<0>(s, writer);
|
reader.Parse<0>(s, writer);
|
||||||
|
|
||||||
std::string actual = ss.str();
|
std::string actual = ss.str();
|
||||||
EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", actual.c_str());
|
EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}", actual.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Writer, AssertRootMayBeAnyValue) {
|
TEST(Writer, AssertRootMayBeAnyValue) {
|
||||||
@ -306,3 +317,61 @@ TEST(Writer, RootValueIsComplete) {
|
|||||||
T(writer.String(""));
|
T(writer.String(""));
|
||||||
#undef T
|
#undef T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Writer, InvalidEncoding) {
|
||||||
|
// Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
|
||||||
|
{
|
||||||
|
GenericStringBuffer<UTF16<> > buffer;
|
||||||
|
Writer<GenericStringBuffer<UTF16<> >, UTF8<>, UTF16<> > writer(buffer);
|
||||||
|
writer.StartArray();
|
||||||
|
EXPECT_FALSE(writer.String("\xfe"));
|
||||||
|
EXPECT_FALSE(writer.String("\xff"));
|
||||||
|
EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
|
||||||
|
writer.EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail in encoding
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer, UTF32<> > writer(buffer);
|
||||||
|
static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
|
||||||
|
EXPECT_FALSE(writer.String(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail in unicode escaping in ASCII output
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer, UTF32<>, ASCII<> > writer(buffer);
|
||||||
|
static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
|
||||||
|
EXPECT_FALSE(writer.String(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Writer, InvalidEventSequence) {
|
||||||
|
// {]
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
writer.StartObject();
|
||||||
|
EXPECT_THROW(writer.EndArray(), AssertException);
|
||||||
|
EXPECT_FALSE(writer.IsComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [}
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
writer.StartArray();
|
||||||
|
EXPECT_THROW(writer.EndObject(), AssertException);
|
||||||
|
EXPECT_FALSE(writer.IsComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
// { 1:
|
||||||
|
{
|
||||||
|
StringBuffer buffer;
|
||||||
|
Writer<StringBuffer> writer(buffer);
|
||||||
|
writer.StartObject();
|
||||||
|
EXPECT_THROW(writer.Int(1), AssertException);
|
||||||
|
EXPECT_FALSE(writer.IsComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user