Merge branch 'master' into schema
This commit is contained in:
commit
74f0673dad
@ -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()
|
||||
|
@ -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()));
|
||||
// ...
|
||||
}
|
||||
~~~~~~~~~~
|
||||
|
@ -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()));
|
||||
// ...
|
||||
}
|
||||
~~~~~~~~~~
|
||||
|
58
doc/faq.md
58
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?
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -320,7 +320,7 @@ std::stringstream ss(json);
|
||||
IStreamWrapper is(ss);
|
||||
|
||||
Document d;
|
||||
d.Parse(is);
|
||||
d.ParseStream(is);
|
||||
~~~~~~~~~~
|
||||
|
||||
但要注意,由于标准库的内部开销问,此实现的性能可能不如RapidJSON的内存/文件流。
|
||||
|
@ -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.
|
||||
}
|
||||
~~~~~~~~~~
|
||||
|
@ -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。它的析构是平凡的。
|
||||
}
|
||||
~~~~~~~~~~
|
||||
|
@ -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")
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
//!@{
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#include <intrin.h> // 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
else if (order <= -1074)
|
||||
return 0;
|
||||
else
|
||||
return order + 1074;
|
||||
return (unsigned)order + 1074;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
37
include/rapidjson/internal/swap.h
Normal file
37
include/rapidjson/internal/swap.h
Normal 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_
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
BIN
library.json
Normal file
Binary file not shown.
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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 状态
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user