diff --git a/CMakeLists.txt b/CMakeLists.txt
index 68139ba..51ee620 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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()
diff --git a/doc/dom.md b/doc/dom.md
index f3e4208..24f1a39 100644
--- a/doc/dom.md
+++ b/doc/dom.md
@@ -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()));
// ...
}
~~~~~~~~~~
diff --git a/doc/dom.zh-cn.md b/doc/dom.zh-cn.md
index c7fcfff..bb4eafb 100644
--- a/doc/dom.zh-cn.md
+++ b/doc/dom.zh-cn.md
@@ -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()));
// ...
}
~~~~~~~~~~
diff --git a/doc/faq.md b/doc/faq.md
index b00b4c6..8f441fe 100644
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -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?
diff --git a/doc/misc/header.html b/doc/misc/header.html
index 2dbe721..d43f2aa 100644
--- a/doc/misc/header.html
+++ b/doc/misc/header.html
@@ -16,6 +16,15 @@ $mathjax
$extrastylesheet
+
diff --git a/doc/stream.md b/doc/stream.md
index 94bc10d..7b3c5ca 100644
--- a/doc/stream.md
+++ b/doc/stream.md
@@ -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.
diff --git a/doc/stream.zh-cn.md b/doc/stream.zh-cn.md
index 5ac32f8..0f930a9 100644
--- a/doc/stream.zh-cn.md
+++ b/doc/stream.zh-cn.md
@@ -320,7 +320,7 @@ std::stringstream ss(json);
IStreamWrapper is(ss);
Document d;
-d.Parse(is);
+d.ParseStream(is);
~~~~~~~~~~
但要注意,由于标准库的内部开销问,此实现的性能可能不如RapidJSON的内存/文件流。
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 3508918..1211023 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -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.
}
~~~~~~~~~~
diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md
index d1381be..3ecaec8 100644
--- a/doc/tutorial.zh-cn.md
+++ b/doc/tutorial.zh-cn.md
@@ -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本身至新成员的Value(16字节)
+ o.AddMember("contacts", contacts, d.GetAllocator()); // 只需 memcpy() contacts本身至新成员的Value(16字节)
// contacts在这里变成Null。它的析构是平凡的。
}
~~~~~~~~~~
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index 6463212..8063d89 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -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
@@ -13,6 +14,8 @@ set(EXAMPLES
simplereader
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")
diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h
index f615ffd..6be2776 100644
--- a/include/rapidjson/allocators.h
+++ b/include/rapidjson/allocators.h
@@ -181,7 +181,7 @@ public:
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
- void *buffer = reinterpret_cast(chunkHead_ + 1) + chunkHead_->size;
+ void *buffer = reinterpret_cast(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(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(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
+ ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h
index 889cdfa..f5c1be9 100644
--- a/include/rapidjson/document.h
+++ b/include/rapidjson/document.h
@@ -69,6 +69,9 @@ RAPIDJSON_NAMESPACE_BEGIN
template
class GenericValue;
+template
+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
+ GenericValue(GenericDocument&& rhs);
+
+ //! Move assignment from a GenericDocument is not permitted.
+ template
+ GenericValue& operator=(GenericDocument&& 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(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(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
//!@{
diff --git a/include/rapidjson/encodedstream.h b/include/rapidjson/encodedstream.h
index 9a93b38..7bc6ad3 100644
--- a/include/rapidjson/encodedstream.h
+++ b/include/rapidjson/encodedstream.h
@@ -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(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(); }
diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h
index 99a30ac..4477cf5 100755
--- a/include/rapidjson/internal/biginteger.h
+++ b/include/rapidjson/internal/biginteger.h
@@ -19,6 +19,7 @@
#if defined(_MSC_VER) && defined(_M_AMD64)
#include // for _umul128
+#pragma intrinsic(_umul128)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@@ -50,7 +51,16 @@ public:
if (length > 0)
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;
}
diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h
index 3b6c423..7a55ee3 100644
--- a/include/rapidjson/internal/diyfp.h
+++ b/include/rapidjson/internal/diyfp.h
@@ -24,6 +24,7 @@
#if defined(_MSC_VER) && defined(_M_AMD64)
#include
#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(exp) + 348u) / 8u;
+ *outExp = -348 + static_cast(index) * 8;
return GetCachedPowerByIndex(index);
}
diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h
index 2d8d2e4..d04ae21 100644
--- a/include/rapidjson/internal/dtoa.h
+++ b/include/rapidjson/internal/dtoa.h
@@ -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(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(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(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(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(length - 1));
buffer[1] = '.';
buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h
index e3f0336..2fdaf54 100644
--- a/include/rapidjson/internal/ieee754.h
+++ b/include/rapidjson/internal/ieee754.h
@@ -53,7 +53,7 @@ public:
else if (order <= -1074)
return 0;
else
- return order + 1074;
+ return (unsigned)order + 1074;
}
private:
diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h
index f911588..c7b78f6 100644
--- a/include/rapidjson/internal/stack.h
+++ b/include/rapidjson/internal/stack.h
@@ -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() {
diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h
index ace65f6..a1b8211 100644
--- a/include/rapidjson/internal/strtod.h
+++ b/include/rapidjson/internal/strtod.h
@@ -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(dS_Exp5)) <<= static_cast(dS_Exp2);
BigInteger bS(bInt);
- bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
+ bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2);
BigInteger hS(1);
- hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
+ hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(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(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(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(kUlp);
precisionSize -= scaleExp;
}
- DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
+ DiyFp rounded(v.f >> precisionSize, v.e + static_cast(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(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(error) >= precisionBits || precisionBits >= halfWay + static_cast(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(delta);
length = kMaxDecimalDigit;
}
diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h
new file mode 100644
index 0000000..41e7e20
--- /dev/null
+++ b/include/rapidjson/internal/swap.h
@@ -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++ 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
+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_
diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h
index f5d5630..b0dabc7 100644
--- a/include/rapidjson/rapidjson.h
+++ b/include/rapidjson/rapidjson.h
@@ -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
diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h
index 8989e38..9a17301 100644
--- a/include/rapidjson/reader.h
+++ b/include/rapidjson/reader.h
@@ -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());
}
}
diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h
index 40cdb35..8fcffbe 100644
--- a/include/rapidjson/writer.h
+++ b/include/rapidjson/writer.h
@@ -350,7 +350,7 @@ template<>
inline bool Writer::WriteInt(int i) {
char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer);
- os_->Pop(11 - (end - buffer));
+ os_->Pop(static_cast(11 - (end - buffer)));
return true;
}
@@ -358,7 +358,7 @@ template<>
inline bool Writer::WriteUint(unsigned u) {
char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer);
- os_->Pop(10 - (end - buffer));
+ os_->Pop(static_cast(10 - (end - buffer)));
return true;
}
@@ -366,7 +366,7 @@ template<>
inline bool Writer::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(21 - (end - buffer)));
return true;
}
@@ -374,7 +374,7 @@ template<>
inline bool Writer::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(20 - (end - buffer)));
return true;
}
@@ -382,7 +382,7 @@ template<>
inline bool Writer::WriteDouble(double d) {
char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer);
- os_->Pop(25 - (end - buffer));
+ os_->Pop(static_cast(25 - (end - buffer)));
return true;
}
diff --git a/library.json b/library.json
new file mode 100644
index 0000000..47fd352
Binary files /dev/null and b/library.json differ
diff --git a/license.txt b/license.txt
index a1bb283..03e66d6 100644
--- a/license.txt
+++ b/license.txt
@@ -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:
diff --git a/readme.md b/readme.md
index 19da386..8682df1 100644
--- a/readme.md
+++ b/readme.md
@@ -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
diff --git a/readme.zh-cn.md b/readme.zh-cn.md
index ec6bd90..5124f8e 100644
--- a/readme.zh-cn.md
+++ b/readme.zh-cn.md
@@ -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 状态
diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt
index 76b413e..e2386c0 100644
--- a/test/unittest/CMakeLists.txt
+++ b/test/unittest/CMakeLists.txt
@@ -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()
diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp
index 2ee6b10..810a99c 100644
--- a/test/unittest/documenttest.cpp
+++ b/test/unittest/documenttest.cpp
@@ -19,6 +19,7 @@
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
#include
+#include
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;
diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp
index f14669a..900783c 100644
--- a/test/unittest/valuetest.cpp
+++ b/test/unittest/valuetest.cpp
@@ -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) {
diff --git a/travis-doxygen.sh b/travis-doxygen.sh
index ad80536..1023108 100755
--- a/travis-doxygen.sh
+++ b/travis-doxygen.sh
@@ -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";
}