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() endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 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") 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") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif() endif()

View File

@ -124,7 +124,7 @@ And the `InputStream` is type of input stream.
## Parse Error {#ParseError} ## 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 Parse Error Code | Description
--------------------------------------------|--------------------------------------------------- --------------------------------------------|---------------------------------------------------
@ -159,8 +159,8 @@ Here shows an example of parse error handling.
Document d; Document d;
if (d.Parse(json).HasParseError()) { if (d.Parse(json).HasParseError()) {
fprintf(stderr, "\nError(offset %u): %s\n", fprintf(stderr, "\nError(offset %u): %s\n",
(unsigned)reader.GetErrorOffset(), (unsigned)d.GetErrorOffset(),
GetParseError_En(reader.GetParseErrorCode())); GetParseError_En(d.GetParseErrorCode()));
// ... // ...
} }
~~~~~~~~~~ ~~~~~~~~~~

View File

@ -124,7 +124,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
## 解析错误 {#ParseError} ## 解析错误 {#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; Document d;
if (d.Parse(json).HasParseError()) { if (d.Parse(json).HasParseError()) {
fprintf(stderr, "\nError(offset %u): %s\n", fprintf(stderr, "\nError(offset %u): %s\n",
(unsigned)reader.GetErrorOffset(), (unsigned)d.GetErrorOffset(),
GetParseError_En(reader.GetParseErrorCode())); 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`. 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) ## Document/Value (DOM)
1. What is move semantics? Why? 1. What is move semantics? Why?

View File

@ -16,6 +16,15 @@ $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" /> <link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet $extrastylesheet
</head> </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> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <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> <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); IStreamWrapper is(ss);
Document d; 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. 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); IStreamWrapper is(ss);
Document d; Document d;
d.Parse(is); d.ParseStream(is);
~~~~~~~~~~ ~~~~~~~~~~
但要注意由于标准库的内部开销问此实现的性能可能不如RapidJSON的内存文件流。 但要注意由于标准库的内部开销问此实现的性能可能不如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: For example, if normal *copy* semantics was used:
~~~~~~~~~~cpp ~~~~~~~~~~cpp
Document d;
Value o(kObjectType); Value o(kObjectType);
{ {
Value contacts(kArrayType); Value contacts(kArrayType);
// adding elements to contacts array. // 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. // 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: So, with move semantics, the above example becomes:
~~~~~~~~~~cpp ~~~~~~~~~~cpp
Document d;
Value o(kObjectType); Value o(kObjectType);
{ {
Value contacts(kArrayType); Value contacts(kArrayType);
// adding elements to contacts array. // 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. // contacts became Null here. Its destruction is trivial.
} }
~~~~~~~~~~ ~~~~~~~~~~

View File

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

View File

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

View File

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

View File

@ -69,6 +69,9 @@ RAPIDJSON_NAMESPACE_BEGIN
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericValue; class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
//! Name-value pair in a JSON object value. //! Name-value pair in a JSON object value.
/*! /*!
This class was internal to GenericValue. It used to be a inner struct. This class was internal to GenericValue. It used to be a inner struct.
@ -446,6 +449,16 @@ private:
//! Copy constructor is not permitted. //! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs); 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: public:
//! Constructor with JSON value type. //! Constructor with JSON value type.
@ -660,6 +673,20 @@ public:
return *this; 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 //! Prepare Value for move semantics
/*! \return *this */ /*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
@ -1749,7 +1776,22 @@ public:
typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor //! 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 stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack. \param stackAllocator Optional allocator for allocating memory for stack.
*/ */
@ -1763,7 +1805,7 @@ public:
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11 //! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT 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_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)), stack_(std::move(rhs.stack_)),
@ -1803,6 +1845,35 @@ public:
} }
#endif #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 //!@name Parse from stream
//!@{ //!@{

View File

@ -146,7 +146,7 @@ private:
if (!c) if (!c)
return; 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; hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } 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(); } 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) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128 #include <intrin.h> // for _umul128
#pragma intrinsic(_umul128)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -51,6 +52,15 @@ public:
AppendDecimal64(decimals + i, decimals + i + length); 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) { BigInteger& operator=(uint64_t u) {
digits_[0] = u; digits_[0] = u;
count_ = 1; count_ = 1;
@ -230,7 +240,7 @@ private:
uint64_t r = 0; uint64_t r = 0;
for (const char* p = begin; p != end; ++p) { for (const char* p = begin; p != end; ++p) {
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
r = r * 10 + (*p - '0'); r = r * 10u + (unsigned)(*p - '0');
} }
return r; return r;
} }

View File

@ -24,6 +24,7 @@
#if defined(_MSC_VER) && defined(_M_AMD64) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -232,8 +233,8 @@ inline DiyFp GetCachedPower(int e, int* K) {
} }
inline DiyFp GetCachedPower10(int exp, int *outExp) { inline DiyFp GetCachedPower10(int exp, int *outExp) {
unsigned index = (exp + 348) / 8; unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
*outExp = -348 + index * 8; *outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index); 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; const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1); uint64_t p2 = Mp.f & (one.f - 1);
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0; *len = 0;
while (kappa > 0) { while (kappa > 0) {
@ -101,7 +101,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--; kappa--;
if (p2 < delta) { if (p2 < delta) {
*K += kappa; *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; return;
} }
} }
@ -158,14 +158,14 @@ inline char* Prettify(char* buffer, int length, int k) {
} }
else if (0 < kk && kk <= 21) { else if (0 < kk && kk <= 21) {
// 1234e-2 -> 12.34 // 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] = '.'; buffer[kk] = '.';
return &buffer[length + 1]; return &buffer[length + 1];
} }
else if (-6 < kk && kk <= 0) { else if (-6 < kk && kk <= 0) {
// 1234e-6 -> 0.001234 // 1234e-6 -> 0.001234
const int offset = 2 - kk; 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[0] = '0';
buffer[1] = '.'; buffer[1] = '.';
for (int i = 2; i < offset; i++) for (int i = 2; i < offset; i++)
@ -179,7 +179,7 @@ inline char* Prettify(char* buffer, int length, int k) {
} }
else { else {
// 1234e30 -> 1.234e33 // 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[1] = '.';
buffer[length + 1] = 'e'; buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]); return WriteExponent(kk - 1, &buffer[0 + length + 2]);

View File

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

View File

@ -16,6 +16,7 @@
#define RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_
#include "../rapidjson.h" #include "../rapidjson.h"
#include "swap.h"
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
@ -81,6 +82,15 @@ public:
} }
#endif #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 Clear() { stackTop_ = stack_; }
void ShrinkToFit() { void ShrinkToFit() {

View File

@ -95,13 +95,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
hS_Exp2 -= common_Exp2; hS_Exp2 -= common_Exp2;
BigInteger dS = d; BigInteger dS = d;
dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
BigInteger bS(bInt); BigInteger bS(bInt);
bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
BigInteger hS(1); BigInteger hS(1);
hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
BigInteger delta(0); BigInteger delta(0);
dS.Difference(bS, &delta); 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) || if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
break; break;
significand = significand * 10 + (decimals[i] - '0'); significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
} }
if (i < length && decimals[i] >= '5') // Rounding if (i < length && decimals[i] >= '5') // Rounding
@ -166,7 +166,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
int adjustment = dExp - actualExp - 1; int adjustment = dExp - actualExp - 1;
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment]; 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; error += kUlp / 2;
} }
@ -184,14 +184,14 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
unsigned scaleExp = (precisionSize + kUlpShift) - 63; unsigned scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp; v.f >>= scaleExp;
v.e += scaleExp; v.e += scaleExp;
error = (error >> scaleExp) + 1 + kUlp; error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
precisionSize -= scaleExp; 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 precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (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++; rounded.f++;
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
rounded.f >>= 1; rounded.f >>= 1;
@ -201,7 +201,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
*result = rounded.ToDouble(); *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) { 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) { if ((int)length > kMaxDecimalDigit) {
int delta = (int(length) - kMaxDecimalDigit); int delta = (int(length) - kMaxDecimalDigit);
exp += delta; exp += delta;
decimalPosition -= delta; decimalPosition -= static_cast<unsigned>(delta);
length = kMaxDecimalDigit; 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 //! Whether using 64-bit architecture
#ifndef RAPIDJSON_64BIT #ifndef RAPIDJSON_64BIT
#if defined(__LP64__) || defined(_WIN64) #if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__)
#define RAPIDJSON_64BIT 1 #define RAPIDJSON_64BIT 1
#else #else
#define RAPIDJSON_64BIT 0 #define RAPIDJSON_64BIT 0

View File

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

View File

@ -350,7 +350,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt(int i) { inline bool Writer<StringBuffer>::WriteInt(int i) {
char *buffer = os_->Push(11); char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer); const char* end = internal::i32toa(i, buffer);
os_->Pop(11 - (end - buffer)); os_->Pop(static_cast<size_t>(11 - (end - buffer)));
return true; return true;
} }
@ -358,7 +358,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint(unsigned u) { inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
char *buffer = os_->Push(10); char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer); const char* end = internal::u32toa(u, buffer);
os_->Pop(10 - (end - buffer)); os_->Pop(static_cast<size_t>(10 - (end - buffer)));
return true; return true;
} }
@ -366,7 +366,7 @@ template<>
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21); char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer); const char* end = internal::i64toa(i64, buffer);
os_->Pop(21 - (end - buffer)); os_->Pop(static_cast<size_t>(21 - (end - buffer)));
return true; return true;
} }
@ -374,7 +374,7 @@ template<>
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20); char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer); const char* end = internal::u64toa(u, buffer);
os_->Pop(20 - (end - buffer)); os_->Pop(static_cast<size_t>(20 - (end - buffer)));
return true; return true;
} }
@ -382,7 +382,7 @@ template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) { inline bool Writer<StringBuffer>::WriteDouble(double d) {
char *buffer = os_->Push(25); char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer); char* end = internal::dtoa(d, buffer);
os_->Pop(25 - (end - buffer)); os_->Pop(static_cast<size_t>(25 - (end - buffer)));
return true; 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. 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 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. A copy of the MIT License is included in this file.
Other dependencies and licenses: 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 GitHub](https://github.com/miloyip/rapidjson/)
* RapidJSON Documentation * RapidJSON Documentation
* [English](http://miloyip.github.io/rapidjson/) * [English](http://rapidjson.org/)
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) * [简体中文](http://rapidjson.org/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference.
## Build status ## 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 GitHub](https://github.com/miloyip/rapidjson/)
* RapidJSON 文档 * RapidJSON 文档
* [English](http://miloyip.github.io/rapidjson/) * [English](http://rapidjson.org/)
* [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) * [简体中文](http://rapidjson.org/zh-cn/)
* [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI但不含API参考手册。 * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)可下载PDF/EPUB/MOBI但不含API参考手册。
## Build 状态 ## Build 状态

View File

@ -24,7 +24,7 @@ set(UNITTEST_SOURCES
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
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")
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 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") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
endif() endif()

View File

@ -19,6 +19,7 @@
#include "rapidjson/encodedstream.h" #include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include <sstream> #include <sstream>
#include <algorithm>
using namespace rapidjson; using namespace rapidjson;
@ -202,7 +203,8 @@ TEST(Document, Swap) {
o.SetObject().AddMember("a", 1, a); o.SetObject().AddMember("a", 1, a);
// Swap between Document and Value // Swap between Document and Value
d1.Swap(o); // d1.Swap(o); // doesn't compile
o.Swap(d1);
EXPECT_TRUE(d1.IsObject()); EXPECT_TRUE(d1.IsObject());
EXPECT_TRUE(o.IsArray()); EXPECT_TRUE(o.IsArray());
@ -212,8 +214,30 @@ TEST(Document, Swap) {
d1.Swap(d2); d1.Swap(d2);
EXPECT_TRUE(d1.IsArray()); EXPECT_TRUE(d1.IsArray());
EXPECT_TRUE(d2.IsObject()); 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. // This should be slow due to assignment in inner-loop.
struct OutputStringStream : public std::ostringstream { struct OutputStringStream : public std::ostringstream {
typedef char Ch; typedef char Ch;

View File

@ -272,6 +272,12 @@ TEST(Value, Swap) {
EXPECT_TRUE(v1.IsObject()); EXPECT_TRUE(v1.IsObject());
EXPECT_TRUE(v2.IsInt()); EXPECT_TRUE(v2.IsInt());
EXPECT_EQ(1234, v2.GetInt()); 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) { TEST(Value, Null) {

View File

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