Merge branch 'master' into json-pointer

Conflicts:
	test/unittest/CMakeLists.txt
This commit is contained in:
miloyip 2015-05-03 20:27:21 +08:00
commit 7fc716006f
62 changed files with 1551 additions and 813 deletions

View File

@ -18,8 +18,10 @@ env:
before_install:
- 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 [ "$CC" = "gcc" ] && [ "$CONF" = "debug" ]; then sudo pip install cpp-coveralls; export GCOV_FLAGS='--coverage'; fi
install: true
@ -34,7 +36,9 @@ before_script:
-DRAPIDJSON_HAS_STDSTRING=ON
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=$CONF
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS" ..)
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS"
-DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS
..)
script:
- cd build
@ -42,3 +46,6 @@ script:
- make examples
- ctest -V `[ "$CONF" = "release" ] || echo "-E perftest"`
- 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
View 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

View File

@ -3,9 +3,9 @@ SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
PROJECT(RapidJSON CXX)
set(LIB_MAJOR_VERSION "0")
set(LIB_MINOR_VERSION "12")
set(LIB_PATCH_VERSION "0")
set(LIB_MAJOR_VERSION "1")
set(LIB_MINOR_VERSION "0")
set(LIB_PATCH_VERSION "1")
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
# 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_EXAMPLES "Build rapidjson examples." 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)
if(RAPIDJSON_HAS_STDSTRING)

View File

@ -1,9 +1,14 @@
SET(GTEST_SEARCH_PATH
"${GTEST_SOURCE_DIR}"
"${CMAKE_SOURCE_DIR}/thirdparty/gtest")
IF(UNIX)
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()
FIND_PATH(GTEST_SOURCE_DIR
@ -15,8 +20,10 @@ FIND_PATH(GTEST_SOURCE_DIR
FIND_PATH(GTEST_INCLUDE_DIR
NAMES gtest/gtest.h
PATH_SUFFIXES include
HINTS ${GTEST_SOURCE_DIR}
PATHS ${GTEST_SEARCH_PATH})
INCLUDE(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GTestSrc DEFAULT_MSG
GTEST_SOURCE_DIR
GTEST_INCLUDE_DIR)

View File

@ -1,4 +1,4 @@
version: 0.12.{build}
version: 1.0.1.{build}
configuration:
- Debug

View File

@ -84,29 +84,25 @@ template <typename InputStream>
GenericDocument& GenericDocument::ParseStream(InputStream& is);
// (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>
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);
// (7) Normal parsing of a string
// (6) Normal parsing of a string
template <unsigned parseFlags, typename SourceEncoding>
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>
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);
~~~~~~~~~~
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:

View File

@ -84,29 +84,25 @@ template <typename InputStream>
GenericDocument& GenericDocument::ParseStream(InputStream& is);
// (4) 原位解析
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
// (5) 原位解析使用Document的编码
template <unsigned parseFlags>
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
// (6) 原位解析,使用缺省标志
// (5) 原位解析,使用缺省标志
GenericDocument& GenericDocument::ParseInsitu(Ch* str);
// (7) 正常解析一个字符串
// (6) 正常解析一个字符串
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& GenericDocument::Parse(const Ch* str);
// (8) 正常解析一个字符串使用Document的编码
// (7) 正常解析一个字符串使用Document的编码
template <unsigned parseFlags>
GenericDocument& GenericDocument::Parse(const Ch* str);
// (9) 正常解析一个字符串,使用缺省标志
// (8) 正常解析一个字符串,使用缺省标志
GenericDocument& GenericDocument::Parse(const Ch* str);
~~~~~~~~~~
[教程](tutorial.md)中的例使用(9)去正常解析字符串。而[](stream.md)的例子使用前3个函数。我们将稍后介绍原位*In situ* 解析。
[教程](tutorial.md)中的例使用(8)去正常解析字符串。而[](stream.md)的例子使用前3个函数。我们将稍后介绍原位*In situ* 解析。
`parseFlags`是以下位标置的组合:

View File

@ -28,7 +28,7 @@
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?
@ -198,7 +198,7 @@
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?

View File

@ -198,7 +198,7 @@
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. 它会消耗许多内存么?

View File

@ -15,7 +15,7 @@
* High performance
* Use template and inline functions to reduce function call overheads.
* Internal optimized Grisu2 and floating point parsing implementations.
* Optional SSE2/SSE4.1 support.
* Optional SSE2/SSE4.2 support.
## Standard compliance

View File

@ -15,7 +15,7 @@
* 高性能
* 使用模版及内联函数去降低函数调用开销。
* 内部经优化的Grisu2及浮点数解析实现。
* 可选的SSE2/SSE4.1支持。
* 可选的SSE2/SSE4.2支持。
## 符合标准

View File

@ -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.
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}

View File

@ -18,7 +18,7 @@
(document.getElementsByClassName('contents')[0]).appendChild(dt);
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);
})();
</script>

View File

@ -192,7 +192,7 @@ Checking | Obtaining
`bool IsNumber()` | N/A
`bool IsUint()` | `unsigned GetUint()`
`bool IsInt()` | `int GetInt()`
`bool IsUint64()` | `uint64_t GetUint()`
`bool IsUint64()` | `uint64_t GetUint64()`
`bool IsInt64()` | `int64_t GetInt64()`
`bool IsDouble()` | `double GetDouble()`

View File

@ -192,7 +192,7 @@ JSON只提供一种数值类型──Number。数字可以是整数或实数。R
`bool IsNumber()` | 不适用
`bool IsUint()` | `unsigned GetUint()`
`bool IsInt()` | `int GetInt()`
`bool IsUint64()` | `uint64_t GetUint()`
`bool IsUint64()` | `uint64_t GetUint64()`
`bool IsInt64()` | `int64_t GetInt64()`
`bool IsDouble()` | `double GetDouble()`

View File

@ -2,7 +2,6 @@
// This example shows writing JSON string with writer directly.
#include "rapidjson/prettywriter.h" // for stringify JSON
#include "rapidjson/filestream.h" // wrapper of C stream for prettywriter as output
#include <cstdio>
#include <string>
#include <vector>
@ -144,13 +143,15 @@ int main(int, char*[]) {
employees.push_back(Employee("Percy TSE", 30, false));
FileStream s(stdout);
PrettyWriter<FileStream> writer(s); // Can also use Writer for condensed formatting
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
writer.StartArray();
for (std::vector<Employee>::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr)
employeeItr->Serialize(writer);
writer.EndArray();
puts(sb.GetString());
return 0;
}

View File

@ -3,7 +3,6 @@
#include "rapidjson/document.h" // rapidjson's DOM-style API
#include "rapidjson/prettywriter.h" // for stringify JSON
#include "rapidjson/filestream.h" // wrapper of C stream for prettywriter as output
#include <cstdio>
using namespace rapidjson;
@ -143,9 +142,10 @@ int main(int, char*[]) {
// 4. Stringify JSON
printf("\nModified JSON with reformatting:\n");
FileStream f(stdout);
PrettyWriter<FileStream> writer(f);
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
document.Accept(writer); // Accept() traverses the DOM and generates Handler events.
puts(sb.GetString());
return 0;
}

View File

@ -62,7 +62,12 @@ concept Allocator {
class CrtAllocator {
public:
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); }
static void Free(void *ptr) { std::free(ptr); }
};
@ -160,6 +165,9 @@ public:
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
@ -191,7 +199,9 @@ public:
// Realloc process: allocate and copy memory, do not free original buffer.
void* newBuffer = Malloc(newSize);
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)

View File

@ -701,8 +701,11 @@ public:
return StringEqual(rhs);
case kNumberType:
if (IsDouble() || rhs.IsDouble())
return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
if (IsDouble() || rhs.IsDouble()) {
double a = GetDouble(); // May convert from integer to double.
double b = rhs.GetDouble(); // Ditto
return a >= b && a <= b; // Prevent -Wfloat-equal
}
else
return data_.n.u64 == rhs.data_.n.u64;
@ -1457,17 +1460,14 @@ public:
case kStringType:
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
case kNumberType:
default:
RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsUint()) return handler.Uint(data_.n.u.u);
else if (IsInt64()) return handler.Int64(data_.n.i64);
else if (IsUint64()) return handler.Uint64(data_.n.u64);
else return handler.Double(data_.n.d);
default:
RAPIDJSON_ASSERT(false);
}
return false;
}
private:
@ -1580,16 +1580,24 @@ private:
// Initialize this value as array with initial data, without calling destructor.
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
flags_ = kArrayFlag;
if (count) {
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;
}
//! Initialize this value as object with initial data, without calling destructor.
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
flags_ = kObjectFlag;
if (count) {
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;
}
@ -1751,7 +1759,7 @@ public:
*/
template <unsigned parseFlags, typename InputStream>
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)
@ -1768,18 +1776,6 @@ public:
//!@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
/*! \tparam parseFlags Combination of \ref ParseFlag.
\param str Mutable zero-terminated string to be parsed.
@ -1787,7 +1783,8 @@ public:
*/
template <unsigned parseFlags>
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)
@ -1795,7 +1792,7 @@ public:
\return The document itself for fluent API.
*/
GenericDocument& ParseInsitu(Ch* str) {
return ParseInsitu<kParseDefaultFlags, Encoding>(str);
return ParseInsitu<kParseDefaultFlags>(str);
}
//!@}

View File

@ -109,6 +109,7 @@ public:
\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) {
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
DetectType();
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
takeFunc_ = f[type_];
@ -177,21 +178,8 @@ private:
}
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
switch (type_) {
case kUTF8:
// 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
}
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
}
typedef Ch (*TakeFunc)(InputByteStream& is);
@ -220,22 +208,11 @@ public:
\param putBOM Whether to write BOM at the beginning of the stream.
*/
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.
switch (type_) {
case kUTF16LE:
case kUTF16BE:
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
break;
case kUTF32LE:
case kUTF32BE:
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
break;
case kUTF8:
// Do nothing
break;
default:
RAPIDJSON_ASSERT(false); // Invalid UTFType
}
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
putFunc_ = f[type_];

View File

@ -15,6 +15,8 @@
#ifndef RAPIDJSON_ERROR_ERROR_H__
#define RAPIDJSON_ERROR_ERROR_H__
#include "../rapidjson.h"
/*! \file error.h */
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */

View File

@ -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_

View File

@ -172,13 +172,10 @@ public:
}
// Compute absolute difference of this and rhs.
// Return false if this < rhs
// Assume this != rhs
bool Difference(const BigInteger& rhs, BigInteger* out) const {
int cmp = Compare(rhs);
if (cmp == 0) {
*out = BigInteger(0);
return false;
}
RAPIDJSON_ASSERT(cmp != 0);
const BigInteger *a, *b; // Makes a > b
bool ret;
if (cmp < 0) { a = &rhs; b = this; ret = true; }
@ -269,12 +266,6 @@ private:
#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 kCapacity = kBitCount / sizeof(Type);
static const size_t kTypeBit = sizeof(Type) * 8;

View File

@ -19,12 +19,12 @@
#ifndef RAPIDJSON_DIYFP_H_
#define RAPIDJSON_DIYFP_H_
#if defined(_MSC_VER)
#include "../rapidjson.h"
#if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h>
#if defined(_M_AMD64)
#pragma intrinsic(_BitScanReverse64)
#endif
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -135,25 +135,9 @@ struct DiyFp {
double d;
uint64_t u64;
}u;
uint64_t significand = f;
int exponent = e;
while (significand > kDpHiddenBit + kDpSignificandMask) {
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);
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
return u.d;
}
@ -238,7 +222,7 @@ inline DiyFp GetCachedPower(int e, int* K) {
//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
int k = static_cast<int>(dk);
if (k != dk)
if (dk - k > 0.0)
k++;
unsigned index = static_cast<unsigned>((k >> 3) + 1);

View File

@ -21,6 +21,7 @@
#include "itoa.h" // GetDigitsLut()
#include "diyfp.h"
#include "ieee754.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -49,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
// Will not reach 10 digits in DigitGen()
//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) {
@ -59,13 +62,12 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1);
int kappa = CountDecimalDigit32(p1);
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0;
while (kappa > 0) {
uint32_t d;
uint32_t d = 0;
switch (kappa) {
case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
case 9: d = p1 / 100000000; p1 %= 100000000; break;
case 8: d = p1 / 10000000; p1 %= 10000000; 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 2: d = p1 / 10; p1 %= 10; break;
case 1: d = p1; p1 = 0; break;
default:
#if defined(_MSC_VER)
__assume(0);
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
__builtin_unreachable();
#else
d = 0;
#endif
default:;
}
if (d || *len)
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) {
if (value == 0) {
Double d(value);
if (d.IsZero()) {
if (d.Sign())
*buffer++ = '-'; // -0.0, Issue #289
buffer[0] = '0';
buffer[1] = '.';
buffer[2] = '0';

View File

@ -34,14 +34,6 @@ public:
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; }
uint64_t Significand() const { return u & kSignificandMask; }
int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
@ -49,6 +41,7 @@ public:
bool IsNan() 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 IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; }
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }

View File

@ -15,6 +15,8 @@
#ifndef RAPIDJSON_ITOA_
#define RAPIDJSON_ITOA_
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -109,12 +111,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
}
inline char* i32toa(int32_t value, char* buffer) {
uint32_t u = static_cast<uint32_t>(value);
if (value < 0) {
*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) {
@ -286,12 +289,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
}
inline char* i64toa(int64_t value, char* buffer) {
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
*buffer++ = '-';
value = -value;
u = ~u + 1;
}
return u64toa(static_cast<uint64_t>(value), buffer);
return u64toa(u, buffer);
}
} // namespace internal

View File

@ -15,9 +15,7 @@
#ifndef RAPIDJSON_INTERNAL_META_H_
#define RAPIDJSON_INTERNAL_META_H_
#ifndef RAPIDJSON_RAPIDJSON_H_
#error <rapidjson.h> not yet included. Do not include this file directly.
#endif
#include "../rapidjson.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH

View File

@ -15,6 +15,8 @@
#ifndef RAPIDJSON_POW10_
#define RAPIDJSON_POW10_
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {

View File

@ -15,6 +15,8 @@
#ifndef RAPIDJSON_INTERNAL_STACK_H_
#define RAPIDJSON_INTERNAL_STACK_H_
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {

View File

@ -15,6 +15,8 @@
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
#define RAPIDJSON_INTERNAL_STRFUNC_H_
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {

View File

@ -52,7 +52,7 @@ inline T Min3(T a, T b, T c) {
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 uint64_t bInt = db.IntegerSignificand();
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;
BigInteger delta(0);
*adjustToNegative = dS.Difference(bS, &delta);
dS.Difference(bS, &delta);
int cmp = 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) {
@ -213,24 +203,18 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
const BigInteger dInt(decimals, length);
const int dExp = (int)decimalPosition - (int)length + exp;
Double a(approx);
for (int i = 0; i < 10; i++) {
bool adjustToNegative;
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative);
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
if (cmp < 0)
return a.Value(); // within half ULP
else if (cmp == 0) {
// Round towards even
if (a.Significand() & 1)
return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
return a.NextPositiveDouble();
else
return a.Value();
}
else // adjustment
a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
}
// This should not happen, but in case there is really a bug, break the infinite-loop
return a.Value();
return a.NextPositiveDouble();
}
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
const int kMaxDecimalDigit = 780;
if ((int)length > kMaxDecimalDigit) {
exp += (int(length) - kMaxDecimalDigit);
int delta = (int(length) - kMaxDecimalDigit);
exp += delta;
decimalPosition -= delta;
length = kMaxDecimalDigit;
}

View File

@ -100,8 +100,9 @@ public:
Base::os_->Put('\n');
WriteIndent();
}
if (!Base::WriteEndObject())
return false;
bool ret = Base::WriteEndObject();
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
Base::os_->Flush();
return true;
@ -123,8 +124,9 @@ public:
Base::os_->Put('\n');
WriteIndent();
}
if (!Base::WriteEndArray())
return false;
bool ret = Base::WriteEndArray();
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
Base::os_->Flush();
return true;

View File

@ -15,9 +15,6 @@
#ifndef RAPIDJSON_RAPIDJSON_H_
#define RAPIDJSON_RAPIDJSON_H_
// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
// Version 0.1
/*!\file rapidjson.h
\brief common definitions and configuration
@ -42,6 +39,40 @@
#include <cstdlib> // malloc(), realloc(), free(), size_t
#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)
/*! \def RAPIDJSON_NAMESPACE
@ -122,9 +153,9 @@
#ifndef RAPIDJSON_FORCEINLINE
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(NDEBUG)
#define RAPIDJSON_FORCEINLINE __forceinline
#elif defined(__GNUC__) && __GNUC__ >= 4
#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
#else
#define RAPIDJSON_FORCEINLINE
@ -356,10 +387,6 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_VERSION_CODE(x,y,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

View File

@ -689,11 +689,13 @@ private:
}
else if (e == 'u') { // Unicode
unsigned codepoint = ParseHex4(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
// Handle UTF-16 surrogate pair
if (is.Take() != '\\' || is.Take() != 'u')
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
unsigned codepoint2 = ParseHex4(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
@ -894,7 +896,7 @@ private:
if (significandDigit < 17) {
d = d * 10.0 + (s.TakePush() - '0');
--expFrac;
if (d != 0.0)
if (d > 0.0)
significandDigit++;
}
else
@ -923,12 +925,24 @@ private:
if (s.Peek() >= '0' && s.Peek() <= '9') {
exp = s.Take() - '0';
if (expMinus) {
while (s.Peek() >= '0' && s.Peek() <= '9') {
exp = exp * 10 + (s.Take() - '0');
if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
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
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
@ -1225,14 +1239,9 @@ private:
// May return a new state on state pop.
template <unsigned parseFlags, typename InputStream, typename Handler>
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
(void)token;
switch (dst) {
case IterativeParsingStartState:
RAPIDJSON_ASSERT(false);
return IterativeParsingErrorState;
case IterativeParsingFinishState:
return dst;
case IterativeParsingErrorState:
return dst;
@ -1271,12 +1280,9 @@ private:
return dst;
case IterativeParsingKeyValueDelimiterState:
if (token == ColonToken) {
RAPIDJSON_ASSERT(token == ColonToken);
is.Take();
return dst;
}
else
return IterativeParsingErrorState;
case IterativeParsingMemberValueState:
// 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.
ParseValue<parseFlags>(is, handler);
if (HasParseError()) {
return IterativeParsingErrorState;
}
return IterativeParsingFinishState;
default:
RAPIDJSON_ASSERT(false);
return IterativeParsingErrorState;
}
}

View File

@ -272,7 +272,8 @@ protected:
os_->Put(hexDigits[(codepoint >> 4) & 15]);
os_->Put(hexDigits[(codepoint ) & 15]);
}
else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
else {
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
// Surrogate pair
unsigned s = codepoint - 0x010000;
unsigned lead = (s >> 10) + 0xD800;
@ -288,8 +289,6 @@ protected:
os_->Put(hexDigits[(trail >> 4) & 15]);
os_->Put(hexDigits[(trail ) & 15]);
}
else
return false; // invalid code point
}
else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
is.Take();
@ -303,7 +302,8 @@ protected:
}
}
else
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
return false;
}
os_->Put('\"');
return true;

View File

@ -1,4 +1,7 @@
![](doc/logo/rapidjson.png)
![](https://img.shields.io/badge/release-v1.0.1-blue.png)
## 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.
@ -13,14 +16,16 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
## Build status
| [Linux][lin-link] | [Windows][win-link] |
| :---------------: | :-----------------: |
| ![lin-badge] | ![win-badge] |
| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] |
| :---------------: | :-----------------: | :-------------------: |
| ![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"
[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"
[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master
[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master
## 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 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.

View File

@ -1,5 +1,9 @@
![](doc/logo/rapidjson.png)
![](https://img.shields.io/badge/release-v1.0.1-blue.png)
## 高效的C++ JSON解析生成器提供SAX及DOM风格API
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.
@ -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/)
* [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小而全。它同时支持SAX和DOM风格的API。SAX解析器只有约500行代码。
* RapidJSON快。它的性能可与`strlen()`相比。可支持SSE2/SSE4.1加速。
* RapidJSON快。它的性能可与`strlen()`相比。可支持SSE2/SSE4.2加速。
* RapidJSON独立。它不依赖于BOOST等外部库。它甚至不依赖于STL。
@ -45,21 +62,21 @@ RapidJSON是跨平台的。以下是一些曾测试的平台编译器组合
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)。
2. 下载 [premake4](http://industriousone.com/premake/download)。
3. 复制 premake4 可执行文件至 `rapidjson/build` (或系统路径)。
4. 进入`rapidjson/build/`目录在Windows下执行`premake.bat`在Linux或其他平台下执行`premake.sh`
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`目录。
2. 在rapidjson目渌下建立一个`build`目录。
3. 在`build`目录下执行`cmake ..`命令以设置生成。Windows用户可使用cmake-gui应用程序。
4. 在Windows下编译生成在build目录中的solution。在Linux下于build目录运行`make`
生成[Doxygen](http://doxygen.org)文档的步骤:
成功生成后,你会在`bin`的目录下找到编译后的测试及例子可执行文件。而生成的文档将位于build下的`doc/html`目录。要执行测试请在build下执行`make test``ctest`。使用`ctest -V`命令可获取详细的输出。
1. 下载及安装[Doxygen](http://doxygen.org/download.html)。
2. 在顶层目录执行`doxygen build/Doxyfile`
3. 在`doc/html`浏览文档。
我们也可以把程序库安装至全系统中只要在具管理權限下从build目录执行`make install`命令。这样会按系统的偏好设置安装所有文件。当安装RapidJSON后其他的CMake项目需要使用它时可以通过在`CMakeLists.txt`加入一句`find_package(RapidJSON)`
## 用法一览

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 "perftest.h"
@ -768,7 +762,7 @@ template <typename Writer>
void itoa_Writer_StringBufferVerify() {
rapidjson::StringBuffer sb;
Writer writer(sb);
for (int j = 0; j < randvalCount; j++) {
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
writer.WriteInt(randval[j]);
@ -780,7 +774,7 @@ void itoa_Writer_StringBufferVerify() {
template <typename Writer>
void itoa_Writer_InsituStringStreamVerify() {
Writer writer;
for (int j = 0; j < randvalCount; j++) {
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
char buffer2[32];

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 "perftest.h"

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 PERFTEST_H_
#define PERFTEST_H_
@ -71,9 +65,20 @@ public:
PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
virtual void SetUp() {
FILE *fp = fopen(filename_ = "data/sample.json", "rb");
if (!fp)
fp = fopen(filename_ = "../../bin/data/sample.json", "rb");
const char *paths[] = {
"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);
fseek(fp, 0, SEEK_END);

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 "perftest.h"

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 "perftest.h"
@ -26,7 +20,6 @@
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filestream.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/encodedstream.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) {
for (size_t i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");

View File

@ -1,13 +1,20 @@
set(UNITTEST_SOURCES
allocatorstest.cpp
bigintegertest.cpp
documenttest.cpp
encodedstreamtest.cpp
encodingstest.cpp
filestreamtest.cpp
itoatest.cpp
jsoncheckertest.cpp
namespacetest.cpp
<<<<<<< HEAD
pointertest.cpp
=======
prettywritertest.cpp
>>>>>>> master
readertest.cpp
simdtest.cpp
stringbuffertest.cpp
strtodtest.cpp
unittest.cpp
@ -15,9 +22,9 @@ set(UNITTEST_SOURCES
writertest.cpp)
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")
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")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif()
@ -36,8 +43,9 @@ add_test(NAME unittest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
if(NOT MSVC)
# Not running SIMD.* unit test cases for Valgrind
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)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")

View 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());
}
}

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/document.h"
@ -28,13 +22,11 @@
using namespace rapidjson;
template <typename Allocator, typename StackAllocator>
void ParseTest() {
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
template <typename DocumentType>
void ParseCheck(DocumentType& doc) {
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());
@ -63,7 +55,7 @@ void ParseTest() {
EXPECT_TRUE(doc.HasMember("pi"));
const ValueType& pi = doc["pi"];
EXPECT_TRUE(pi.IsNumber());
EXPECT_EQ(3.1416, pi.GetDouble());
EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
EXPECT_TRUE(doc.HasMember("a"));
const ValueType& a = doc["a"];
@ -73,6 +65,28 @@ void ParseTest() {
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) {
ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
@ -81,14 +95,21 @@ TEST(Document, Parse) {
}
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];
sprintf(buffer, "encodings/%s", filename);
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, paths[i], filename);
FILE *fp = fopen(buffer, "rb");
if (!fp) {
sprintf(buffer, "../../bin/encodings/%s", filename);
fp = fopen(buffer, "rb");
}
if (fp)
return fp;
}
return 0;
}
TEST(Document, ParseStream_EncodedInputStream) {
@ -223,6 +244,10 @@ TEST(Document, UserBuffer) {
EXPECT_FALSE(doc.HasParseError());
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
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

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/filereadstream.h"
@ -47,15 +41,22 @@ private:
protected:
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];
sprintf(buffer, "encodings/%s", filename);
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, paths[i], filename);
FILE *fp = fopen(buffer, "rb");
if (!fp) {
sprintf(buffer, "../../bin/encodings/%s", filename);
fp = fopen(buffer, "rb");
}
if (fp)
return fp;
}
return 0;
}
static char *ReadFile(const char* filename, bool appendPath, size_t* outLength) {
FILE *fp = appendPath ? Open(filename) : fopen(filename, "rb");
@ -112,10 +113,11 @@ protected:
}
EXPECT_EQ('\0', s.Peek());
free(data);
EXPECT_EQ(size, eis.Tell());
}
}
void TestAutoUTFInputStream(const char *filename) {
void TestAutoUTFInputStream(const char *filename, bool expectHasBOM) {
// Test FileReadStream
{
char buffer[16];
@ -123,6 +125,7 @@ protected:
ASSERT_TRUE(fp != 0);
FileReadStream fs(fp, buffer, sizeof(buffer));
AutoUTFInputStream<unsigned, FileReadStream> eis(fs);
EXPECT_EQ(expectHasBOM, eis.HasBOM());
StringStream s(json_);
while (eis.Peek() != '\0') {
unsigned expected, actual;
@ -140,6 +143,7 @@ protected:
char* data = ReadFile(filename, true, &size);
MemoryStream ms(data, size);
AutoUTFInputStream<unsigned, MemoryStream> eis(ms);
EXPECT_EQ(expectHasBOM, eis.HasBOM());
StringStream s(json_);
while (eis.Peek() != '\0') {
@ -150,6 +154,7 @@ protected:
}
EXPECT_EQ('\0', s.Peek());
free(data);
EXPECT_EQ(size, eis.Tell());
}
}
@ -257,16 +262,25 @@ TEST_F(EncodedStreamTest, EncodedInputStream) {
}
TEST_F(EncodedStreamTest, AutoUTFInputStream) {
TestAutoUTFInputStream("utf8.json");
TestAutoUTFInputStream("utf8bom.json");
TestAutoUTFInputStream("utf16le.json");
TestAutoUTFInputStream("utf16lebom.json");
TestAutoUTFInputStream("utf16be.json");
TestAutoUTFInputStream("utf16bebom.json");
TestAutoUTFInputStream("utf32le.json");
TestAutoUTFInputStream("utf32lebom.json");
TestAutoUTFInputStream("utf32be.json");
TestAutoUTFInputStream("utf32bebom.json");
TestAutoUTFInputStream("utf8.json", false);
TestAutoUTFInputStream("utf8bom.json", true);
TestAutoUTFInputStream("utf16le.json", false);
TestAutoUTFInputStream("utf16lebom.json",true);
TestAutoUTFInputStream("utf16be.json", false);
TestAutoUTFInputStream("utf16bebom.json",true);
TestAutoUTFInputStream("utf32le.json", false);
TestAutoUTFInputStream("utf32lebom.json",true);
TestAutoUTFInputStream("utf32be.json", false);
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) {

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/filereadstream.h"

View File

@ -1,25 +1,18 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/filestream.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h"
@ -31,9 +24,21 @@ public:
FileStreamTest() : filename_(), json_(), length_() {}
virtual void SetUp() {
FILE *fp = fopen(filename_ = "data/sample.json", "rb");
if (!fp)
fp = fopen(filename_ = "../../bin/data/sample.json", "rb");
const char *paths[] = {
"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(paths[i], "rb");
if (fp) {
filename_ = paths[i];
break;
}
}
ASSERT_TRUE(fp != 0);
fseek(fp, 0, SEEK_END);
@ -60,24 +65,6 @@ protected:
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) {
FILE *fp = fopen(filename_, "rb");
ASSERT_TRUE(fp != 0);

158
test/unittest/itoatest.cpp Normal file
View 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

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"
@ -25,9 +19,22 @@
using namespace rapidjson;
static char* ReadFile(const char* filename, size_t& length) {
FILE *fp = fopen(filename, "rb");
if (!fp)
fp = fopen(filename, "rb");
const char *paths[] = {
"jsonchecker/%s",
"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)
return 0;
@ -51,18 +58,14 @@ TEST(JsonChecker, Reader) {
if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting.
continue;
sprintf(filename, "jsonchecker/fail%d.json", i);
sprintf(filename, "fail%d.json", i);
size_t length;
char* json = ReadFile(filename, length);
if (!json) {
sprintf(filename, "../../bin/jsonchecker/fail%d.json", i);
json = ReadFile(filename, length);
if (!json) {
printf("jsonchecker file %s not found", filename);
ADD_FAILURE();
continue;
}
}
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
document.Parse((const char*)json);
@ -76,17 +79,13 @@ TEST(JsonChecker, Reader) {
// passX.json
for (int i = 1; i <= 3; i++) {
sprintf(filename, "jsonchecker/pass%d.json", i);
sprintf(filename, "pass%d.json", i);
size_t length;
char* json = ReadFile(filename, length);
if (!json) {
sprintf(filename, "../../bin/jsonchecker/pass%d.json", i);
json = ReadFile(filename, length);
if (!json) {
printf("jsonchecker file %s not found", filename);
continue;
}
}
GenericDocument<UTF8<>, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak)
document.Parse((const char*)json);

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"

View 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);
}

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"
@ -30,6 +24,7 @@ using namespace rapidjson;
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(float-equal)
#endif
template<bool expect>
@ -187,16 +182,20 @@ static void TestParseDouble() {
Reader reader; \
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code()); \
EXPECT_EQ(1u, h.step_); \
internal::Double e(x), a(h.actual_); \
if (fullPrecision) { \
EXPECT_EQ(x, h.actual_); \
if (x != h.actual_) \
EXPECT_EQ(e.Uint64Value(), a.Uint64Value()); \
if (e.Uint64Value() != a.Uint64Value()) \
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_); \
} \
}
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.5", 1.5);
@ -227,6 +226,12 @@ static void TestParseDouble() {
TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise
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, "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
// 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.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'
n1e308[0] = '1';
@ -258,28 +289,53 @@ static void TestParseDouble() {
TEST_DOUBLE(fullPrecision, n1e308, 1E308);
}
#if 0 // Very slow
static const unsigned count = 10000000;
// Random test for double
{
Random r;
// Cover trimming
TEST_DOUBLE(fullPrecision,
"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;
Reader reader; // Reusing reader to prevent heap allocation
// Exhaustively test different exponents with random significant
for (uint64_t exp = 0; exp < 2047; exp++) {
;
for (unsigned i = 0; i < count; i++) {
internal::Double d;
do {
// 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());
d = internal::Double(u);
} while (d.IsNan() || d.IsInf()/* || !d.IsNormal()*/); // Also work for subnormal now
internal::Double d = internal::Double(u);
char buffer[32];
*internal::dtoa(d.Value(), buffer) = '\0';
TEST_DOUBLE(fullPrecision, buffer, d.Value());
}
}
#endif
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_);
}
}
}
}
#undef TEST_DOUBLE
}
@ -482,6 +538,17 @@ TEST(Reader, ParseString_Transcoding) {
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) {
StringStream s("\"Hello\\nWorld\"");
ParseStringHandler<UTF8<> > h;
@ -491,24 +558,31 @@ TEST(Reader, ParseString_NonDestructive) {
EXPECT_EQ(11u, h.length_);
}
ParseErrorCode TestString(const char* str) {
StringStream s(str);
BaseReaderHandler<> h;
Reader reader;
reader.Parse<kParseValidateEncodingFlag>(s, h);
template <typename Encoding>
ParseErrorCode TestString(const typename Encoding::Ch* str) {
GenericStringStream<Encoding> s(str);
BaseReaderHandler<Encoding> h;
GenericReader<Encoding, Encoding> reader;
reader.template Parse<kParseValidateEncodingFlag>(s, h);
return reader.GetParseErrorCode();
}
TEST(Reader, ParseString_Error) {
#define TEST_STRING_ERROR(errorCode, str)\
EXPECT_EQ(errorCode, TestString(str))
EXPECT_EQ(errorCode, TestString<UTF8<> >(str))
#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 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.
@ -517,6 +591,10 @@ TEST(Reader, ParseString_Error) {
// Incorrect hex digit after \\u escape in string.
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.
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]");
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]");
@ -533,7 +611,7 @@ TEST(Reader, ParseString_Error) {
char e[] = { '[', '\"', 0, '\"', ']', '\0' };
for (unsigned char c = 0x80u; c <= 0xBFu; c++) {
e[2] = c;
ParseErrorCode error = TestString(e);
ParseErrorCode error = TestString<UTF8<> >(e);
EXPECT_EQ(kParseErrorStringInvalidEncoding, error);
if (error != kParseErrorStringInvalidEncoding)
std::cout << (unsigned)(unsigned char)c << std::endl;
@ -552,30 +630,40 @@ TEST(Reader, ParseString_Error) {
// 4 Overlong sequences
// 4.1 Examples of an overlong ASCII character
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, 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('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
// 4.2 Maximum overlong sequences
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, 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('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
// 4.3 Overlong representation of the NUL character
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, 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('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
// 5 Illegal code positions
// 5.1 Single UTF-16 surrogates
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xA0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, 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, 0xA0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0'));
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBEu, 0x80u, '\"', ']', '\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 TEST_STRINGARRAY_ERROR
@ -655,7 +743,7 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> {
}
}
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) {
switch(step_) {
case 1: EXPECT_STREQ("hello", str); step_++; return true;
@ -965,6 +1053,17 @@ TEST(Reader, IterativeParsing_ErrorHandling) {
TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u);
TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u);
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<> >
@ -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__
RAPIDJSON_DIAG_POP
#endif

View 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>();
}

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/stringbuffer.h"
@ -54,6 +48,10 @@ TEST(StringBuffer, Push) {
buffer.Push(5);
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) {

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"

View File

@ -1,28 +1,25 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/rapidjson.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl;
#if _MSC_VER
_CrtMemState memoryState = { 0 };
_CrtMemCheckpoint(&memoryState);

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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 UNITTEST_H_
#define UNITTEST_H_

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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/document.h"
@ -203,12 +197,28 @@ TEST(Value, EqualtoOperator) {
EXPECT_TRUE(z.RemoveMember("t"));
TestUnequal(x, z);
TestEqual(y, z);
y.AddMember("t", true, crtAllocator);
z.AddMember("t", true, z.GetAllocator());
y.AddMember("t", false, crtAllocator);
z.AddMember("t", false, z.GetAllocator());
TestUnequal(x, y);
TestUnequal(z, x);
y["t"] = true;
z["t"] = true;
TestEqual(x, y);
TestEqual(y, z);
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
x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0));
y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF));
@ -229,6 +239,13 @@ void TestCopyFrom() {
EXPECT_STREQ(v1.GetString(), v2.GetString());
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);
v2.CopyFrom(v1, a);
EXPECT_TRUE(v2.IsArray());
@ -339,7 +356,7 @@ TEST(Value, Int) {
EXPECT_EQ(1234u, x.GetUint());
EXPECT_EQ(1234, x.GetInt64());
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, (unsigned)x);
//EXPECT_EQ(1234, (int64_t)x);
@ -397,7 +414,7 @@ TEST(Value, Uint) {
EXPECT_TRUE(x.IsUint());
EXPECT_TRUE(x.IsInt64());
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.IsNull());
@ -462,10 +479,19 @@ TEST(Value, Int64) {
z.SetInt64(2147483648LL); // 2^31, cannot cast as int
EXPECT_FALSE(z.IsInt());
EXPECT_TRUE(z.IsUint());
EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0);
z.SetInt64(4294967296LL); // 2^32, cannot cast as uint
EXPECT_FALSE(z.IsInt());
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) {
@ -508,16 +534,15 @@ TEST(Value, Uint64) {
z.SetUint64(9223372036854775808uLL); // 2^63 cannot cast as int64
EXPECT_FALSE(z.IsInt64());
// Issue 48
EXPECT_EQ(9223372036854775808uLL, z.GetUint64());
EXPECT_EQ(9223372036854775808uLL, z.GetUint64()); // Issue 48
EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble());
}
TEST(Value, Double) {
// Constructor with double
Value x(12.34);
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.IsDouble());
@ -533,10 +558,10 @@ TEST(Value, Double) {
// SetDouble()
Value z;
z.SetDouble(12.34);
EXPECT_EQ(12.34, z.GetDouble());
EXPECT_NEAR(12.34, z.GetDouble(), 0.0);
z = 56.78;
EXPECT_EQ(56.78, z.GetDouble());
EXPECT_NEAR(56.78, z.GetDouble(), 0.0);
}
TEST(Value, String) {
@ -977,6 +1002,7 @@ TEST(Value, Object) {
EXPECT_STREQ("Banana", x["B"].GetString());
EXPECT_STREQ("CherryD", x[C0D].GetString());
EXPECT_STREQ("CherryD", x[othername].GetString());
EXPECT_THROW(x["nonexist"], AssertException);
// const operator[]
EXPECT_STREQ("Apple", y["A"].GetString());
@ -1041,13 +1067,15 @@ TEST(Value, Object) {
EXPECT_FALSE(citr >= itr);
// RemoveMember()
x.RemoveMember("A");
EXPECT_TRUE(x.RemoveMember("A"));
EXPECT_FALSE(x.HasMember("A"));
x.RemoveMember("B");
EXPECT_TRUE(x.RemoveMember("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_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("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\":[]}");
}

View File

@ -1,22 +1,16 @@
// Copyright (C) 2011 Milo Yip
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 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
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// 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"
@ -46,7 +40,7 @@ TEST(Writer, Compact) {
StringBuffer buffer; \
Writer<StringBuffer> writer(buffer); \
Reader reader; \
reader.Parse<0>(s, writer); \
reader.Parse<kParseFullPrecisionFlag>(s, writer); \
EXPECT_STREQ(json, buffer.GetString()); \
EXPECT_TRUE(writer.IsComplete()); \
}
@ -89,10 +83,27 @@ TEST(Writer, String) {
TEST_ROUNDTRIP("[\"Hello\"]");
TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
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_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) {
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;
OStreamWrapper os(ss);
@ -163,7 +174,7 @@ TEST(Writer, OStreamWrapper) {
reader.Parse<0>(s, writer);
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) {
@ -306,3 +317,61 @@ TEST(Writer, RootValueIsComplete) {
T(writer.String(""));
#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());
}
}