update rapidjson (nw)

This commit is contained in:
Miodrag Milanovic 2016-08-06 14:23:30 +02:00
parent 3917850b61
commit a8ebc11437
41 changed files with 389 additions and 248 deletions

View File

@ -20,5 +20,6 @@ Testing
/googletest
install_manifest.txt
Doxyfile
Doxyfile.zh-cn
DartConfiguration.tcl
*.nupkg

View File

@ -1,3 +1,3 @@
[submodule "thirdparty/gtest"]
path = thirdparty/gtest
url = https://chromium.googlesource.com/external/googletest.git
url = https://github.com/google/googletest.git

View File

@ -1,16 +1,12 @@
sudo: required
dist: precise
language: cpp
sudo: false
cache:
- ccache
addons:
apt:
packages: &default_packages
- cmake
- valgrind
env:
global:
global:
- USE_CCACHE=1
- CCACHE_SLOPPINESS=pch_defines,time_macros
- CCACHE_COMPRESS=1
@ -20,108 +16,41 @@ global:
- GITHUB_REPO='miloyip/rapidjson'
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
before_install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386
matrix:
include:
# gcc
- env: CONF=release ARCH=x86 CXX11=ON
compiler: gcc
addons:
apt:
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
- env: CONF=release ARCH=x86_64 CXX11=ON
compiler: gcc
- env: CONF=debug ARCH=x86 CXX11=OFF
compiler: gcc
addons:
apt:
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
- env: CONF=debug ARCH=x86_64 CXX11=OFF
compiler: gcc
# clang
- env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
- clang-3.7
- env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- clang-3.7
- env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
- clang-3.7
- env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- clang-3.7
- env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
- clang-3.7
- env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
compiler: clang
addons:
apt:
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
packages:
- *default_packages
- clang-3.7
# coverage report
- env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage'
compiler: gcc
cache:
- ccache
- pip
addons:
apt:
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
after_success:
- pip install --user cpp-coveralls
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
@ -130,12 +59,6 @@ matrix:
cache:
- ccache
- pip
addons:
apt:
packages:
- *default_packages
- g++-multilib
- libc6-dbg:i386
after_success:
- pip install --user cpp-coveralls
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
@ -158,7 +81,7 @@ before_script:
- mkdir build
script:
- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi
- if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi
- >
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
(cd build && cmake

View File

@ -1,4 +1,8 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
if(POLICY CMP0025)
# detect Apple's Clang
cmake_policy(SET CMP0025 NEW)
endif()
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
@ -28,6 +32,9 @@ option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11 (gcc/clang)" ON)
option(RAPIDJSON_BUILD_ASAN "Build rapidjson with address sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_BUILD_UBSAN "Build rapidjson with undefined behavior sanitizer (gcc/clang)" OFF)
option(RAPIDJSON_HAS_STDSTRING "" OFF)
if(RAPIDJSON_HAS_STDSTRING)
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
@ -51,11 +58,35 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
endif()
if (RAPIDJSON_BUILD_ASAN)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0")
message(FATAL_ERROR "GCC < 4.8 doesn't support the address sanitizer")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
endif()
endif()
if (RAPIDJSON_BUILD_UBSAN)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0")
message(FATAL_ERROR "GCC < 4.9 doesn't support the undefined behavior sanitizer")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
endif()
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers")
if (RAPIDJSON_BUILD_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
if (RAPIDJSON_BUILD_ASAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
endif()
if (RAPIDJSON_BUILD_UBSAN)
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
endif()
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")

View File

@ -1,7 +1,7 @@
SET(GTEST_SEARCH_PATH
"${GTEST_SOURCE_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest")
"${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest/googletest")
IF(UNIX)
IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST)

View File

@ -118,6 +118,7 @@ Parse flags | Meaning
`kParseCommentsFlag` | Allow one-line `// ...` and multi-line `/* ... */` comments (relaxed JSON syntax).
`kParseNumbersAsStringsFlag` | Parse numerical type values as strings.
`kParseTrailingCommasFlag` | Allow trailing commas at the end of objects and arrays (relaxed JSON syntax).
`kParseNanAndInfFlag` | Allow parsing `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (relaxed JSON syntax).
By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time.

View File

@ -26,6 +26,7 @@
* Support optional relaxed syntax.
* Single line (`// ...`) and multiple line (`/* ... */`) comments (`kParseCommentsFlag`).
* Trailing commas at the end of objects and arrays (`kParseTrailingCommasFlag`).
* [NPM compliant](doc/npm.md).
## Unicode

View File

@ -7,21 +7,5 @@
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES * * */
var disqus_shortname = 'rapidjson-doc';
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dt = document.createElement('div');
dt.id = "disqus_thread";
(document.getElementsByClassName('contents')[0]).appendChild(dt);
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
</body>
</html>

View File

@ -16,15 +16,6 @@ $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-63929386-1', 'auto');
ga('send', 'pageview');
</script>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="topbanner"><a href="https://github.com/miloyip/rapidjson" title="RapidJSON GitHub"><i class="githublogo"></i></a></div>

31
3rdparty/rapidjson/doc/npm.md vendored Normal file
View File

@ -0,0 +1,31 @@
## NPM
# package.json {#package}
~~~~~~~~~~js
{
...
"dependencies": {
...
"rapidjson": "git@github.com:miloyip/rapidjson.git"
},
...
"gypfile": true
}
~~~~~~~~~~
# binding.gyp {#binding}
~~~~~~~~~~js
{
...
'targets': [
{
...
'include_dirs': [
'<!(node -e \'require("rapidjson")\')'
]
}
]
}
~~~~~~~~~~

View File

@ -59,7 +59,7 @@ These events can be easily matched with the JSON, except some event parameters n
using namespace rapidjson;
using namespace std;
struct MyHandler {
struct MyHandler : public BaseReaderHandler<UTF8<>, MyHandler> {
bool Null() { cout << "Null()" << endl; return true; }
bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; }
bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; }

View File

@ -59,7 +59,7 @@ EndObject(7)
using namespace rapidjson;
using namespace std;
struct MyHandler {
struct MyHandler : public BaseReaderHandler<UTF8<>, MyHandler> {
bool Null() { cout << "Null()" << endl; return true; }
bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; }
bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; }
@ -106,6 +106,7 @@ class Handler {
bool Int64(int64_t i);
bool Uint64(uint64_t i);
bool Double(double d);
bool RawNumber(const Ch* str, SizeType length, bool copy);
bool String(const Ch* str, SizeType length, bool copy);
bool StartObject();
bool Key(const Ch* str, SizeType length, bool copy);

View File

@ -152,7 +152,7 @@ JSON Schema supports [`$ref` keyword](http://spacetelescope.github.io/understand
{ "$ref": "definitions.json#/address" }
~~~
As `SchemaValidator` does not know how to resolve such URI, it needs a user-provided `IRemoteSchemaDocumentProvider` instance to do so.
As `SchemaDocument` does not know how to resolve such URI, it needs a user-provided `IRemoteSchemaDocumentProvider` instance to do so.
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
@ -165,7 +165,7 @@ public:
// ...
MyRemoteSchemaDocumentProvider provider;
SchemaValidator validator(schema, &provider);
SchemaDocument schema(sd, &provider);
~~~
## Conformance

View File

@ -152,7 +152,7 @@ JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understand
{ "$ref": "definitions.json#/address" }
~~~
由于 `SchemaValidator` 并不知道如何处理那些 URI它需要使用者提供一个 `IRemoteSchemaDocumentProvider` 的实例去处理。
由于 `SchemaDocument` 并不知道如何处理那些 URI它需要使用者提供一个 `IRemoteSchemaDocumentProvider` 的实例去处理。
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
@ -165,7 +165,7 @@ public:
// ...
MyRemoteSchemaDocumentProvider provider;
SchemaValidator validator(schema, &provider);
SchemaDocument schema(sd, &provider);
~~~
## 标准的符合程度

View File

@ -166,7 +166,7 @@ If we are unsure whether a member exists, we need to call `HasMember()` before c
~~~~~~~~~~cpp
Value::ConstMemberIterator itr = document.FindMember("hello");
if (itr != document.MemberEnd())
printf("%s %s\n", itr->value.GetString());
printf("%s\n", itr->value.GetString());
~~~~~~~~~~
## Querying Number {#QueryNumber}

View File

@ -166,7 +166,7 @@ Type of member a is Array
~~~~~~~~~~cpp
Value::ConstMemberIterator itr = document.FindMember("hello");
if (itr != document.MemberEnd())
printf("%s %s\n", itr->value.GetString());
printf("%s\n", itr->value.GetString());
~~~~~~~~~~
## 查询 Number {#QueryNumber}
@ -379,7 +379,7 @@ const char * cstr = getenv("USER");
size_t cstr_len = ...; // 如果有长度
Value s;
// s.SetString(cstr); // 这不能通过编译
s.SetString(StringRef(cstr)); // 可以,假设它的生命周期全,并且是以空字符结尾的
s.SetString(StringRef(cstr)); // 可以,假设它的生命周期全,并且是以空字符结尾的
s = StringRef(cstr); // 上行的缩写
s.SetString(StringRef(cstr, cstr_len));// 更快,可处理空字符
s = StringRef(cstr, cstr_len); // 上行的缩写

View File

@ -1,7 +1,8 @@
// Example of parsing JSON to document by parts.
// Using C++11 threads
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
// Temporarily disable for clang (older version) due to incompatibility with libstdc++
#if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)) && !defined(__clang__)
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"

View File

@ -179,7 +179,8 @@ public:
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
@ -211,11 +212,13 @@ 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.
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
if (void* newBuffer = Malloc(newSize)) {
if (originalSize)
std::memcpy(newBuffer, originalPtr, originalSize);
return newBuffer;
}
else
return NULL;
}
//! Frees a memory block (concept Allocator)
@ -229,15 +232,20 @@ private:
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
void AddChunk(size_t capacity) {
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
chunkHead_ = chunk;
return true;
}
else
return false;
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.

View File

@ -23,24 +23,26 @@
#include "memorystream.h"
#include "encodedstream.h"
#include <new> // placement new
#include <limits>
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
#ifdef _MSC_VER
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 6
RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
#endif
#endif // __GNUC__
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include <iterator> // std::iterator, std::random_access_iterator_tag
@ -478,7 +480,7 @@ template<typename ValueType>
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
typedef std::basic_string<typename ValueType::Ch> StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return v.GetString(); }
static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
};
#endif
@ -952,12 +954,16 @@ public:
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
return static_cast<uint64_t>(d) == u;
return (d >= 0.0)
&& (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
&& (u == static_cast<uint64_t>(d));
}
if (IsInt64()) {
int64_t i = GetInt64();
volatile double d = static_cast<double>(i);
return static_cast< int64_t>(d) == i;
return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
&& (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
&& (i == static_cast<int64_t>(d));
}
return true; // double, int, uint are always lossless
}
@ -973,6 +979,9 @@ public:
bool IsLosslessFloat() const {
if (!IsNumber()) return false;
double a = GetDouble();
if (a < static_cast<double>(-std::numeric_limits<float>::max())
|| a > static_cast<double>(std::numeric_limits<float>::max()))
return false;
double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal
}
@ -1160,8 +1169,8 @@ public:
\return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd().
*/
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
#endif
//! Add a member (name-value pair) to the object.
@ -2561,17 +2570,6 @@ private:
};
RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_DOCUMENT_H_

View File

@ -154,7 +154,11 @@ struct UTF8 {
}
unsigned char type = GetRange(static_cast<unsigned char>(c));
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
if (type >= 32) {
*codepoint = 0;
} else {
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
}
bool result = true;
switch (type) {
case 2: TAIL(); return result;

View File

@ -102,7 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--;
if (p2 < delta) {
*K += kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast<int>(kappa)]);
int index = -static_cast<int>(kappa);
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
return;
}
}

View File

@ -142,7 +142,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
size_t remaining = length - i;
const unsigned kUlpShift = 3;
const unsigned kUlp = 1 << kUlpShift;
int error = (remaining == 0) ? 0 : kUlp / 2;
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
DiyFp v(significand, 0);
v = v.Normalize();

View File

@ -767,8 +767,12 @@ private:
tokenCount_ = rhs.tokenCount_ + extraToken;
tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
if (rhs.tokenCount_ > 0) {
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
}
if (nameBufferSize > 0) {
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
}
// Adjust pointers to name buffer
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;

View File

@ -115,6 +115,12 @@ public:
}
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
#if RAPIDJSON_HAS_STDSTRING
bool Key(const std::basic_string<Ch>& str) {
return Key(str.data(), SizeType(str.size()));
}
#endif
bool EndObject(SizeType memberCount = 0) {
(void)memberCount;

View File

@ -250,7 +250,7 @@
//! Whether using 64-bit architecture
#ifndef RAPIDJSON_64BIT
#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__)
#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
#define RAPIDJSON_64BIT 1
#else
#define RAPIDJSON_64BIT 0

View File

@ -23,6 +23,7 @@
#include "internal/meta.h"
#include "internal/stack.h"
#include "internal/strtod.h"
#include <limits>
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
#include <intrin.h>
@ -42,6 +43,7 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(old-style-cast)
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
#endif
@ -150,6 +152,7 @@ enum ParseFlag {
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
};
@ -1137,6 +1140,8 @@ private:
(parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
size_t startOffset = s.Tell();
double d = 0.0;
bool useNanOrInf = false;
// Parse minus
bool minus = Consume(s, '-');
@ -1178,12 +1183,26 @@ private:
significandDigit++;
}
}
// Parse NaN or Infinity here
else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
useNanOrInf = true;
if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
d = std::numeric_limits<double>::quiet_NaN();
}
else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
}
else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
}
else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
// Parse 64bit int
bool useDouble = false;
double d = 0.0;
if (use64bit) {
if (minus)
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
@ -1346,6 +1365,9 @@ private:
cont = handler.Double(minus ? -d : d);
}
else if (useNanOrInf) {
cont = handler.Double(d);
}
else {
if (use64bit) {
if (minus)

View File

@ -19,13 +19,6 @@
#include "pointer.h"
#include <cmath> // abs, floor
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(weak-vtables)
RAPIDJSON_DIAG_OFF(exit-time-destructors)
RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
#endif
#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
#else
@ -58,18 +51,20 @@ RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
#include "stringbuffer.h"
#endif
#if defined(__GNUC__)
RAPIDJSON_DIAG_PUSH
#if defined(__GNUC__)
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(weak-vtables)
RAPIDJSON_DIAG_OFF(exit-time-destructors)
RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
RAPIDJSON_DIAG_OFF(variadic-macros)
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
@ -413,9 +408,11 @@ public:
}
}
AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
if (schemaDocument) {
AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
}
if (const ValueType* v = GetMember(value, GetNotString())) {
schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
@ -578,7 +575,9 @@ public:
}
~Schema() {
allocator_->Free(enum_);
if (allocator_) {
allocator_->Free(enum_);
}
if (properties_) {
for (SizeType i = 0; i < propertyCount_; i++)
properties_[i].~Property();
@ -1339,7 +1338,7 @@ public:
\param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
\param allocator An optional allocator instance for allocating memory. Can be null.
*/
GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) RAPIDJSON_NOEXCEPT :
explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
remoteProvider_(remoteProvider),
allocator_(allocator),
ownAllocator_(),
@ -2002,17 +2001,6 @@ private:
};
RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__)
RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_SCHEMA_H_

View File

@ -95,7 +95,7 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
//! Put N copies of a character to a stream.
template<typename Stream, typename Ch>
inline void PutN(Stream& stream, Ch c, size_t n) {
PutReserve<Stream>(stream, n);
PutReserve(stream, n);
for (size_t i = 0; i < n; i++)
PutUnsafe(stream, c);
}

View File

@ -41,6 +41,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable-code)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -62,6 +63,7 @@ RAPIDJSON_NAMESPACE_BEGIN
enum WriteFlag {
kWriteNoFlags = 0, //!< No flags are set.
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN.
kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
};
@ -167,30 +169,30 @@ public:
*/
//@{
bool Null() { Prefix(kNullType); return WriteNull(); }
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
//! Writes the given \c double value to the stream
/*!
\param d The value to be written.
\return Whether it is succeed.
*/
bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
(void)copy;
Prefix(kNumberType);
return WriteString(str, length);
return EndValue(WriteString(str, length));
}
bool String(const Ch* str, SizeType length, bool copy = false) {
(void)copy;
Prefix(kStringType);
return WriteString(str, length);
return EndValue(WriteString(str, length));
}
#if RAPIDJSON_HAS_STDSTRING
@ -212,10 +214,7 @@ public:
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
level_stack_.template Pop<Level>(1);
bool ret = WriteEndObject();
if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
os_->Flush();
return ret;
return EndValue(WriteEndObject());
}
bool StartArray() {
@ -229,10 +228,7 @@ public:
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
level_stack_.template Pop<Level>(1);
bool ret = WriteEndArray();
if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
os_->Flush();
return ret;
return EndValue(WriteEndArray());
}
//@}
@ -253,7 +249,7 @@ public:
\param length Length of the json.
\param type Type of the root of json.
*/
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return WriteRawValue(json, length); }
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
protected:
//! Information for each nested level
@ -319,9 +315,25 @@ protected:
}
bool WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf())
return false;
if (internal::Double(d).IsNanOrInf()) {
if (!(writeFlags & kWriteNanAndInfFlag))
return false;
if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
return true;
}
char buffer[25];
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
PutReserve(*os_, static_cast<size_t>(end - buffer));
@ -442,6 +454,13 @@ protected:
}
}
// Flush the value if it is the top level one.
bool EndValue(bool ret) {
if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
os_->Flush();
return ret;
}
OutputStream* os_;
internal::Stack<StackAllocator> level_stack_;
int maxDecimalPlaces_;
@ -489,8 +508,25 @@ inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf())
return false;
if (internal::Double(d).IsNanOrInf()) {
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
return false;
if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
return true;
}
char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);

View File

@ -1,8 +1,8 @@
{
"name": "rapidjson",
"version": "1.0.3",
"version": "1.0.4",
"description": "![](doc/logo/rapidjson.png)",
"main": "index.js",
"main": "include_dirs.js",
"directories": {
"doc": "doc",
"example": "example",
@ -20,6 +20,5 @@
"bugs": {
"url": "https://github.com/miloyip/rapidjson/issues"
},
"homepage": "https://github.com/miloyip/rapidjson#readme",
"main": "include_dirs.js"
"homepage": "https://github.com/miloyip/rapidjson#readme"
}

View File

@ -1,3 +1,5 @@
include(CheckCXXCompilerFlag)
set(UNITTEST_SOURCES
allocatorstest.cpp
bigintegertest.cpp
@ -38,11 +40,14 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
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 -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
# If the user is running a newer version of Clang that includes the
# -Wdouble-promotion, we will ignore that warning.
# if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
# endif()
# If the user is running a newer version of Clang that includes the
# -Wdouble-promotion, we will ignore that warning.
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7)
CHECK_CXX_COMPILER_FLAG("-Wno-double-promotion" HAS_NO_DOUBLE_PROMOTION)
if (HAS_NO_DOUBLE_PROMOTION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
endif()
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Force to always compile with /W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

View File

@ -37,6 +37,7 @@ TEST(dtoa, normal) {
TEST_DTOA(1.2345678, "1.2345678");
TEST_DTOA(0.123456789012, "0.123456789012");
TEST_DTOA(1234567.8, "1234567.8");
TEST_DTOA(-79.39773355813419, "-79.39773355813419");
TEST_DTOA(0.000001, "0.000001");
TEST_DTOA(0.0000001, "1e-7");
TEST_DTOA(1e30, "1e30");

View File

@ -302,8 +302,9 @@ TEST(EncodingsTest, UTF8) {
decodedCount++;
}
if (*encodedStr) // This decoder cannot handle U+0000
if (*encodedStr) { // This decoder cannot handle U+0000
EXPECT_EQ(1u, decodedCount); // Should only contain one code point
}
EXPECT_EQ(UTF8_ACCEPT, state);
if (UTF8_ACCEPT != state)

View File

@ -50,8 +50,9 @@ static void TestStringStream() {
StringStreamType iss(s);
BasicIStreamWrapper<StringStreamType> is(iss);
EXPECT_EQ(0, is.Tell());
if (sizeof(Ch) == 1)
if (sizeof(Ch) == 1) {
EXPECT_EQ(0, is.Peek4()); // less than 4 bytes
}
for (int i = 0; i < 3; i++) {
EXPECT_EQ(static_cast<size_t>(i), is.Tell());
EXPECT_EQ('A' + i, is.Peek());

View File

@ -84,6 +84,8 @@ static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) {
VerifyValue<T>(Traits<T>::Negate(i + 1), f, g);
}
last = i;
if (i > static_cast<T>(std::numeric_limits<T>::max() / static_cast<T>(power)))
break;
i *= power;
} while (last < i);
}

View File

@ -19,17 +19,21 @@
#include "rapidjson/internal/itoa.h"
#include "rapidjson/memorystream.h"
#include <limits>
using namespace rapidjson;
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
#ifdef __GNUC__
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(float-equal)
RAPIDJSON_DIAG_OFF(missing-noreturn)
#if __GNUC__ >= 7
RAPIDJSON_DIAG_OFF(dangling-else)
#endif
#endif // __GNUC__
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(variadic-macros)
RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
#endif
@ -1774,10 +1778,67 @@ TEST(Reader, TrailingCommaHandlerTerminationIterative) {
TestTrailingCommaHandlerTermination<kParseIterativeFlag>();
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
TEST(Reader, ParseNanAndInfinity) {
#define TEST_NAN_INF(str, x) \
{ \
{ \
StringStream s(str); \
ParseDoubleHandler h; \
Reader reader; \
ASSERT_EQ(kParseErrorNone, reader.Parse<kParseNanAndInfFlag>(s, h).Code()); \
EXPECT_EQ(1u, h.step_); \
internal::Double e(x), a(h.actual_); \
EXPECT_EQ(e.IsNan(), a.IsNan()); \
EXPECT_EQ(e.IsInf(), a.IsInf()); \
if (!e.IsNan()) \
EXPECT_EQ(e.Sign(), a.Sign()); \
} \
{ \
const char* json = "{ \"naninfdouble\": " str " } "; \
StringStream s(json); \
NumbersAsStringsHandler h(str); \
Reader reader; \
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag|kParseNanAndInfFlag>(s, h)); \
} \
{ \
char* json = StrDup("{ \"naninfdouble\": " str " } "); \
InsituStringStream s(json); \
NumbersAsStringsHandler h(str); \
Reader reader; \
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag|kParseNanAndInfFlag>(s, h)); \
free(json); \
} \
}
#define TEST_NAN_INF_ERROR(errorCode, str, errorOffset) \
{ \
int streamPos = errorOffset; \
char buffer[1001]; \
strncpy(buffer, str, 1000); \
InsituStringStream s(buffer); \
BaseReaderHandler<> h; \
Reader reader; \
EXPECT_FALSE(reader.Parse<kParseNanAndInfFlag>(s, h)); \
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
EXPECT_EQ(streamPos, s.Tell());\
}
double nan = std::numeric_limits<double>::quiet_NaN();
double inf = std::numeric_limits<double>::infinity();
TEST_NAN_INF("NaN", nan);
TEST_NAN_INF("-NaN", nan);
TEST_NAN_INF("Inf", inf);
TEST_NAN_INF("Infinity", inf);
TEST_NAN_INF("-Inf", -inf);
TEST_NAN_INF("-Infinity", -inf);
TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "nan", 1);
TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "-nan", 1);
TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "NAN", 1);
TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "-Infinty", 6);
#undef TEST_NAN_INF_ERROR
#undef TEST_NAN_INF
}
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif

View File

@ -111,7 +111,7 @@ TEST(SchemaValidator, Hasher) {
EXPECT_FALSE(d.HasParseError());\
EXPECT_TRUE(expected == d.Accept(validator));\
EXPECT_TRUE(expected == validator.IsValid());\
if (expected && !validator.IsValid()) {\
if ((expected) && !validator.IsValid()) {\
StringBuffer sb;\
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\
printf("Invalid schema: %s\n", sb.GetString());\

View File

@ -37,6 +37,13 @@ TEST(StringBuffer, Put) {
EXPECT_STREQ("A", buffer.GetString());
}
TEST(StringBuffer, PutN_Issue672) {
GenericStringBuffer<UTF8<>, MemoryPoolAllocator<> > buffer;
EXPECT_EQ(0, buffer.GetSize());
rapidjson::PutN(buffer, ' ', 1);
EXPECT_EQ(1, buffer.GetSize());
}
TEST(StringBuffer, Clear) {
StringBuffer buffer;
buffer.Put('A');

View File

@ -545,8 +545,10 @@ TEST(Value, Int64) {
// Templated functions
EXPECT_TRUE(z.Is<int64_t>());
EXPECT_EQ(i, z.Get<int64_t>());
#if 0 // signed integer underflow is undefined behaviour
EXPECT_EQ(i - 1, z.Set(i - 1).Get<int64_t>());
EXPECT_EQ(i - 2, z.Set<int64_t>(i - 2).Get<int64_t>());
#endif
}
TEST(Value, Uint64) {
@ -671,6 +673,7 @@ TEST(Value, Float) {
}
TEST(Value, IsLosslessDouble) {
EXPECT_TRUE(Value(0.0).IsLosslessDouble());
EXPECT_TRUE(Value(12.34).IsLosslessDouble());
EXPECT_TRUE(Value(-123).IsLosslessDouble());
EXPECT_TRUE(Value(2147483648u).IsLosslessDouble());
@ -679,8 +682,19 @@ TEST(Value, IsLosslessDouble) {
EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble());
#endif
EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble());
EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble());
EXPECT_FALSE(Value(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // INT64_MAX
EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // -INT64_MAX
EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF)) - 1).IsLosslessDouble()); // INT64_MIN
EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble()); // UINT64_MAX
EXPECT_TRUE(Value(3.4028234e38f).IsLosslessDouble()); // FLT_MAX
EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessDouble()); // -FLT_MAX
EXPECT_TRUE(Value(1.17549435e-38f).IsLosslessDouble()); // FLT_MIN
EXPECT_TRUE(Value(-1.17549435e-38f).IsLosslessDouble()); // -FLT_MIN
EXPECT_TRUE(Value(1.7976931348623157e+308).IsLosslessDouble()); // DBL_MAX
EXPECT_TRUE(Value(-1.7976931348623157e+308).IsLosslessDouble()); // -DBL_MAX
EXPECT_TRUE(Value(2.2250738585072014e-308).IsLosslessDouble()); // DBL_MIN
EXPECT_TRUE(Value(-2.2250738585072014e-308).IsLosslessDouble()); // -DBL_MIN
}
TEST(Value, IsLosslessFloat) {
@ -1119,14 +1133,18 @@ TEST(Value, ArrayHelperRangeFor) {
{
int i = 0;
for (auto& v : x.GetArray())
EXPECT_EQ(i++, v.GetInt());
for (auto& v : x.GetArray()) {
EXPECT_EQ(i, v.GetInt());
i++;
}
EXPECT_EQ(i, 10);
}
{
int i = 0;
for (const auto& v : const_cast<const Value&>(x).GetArray())
EXPECT_EQ(i++, v.GetInt());
for (const auto& v : const_cast<const Value&>(x).GetArray()) {
EXPECT_EQ(i, v.GetInt());
i++;
}
EXPECT_EQ(i, 10);
}

View File

@ -439,33 +439,47 @@ TEST(Writer, InvalidEventSequence) {
}
}
extern double zero; // clang -Wmissing-variable-declarations
double zero = 0.0; // Use global variable to prevent compiler warning
TEST(Writer, NaN) {
double nan = zero / zero;
double nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_TRUE(internal::Double(nan).IsNan());
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(nan));
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(nan));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(nan));
EXPECT_STREQ("NaN", buffer.GetString());
}
GenericStringBuffer<UTF16<> > buffer2;
Writer<GenericStringBuffer<UTF16<> > > writer2(buffer2);
EXPECT_FALSE(writer2.Double(nan));
}
TEST(Writer, Inf) {
double inf = 1.0 / zero;
double inf = std::numeric_limits<double>::infinity();
EXPECT_TRUE(internal::Double(inf).IsInf());
StringBuffer buffer;
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(inf));
EXPECT_FALSE(writer.Double(inf));
}
{
Writer<StringBuffer> writer(buffer);
EXPECT_FALSE(writer.Double(-inf));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(inf));
}
{
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
EXPECT_TRUE(writer.Double(-inf));
}
EXPECT_STREQ("Infinity-Infinity", buffer.GetString());
}
TEST(Writer, RawValue) {

View File

@ -42,8 +42,8 @@ abort() {
skip "Running Doxygen only for updates on 'master' branch (current: ${TRAVIS_BRANCH})."
# check for job number
[ "${TRAVIS_JOB_NUMBER}" = "${TRAVIS_BUILD_NUMBER}.1" ] || \
skip "Running Doxygen only on first job of build ${TRAVIS_BUILD_NUMBER} (current: ${TRAVIS_JOB_NUMBER})."
# [ "${TRAVIS_JOB_NUMBER}" = "${TRAVIS_BUILD_NUMBER}.1" ] || \
# skip "Running Doxygen only on first job of build ${TRAVIS_BUILD_NUMBER} (current: ${TRAVIS_JOB_NUMBER})."
# install doxygen binary distribution
doxygen_install()