Merge branch 'master' into schema

This commit is contained in:
Milo Yip 2015-09-01 09:32:29 +08:00
commit 74f0673dad
31 changed files with 293 additions and 61 deletions

View File

@ -26,9 +26,9 @@ if(RAPIDJSON_HAS_STDSTRING)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif()

View File

@ -124,7 +124,7 @@ And the `InputStream` is type of input stream.
## Parse Error {#ParseError}
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffet()`.
When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffset()`.
Parse Error Code | Description
--------------------------------------------|---------------------------------------------------
@ -159,8 +159,8 @@ Here shows an example of parse error handling.
Document d;
if (d.Parse(json).HasParseError()) {
fprintf(stderr, "\nError(offset %u): %s\n",
(unsigned)reader.GetErrorOffset(),
GetParseError_En(reader.GetParseErrorCode()));
(unsigned)d.GetErrorOffset(),
GetParseError_En(d.GetParseErrorCode()));
// ...
}
~~~~~~~~~~

View File

@ -124,7 +124,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
## 解析错误 {#ParseError}
当解析过程顺利完成,`Document`便会含有解析结果。当过程出现错误原来的DOM会*维持不便*。可使用`bool HasParseError()``ParseErrorCode GetParseError()``size_t GetParseOffet()`获取解析的错误状态。
当解析过程顺利完成,`Document`便会含有解析结果。当过程出现错误原来的DOM会*维持不便*。可使用`bool HasParseError()``ParseErrorCode GetParseError()``size_t GetParseOffset()`获取解析的错误状态。
解析错误代号 | 描述
--------------------------------------------|---------------------------------------------------
@ -159,8 +159,8 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
Document d;
if (d.Parse(json).HasParseError()) {
fprintf(stderr, "\nError(offset %u): %s\n",
(unsigned)reader.GetErrorOffset(),
GetParseError_En(reader.GetParseErrorCode()));
(unsigned)d.GetErrorOffset(),
GetParseError_En(d.GetParseErrorCode()));
// ...
}
~~~~~~~~~~

View File

@ -102,6 +102,64 @@
Some applications use 64-bit unsigned/signed integers. And these integers cannot be converted into `double` without loss of precision. So the parsers detects whether a JSON number is convertible to different types of integers and/or `double`.
8. How to clear-and-minimize a document or value?
Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data:
```
Document d;
...
d.SetObject(); // clear and minimize
```
Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize):
```
Value(kObjectType).Swap(d);
```
or equivalent, but sightly longer to type:
```
d.Swap(Value(kObjectType).Move());
```
9. How to insert a document node into another document?
Let's take the following two DOM trees represented as JSON documents:
```
Document person;
person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}");
Document address;
address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}");
```
Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`:
```
{ "person": {
"name": { "first": "Adam", "last": "Thomas" },
"address": { "city": "Moscow", "street": "Quiet" }
}
}
```
The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer.
Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value:
```
Documnet address(person.GetAllocator());
...
person["person"].AddMember("address", address["address"], person.GetAllocator());
```
Alternatively, if we don't want to explicitly refer to the root value of `address` by name, we can refer to it via iterator:
```
auto addressRoot = address.MemberBegin();
person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator());
```
Second way is to deep-clone the value from the address document:
```
Value addressValue = Value(address["address"], person.GetAllocator());
person["person"].AddMember("address", addressValue, person.GetAllocator());
```
## Document/Value (DOM)
1. What is move semantics? Why?

View File

@ -16,6 +16,15 @@ $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>

View File

@ -320,7 +320,7 @@ std::stringstream ss(json);
IStreamWrapper is(ss);
Document d;
d.Parse(is);
d.ParseStream(is);
~~~~~~~~~~
Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library.

View File

@ -320,7 +320,7 @@ std::stringstream ss(json);
IStreamWrapper is(ss);
Document d;
d.Parse(is);
d.ParseStream(is);
~~~~~~~~~~
但要注意由于标准库的内部开销问此实现的性能可能不如RapidJSON的内存文件流。

View File

@ -292,12 +292,13 @@ The simple answer is performance. For fixed size JSON types (Number, True, False
For example, if normal *copy* semantics was used:
~~~~~~~~~~cpp
Document d;
Value o(kObjectType);
{
Value contacts(kArrayType);
// adding elements to contacts array.
// ...
o.AddMember("contacts", contacts); // deep clone contacts (may be with lots of allocations)
o.AddMember("contacts", contacts, d.GetAllocator()); // deep clone contacts (may be with lots of allocations)
// destruct contacts.
}
~~~~~~~~~~
@ -313,11 +314,12 @@ To make RapidJSON simple and fast, we chose to use *move* semantics for assignme
So, with move semantics, the above example becomes:
~~~~~~~~~~cpp
Document d;
Value o(kObjectType);
{
Value contacts(kArrayType);
// adding elements to contacts array.
o.AddMember("contacts", contacts); // just memcpy() of contacts itself to the value of new member (16 bytes)
o.AddMember("contacts", contacts, d.GetAllocator()); // just memcpy() of contacts itself to the value of new member (16 bytes)
// contacts became Null here. Its destruction is trivial.
}
~~~~~~~~~~

View File

@ -297,7 +297,7 @@ Value o(kObjectType);
Value contacts(kArrayType);
// 把元素加进contacts数组。
// ...
o.AddMember("contacts", contacts); // 深度复制contacts (可能有大量内存分配)
o.AddMember("contacts", contacts, d.GetAllocator()); // 深度复制contacts (可能有大量内存分配)
// 析构contacts。
}
~~~~~~~~~~
@ -317,7 +317,7 @@ Value o(kObjectType);
{
Value contacts(kArrayType);
// adding elements to contacts array.
o.AddMember("contacts", contacts); // 只需 memcpy() contacts本身至新成员的Value16字节
o.AddMember("contacts", contacts, d.GetAllocator()); // 只需 memcpy() contacts本身至新成员的Value16字节
// contacts在这里变成Null。它的析构是平凡的。
}
~~~~~~~~~~

View File

@ -1,6 +1,7 @@
# Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
# Copyright (c) 2013 Rafal Jeczalik (rjeczalik@gmail.com)
# Distributed under the MIT License (see license.txt file)
cmake_minimum_required(VERSION 2.8)
set(EXAMPLES
capitalize
@ -14,6 +15,8 @@ set(EXAMPLES
simplewriter
tutorial)
include_directories("../include/")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")

View File

@ -181,7 +181,7 @@ public:
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
return buffer;
}
@ -199,7 +199,7 @@ public:
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
size_t increment = static_cast<size_t>(newSize - originalSize);
increment = RAPIDJSON_ALIGN(increment);
if (chunkHead_->size + increment <= chunkHead_->capacity) {
@ -231,7 +231,7 @@ private:
void AddChunk(size_t capacity) {
if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;

View File

@ -69,6 +69,9 @@ RAPIDJSON_NAMESPACE_BEGIN
template <typename Encoding, typename Allocator>
class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
//! Name-value pair in a JSON object value.
/*!
This class was internal to GenericValue. It used to be a inner struct.
@ -446,6 +449,16 @@ private:
//! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Moving from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
//! Move assignment from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
#endif
public:
//! Constructor with JSON value type.
@ -660,6 +673,20 @@ public:
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//! Prepare Value for move semantics
/*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
@ -1749,7 +1776,22 @@ public:
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor
/*! \param allocator Optional allocator for allocating memory.
/*! Creates an empty document of specified type.
\param type Mandatory type of object to create.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
//! Constructor
/*! Creates an empty document which type is Null.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
@ -1763,7 +1805,7 @@ public:
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
: ValueType(std::move(rhs)),
: ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)),
@ -1803,6 +1845,35 @@ public:
}
#endif
//! Exchange the contents of this document with those of another.
/*!
\param other Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
//!@name Parse from stream
//!@{

View File

@ -146,7 +146,7 @@ private:
if (!c)
return;
unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }

View File

@ -19,6 +19,7 @@
#if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128
#pragma intrinsic(_umul128)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -51,6 +52,15 @@ public:
AppendDecimal64(decimals + i, decimals + i + length);
}
BigInteger& operator=(const BigInteger &rhs)
{
if (this != &rhs) {
count_ = rhs.count_;
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
}
return *this;
}
BigInteger& operator=(uint64_t u) {
digits_[0] = u;
count_ = 1;
@ -230,7 +240,7 @@ private:
uint64_t r = 0;
for (const char* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
r = r * 10 + (*p - '0');
r = r * 10u + (unsigned)(*p - '0');
}
return r;
}

View File

@ -24,6 +24,7 @@
#if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h>
#pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -232,8 +233,8 @@ inline DiyFp GetCachedPower(int e, int* K) {
}
inline DiyFp GetCachedPower10(int exp, int *outExp) {
unsigned index = (exp + 348) / 8;
*outExp = -348 + index * 8;
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
*outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index);
}

View File

@ -62,7 +62,7 @@ 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); // kappa in [0, 9]
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0;
while (kappa > 0) {
@ -101,7 +101,7 @@ 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[-kappa]);
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast<int>(kappa)]);
return;
}
}
@ -158,14 +158,14 @@ inline char* Prettify(char* buffer, int length, int k) {
}
else if (0 < kk && kk <= 21) {
// 1234e-2 -> 12.34
std::memmove(&buffer[kk + 1], &buffer[kk], length - kk);
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
buffer[kk] = '.';
return &buffer[length + 1];
}
else if (-6 < kk && kk <= 0) {
// 1234e-6 -> 0.001234
const int offset = 2 - kk;
std::memmove(&buffer[offset], &buffer[0], length);
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
buffer[0] = '0';
buffer[1] = '.';
for (int i = 2; i < offset; i++)
@ -179,7 +179,7 @@ inline char* Prettify(char* buffer, int length, int k) {
}
else {
// 1234e30 -> 1.234e33
std::memmove(&buffer[2], &buffer[1], length - 1);
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
buffer[1] = '.';
buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]);

View File

@ -53,7 +53,7 @@ public:
else if (order <= -1074)
return 0;
else
return order + 1074;
return (unsigned)order + 1074;
}
private:

View File

@ -16,6 +16,7 @@
#define RAPIDJSON_INTERNAL_STACK_H_
#include "../rapidjson.h"
#include "swap.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
@ -81,6 +82,15 @@ public:
}
#endif
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(stack_, rhs.stack_);
internal::Swap(stackTop_, rhs.stackTop_);
internal::Swap(stackEnd_, rhs.stackEnd_);
internal::Swap(initialCapacity_, rhs.initialCapacity_);
}
void Clear() { stackTop_ = stack_; }
void ShrinkToFit() {

View File

@ -95,13 +95,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
hS_Exp2 -= common_Exp2;
BigInteger dS = d;
dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2;
dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
BigInteger bS(bInt);
bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
BigInteger hS(1);
hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
BigInteger delta(0);
dS.Difference(bS, &delta);
@ -134,7 +134,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
break;
significand = significand * 10 + (decimals[i] - '0');
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
}
if (i < length && decimals[i] >= '5') // Rounding
@ -163,10 +163,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
};
int adjustment = dExp - actualExp - 1;
int adjustment = dExp - actualExp - 1;
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment];
if (length + adjustment > 19) // has more digits than decimal digits in 64-bit
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
error += kUlp / 2;
}
@ -184,14 +184,14 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp;
v.e += scaleExp;
error = (error >> scaleExp) + 1 + kUlp;
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
precisionSize -= scaleExp;
}
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
if (precisionBits >= halfWay + error) {
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
rounded.f++;
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
rounded.f >>= 1;
@ -201,7 +201,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
*result = rounded.ToDouble();
return halfWay - error >= precisionBits || precisionBits >= halfWay + error;
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
}
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
@ -249,7 +249,7 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
if ((int)length > kMaxDecimalDigit) {
int delta = (int(length) - kMaxDecimalDigit);
exp += delta;
decimalPosition -= delta;
decimalPosition -= static_cast<unsigned>(delta);
length = kMaxDecimalDigit;
}

View File

@ -0,0 +1,37 @@
// 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_INTERNAL_SWAP_H_
#define RAPIDJSON_INTERNAL_SWAP_H_
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
//! Custom swap() to avoid dependency on C++ <algorith> header
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
\note This has the same semantics as std::swap().
*/
template <typename T>
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
T tmp = a;
a = b;
b = tmp;
}
} // namespace internal
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_INTERNAL_SWAP_H_

View File

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

View File

@ -271,7 +271,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
// The rest of string using SIMD
static const char whitespace[16] = " \n\r\t";
const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
for (;; p += 16) {
const __m128i s = _mm_load_si128((const __m128i *)p);
@ -1387,13 +1387,13 @@ private:
}
switch (src) {
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
case IterativeParsingObjectInitialState:
case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
}
}

View File

@ -350,7 +350,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt(int i) {
char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer);
os_->Pop(11 - (end - buffer));
os_->Pop(static_cast<size_t>(11 - (end - buffer)));
return true;
}
@ -358,7 +358,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer);
os_->Pop(10 - (end - buffer));
os_->Pop(static_cast<size_t>(10 - (end - buffer)));
return true;
}
@ -366,7 +366,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer);
os_->Pop(21 - (end - buffer));
os_->Pop(static_cast<size_t>(21 - (end - buffer)));
return true;
}
@ -374,7 +374,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer);
os_->Pop(20 - (end - buffer));
os_->Pop(static_cast<size_t>(20 - (end - buffer)));
return true;
}
@ -382,7 +382,7 @@ template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) {
char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer);
os_->Pop(25 - (end - buffer));
os_->Pop(static_cast<size_t>(25 - (end - buffer)));
return true;
}

BIN
library.json Normal file

Binary file not shown.

View File

@ -3,7 +3,7 @@ Tencent is pleased to support the open source community by making RapidJSON avai
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License.
If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON.
If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license.
A copy of the MIT License is included in this file.
Other dependencies and licenses:

View File

@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/)
* RapidJSON Documentation
* [English](http://miloyip.github.io/rapidjson/)
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/)
* [English](http://rapidjson.org/)
* [简体中文](http://rapidjson.org/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference.
## Build status

View File

@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights
* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/)
* RapidJSON 文档
* [English](http://miloyip.github.io/rapidjson/)
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/)
* [English](http://rapidjson.org/)
* [简体中文](http://rapidjson.org/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI但不含API参考手册。
## Build 状态

View File

@ -24,7 +24,7 @@ set(UNITTEST_SOURCES
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")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif()

View File

@ -19,6 +19,7 @@
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
#include <sstream>
#include <algorithm>
using namespace rapidjson;
@ -202,7 +203,8 @@ TEST(Document, Swap) {
o.SetObject().AddMember("a", 1, a);
// Swap between Document and Value
d1.Swap(o);
// d1.Swap(o); // doesn't compile
o.Swap(d1);
EXPECT_TRUE(d1.IsObject());
EXPECT_TRUE(o.IsArray());
@ -212,8 +214,30 @@ TEST(Document, Swap) {
d1.Swap(d2);
EXPECT_TRUE(d1.IsArray());
EXPECT_TRUE(d2.IsObject());
EXPECT_EQ(&d2.GetAllocator(), &a);
// reset value
Value().Swap(d1);
EXPECT_TRUE(d1.IsNull());
// reset document, including allocator
Document().Swap(d2);
EXPECT_TRUE(d2.IsNull());
EXPECT_NE(&d2.GetAllocator(), &a);
// testing std::swap compatibility
d1.SetBool(true);
using std::swap;
swap(d1, d2);
EXPECT_TRUE(d1.IsNull());
EXPECT_TRUE(d2.IsTrue());
swap(o, d2);
EXPECT_TRUE(o.IsTrue());
EXPECT_TRUE(d2.IsArray());
}
// This should be slow due to assignment in inner-loop.
struct OutputStringStream : public std::ostringstream {
typedef char Ch;

View File

@ -272,6 +272,12 @@ TEST(Value, Swap) {
EXPECT_TRUE(v1.IsObject());
EXPECT_TRUE(v2.IsInt());
EXPECT_EQ(1234, v2.GetInt());
// testing std::swap compatibility
using std::swap;
swap(v1, v2);
EXPECT_TRUE(v1.IsInt());
EXPECT_TRUE(v2.IsObject());
}
TEST(Value, Null) {

View File

@ -78,6 +78,7 @@ gh_pages_prepare()
gh_pages_commit() {
cd "${TRAVIS_BUILD_DIR}/build/doc/html";
echo "rapidjson.org" > CNAME
git add --all;
git diff-index --quiet HEAD || git commit -m "Automatic doxygen build";
}