no longer need to pass the size to rapidjson
This commit is contained in:
parent
bd8e0fd2a1
commit
32a26332f8
|
@ -1,29 +1,23 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ALLOCATORS_H_
|
#ifndef RAPIDJSON_ALLOCATORS_H_
|
||||||
#define RAPIDJSON_ALLOCATORS_H_
|
#define RAPIDJSON_ALLOCATORS_H_
|
||||||
|
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Allocator
|
// Allocator
|
||||||
|
@ -68,8 +62,20 @@ concept Allocator {
|
||||||
class CrtAllocator {
|
class CrtAllocator {
|
||||||
public:
|
public:
|
||||||
static const bool kNeedFree = true;
|
static const bool kNeedFree = true;
|
||||||
void* Malloc(size_t size) { return std::malloc(size); }
|
void* Malloc(size_t size) {
|
||||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
|
if (size) // behavior of malloc(0) is implementation defined.
|
||||||
|
return std::malloc(size);
|
||||||
|
else
|
||||||
|
return NULL; // standardize to returning NULL.
|
||||||
|
}
|
||||||
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||||
|
(void)originalSize;
|
||||||
|
if (newSize == 0) {
|
||||||
|
std::free(originalPtr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return std::realloc(originalPtr, newSize);
|
||||||
|
}
|
||||||
static void Free(void *ptr) { std::free(ptr); }
|
static void Free(void *ptr) { std::free(ptr); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,9 +110,6 @@ public:
|
||||||
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||||
{
|
{
|
||||||
if (!baseAllocator_)
|
|
||||||
ownBaseAllocator_ = baseAllocator_ = new BaseAllocator();
|
|
||||||
AddChunk(chunk_capacity_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Constructor with user-supplied buffer.
|
//! Constructor with user-supplied buffer.
|
||||||
|
@ -135,16 +138,18 @@ public:
|
||||||
*/
|
*/
|
||||||
~MemoryPoolAllocator() {
|
~MemoryPoolAllocator() {
|
||||||
Clear();
|
Clear();
|
||||||
delete ownBaseAllocator_;
|
RAPIDJSON_DELETE(ownBaseAllocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||||
void Clear() {
|
void Clear() {
|
||||||
while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
|
while (chunkHead_ && chunkHead_ != userBuffer_) {
|
||||||
ChunkHeader* next = chunkHead_->next;
|
ChunkHeader* next = chunkHead_->next;
|
||||||
baseAllocator_->Free(chunkHead_);
|
baseAllocator_->Free(chunkHead_);
|
||||||
chunkHead_ = next;
|
chunkHead_ = next;
|
||||||
}
|
}
|
||||||
|
if (chunkHead_ && chunkHead_ == userBuffer_)
|
||||||
|
chunkHead_->size = 0; // Clear user buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Computes the total capacity of allocated memory chunks.
|
//! Computes the total capacity of allocated memory chunks.
|
||||||
|
@ -169,11 +174,14 @@ public:
|
||||||
|
|
||||||
//! Allocates a memory block. (concept Allocator)
|
//! Allocates a memory block. (concept Allocator)
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size) {
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
size = RAPIDJSON_ALIGN(size);
|
size = RAPIDJSON_ALIGN(size);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -183,12 +191,15 @@ public:
|
||||||
if (originalPtr == 0)
|
if (originalPtr == 0)
|
||||||
return Malloc(newSize);
|
return Malloc(newSize);
|
||||||
|
|
||||||
|
if (newSize == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Do not shrink if new size is smaller than original
|
// Do not shrink if new size is smaller than original
|
||||||
if (originalSize >= newSize)
|
if (originalSize >= newSize)
|
||||||
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 == reinterpret_cast<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) {
|
||||||
|
@ -200,7 +211,9 @@ public:
|
||||||
// Realloc process: allocate and copy memory, do not free original buffer.
|
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||||
void* newBuffer = Malloc(newSize);
|
void* newBuffer = Malloc(newSize);
|
||||||
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
|
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
|
||||||
return std::memcpy(newBuffer, originalPtr, originalSize);
|
if (originalSize)
|
||||||
|
std::memcpy(newBuffer, originalPtr, originalSize);
|
||||||
|
return newBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Frees a memory block (concept Allocator)
|
//! Frees a memory block (concept Allocator)
|
||||||
|
@ -216,7 +229,9 @@ private:
|
||||||
/*! \param capacity Capacity of the chunk in bytes.
|
/*! \param capacity Capacity of the chunk in bytes.
|
||||||
*/
|
*/
|
||||||
void AddChunk(size_t capacity) {
|
void AddChunk(size_t capacity) {
|
||||||
ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
|
if (!baseAllocator_)
|
||||||
|
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
|
||||||
|
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_;
|
||||||
|
@ -241,6 +256,6 @@ private:
|
||||||
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
|
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_ENCODINGS_H_
|
#endif // RAPIDJSON_ENCODINGS_H_
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_DOCUMENT_H_
|
#ifndef RAPIDJSON_DOCUMENT_H_
|
||||||
#define RAPIDJSON_DOCUMENT_H_
|
#define RAPIDJSON_DOCUMENT_H_
|
||||||
|
@ -26,50 +20,41 @@
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "internal/meta.h"
|
#include "internal/meta.h"
|
||||||
#include "internal/strfunc.h"
|
#include "internal/strfunc.h"
|
||||||
#include "memorystream.h"
|
|
||||||
#include "encodedstream.h"
|
|
||||||
#include <new> // placement new
|
#include <new> // placement new
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||||
#elif defined(__GNUC__)
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RAPIDJSON_HAS_STDSTRING
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_HAS_STDSTRING
|
|
||||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
|
||||||
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
|
|
||||||
#else
|
|
||||||
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
|
|
||||||
#endif
|
|
||||||
/*! \def RAPIDJSON_HAS_STDSTRING
|
|
||||||
\ingroup RAPIDJSON_CONFIG
|
|
||||||
\brief Enable RapidJSON support for \c std::string
|
|
||||||
|
|
||||||
By defining this preprocessor symbol to \c 1, several convenience functions for using
|
|
||||||
\ref rapidjson::GenericValue with \c std::string are enabled, especially
|
|
||||||
for construction and comparison.
|
|
||||||
|
|
||||||
\hideinitializer
|
|
||||||
*/
|
|
||||||
#include <string>
|
|
||||||
#endif // RAPIDJSON_HAS_STDSTRING
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
|
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
|
||||||
#include <iterator> // std::iterator, std::random_access_iterator_tag
|
#include <iterator> // std::iterator, std::random_access_iterator_tag
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
#include <utility> // std::move
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// Forward declaration.
|
// Forward declaration.
|
||||||
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.
|
||||||
|
@ -258,6 +243,7 @@ struct GenericStringRef {
|
||||||
typedef CharType Ch; //!< character type of the string
|
typedef CharType Ch; //!< character type of the string
|
||||||
|
|
||||||
//! Create string reference from \c const character array
|
//! Create string reference from \c const character array
|
||||||
|
#ifndef __clang__ // -Wdocumentation
|
||||||
/*!
|
/*!
|
||||||
This constructor implicitly creates a constant string reference from
|
This constructor implicitly creates a constant string reference from
|
||||||
a \c const character array. It has better performance than
|
a \c const character array. It has better performance than
|
||||||
|
@ -280,11 +266,13 @@ struct GenericStringRef {
|
||||||
In such cases, the referenced string should be \b copied to the
|
In such cases, the referenced string should be \b copied to the
|
||||||
GenericValue instead.
|
GenericValue instead.
|
||||||
*/
|
*/
|
||||||
|
#endif
|
||||||
template<SizeType N>
|
template<SizeType N>
|
||||||
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
|
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
|
||||||
: s(str), length(N-1) {}
|
: s(str), length(N-1) {}
|
||||||
|
|
||||||
//! Explicitly create string reference from \c const character pointer
|
//! Explicitly create string reference from \c const character pointer
|
||||||
|
#ifndef __clang__ // -Wdocumentation
|
||||||
/*!
|
/*!
|
||||||
This constructor can be used to \b explicitly create a reference to
|
This constructor can be used to \b explicitly create a reference to
|
||||||
a constant string pointer.
|
a constant string pointer.
|
||||||
|
@ -303,16 +291,19 @@ struct GenericStringRef {
|
||||||
In such cases, the referenced string should be \b copied to the
|
In such cases, the referenced string should be \b copied to the
|
||||||
GenericValue instead.
|
GenericValue instead.
|
||||||
*/
|
*/
|
||||||
|
#endif
|
||||||
explicit GenericStringRef(const CharType* str)
|
explicit GenericStringRef(const CharType* str)
|
||||||
: s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
|
: s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
|
||||||
|
|
||||||
//! Create constant string reference from pointer and length
|
//! Create constant string reference from pointer and length
|
||||||
|
#ifndef __clang__ // -Wdocumentation
|
||||||
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
|
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
|
||||||
\param len length of the string, excluding the trailing NULL terminator
|
\param len length of the string, excluding the trailing NULL terminator
|
||||||
|
|
||||||
\post \ref s == str && \ref length == len
|
\post \ref s == str && \ref length == len
|
||||||
\note Constant complexity.
|
\note Constant complexity.
|
||||||
*/
|
*/
|
||||||
|
#endif
|
||||||
GenericStringRef(const CharType* str, SizeType len)
|
GenericStringRef(const CharType* str, SizeType len)
|
||||||
: s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
|
: s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
|
||||||
|
|
||||||
|
@ -428,6 +419,7 @@ public:
|
||||||
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
|
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
|
||||||
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
||||||
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
|
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
|
||||||
|
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
|
||||||
|
|
||||||
//!@name Constructors and destructor.
|
//!@name Constructors and destructor.
|
||||||
//@{
|
//@{
|
||||||
|
@ -446,6 +438,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.
|
||||||
|
@ -453,13 +455,17 @@ public:
|
||||||
\param type Type of the value.
|
\param type Type of the value.
|
||||||
\note Default content for number is zero.
|
\note Default content for number is zero.
|
||||||
*/
|
*/
|
||||||
GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
|
explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
|
||||||
static const unsigned defaultFlags[7] = {
|
static const unsigned defaultFlags[7] = {
|
||||||
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
|
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
|
||||||
kNumberAnyFlag
|
kNumberAnyFlag
|
||||||
};
|
};
|
||||||
RAPIDJSON_ASSERT(type <= kNumberType);
|
RAPIDJSON_ASSERT(type <= kNumberType);
|
||||||
flags_ = defaultFlags[type];
|
flags_ = defaultFlags[type];
|
||||||
|
|
||||||
|
// Use ShortString to store empty string.
|
||||||
|
if (type == kStringType)
|
||||||
|
data_.ss.SetLength(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Explicit copy constructor (with allocator)
|
//! Explicit copy constructor (with allocator)
|
||||||
|
@ -637,7 +643,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
|
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
|
||||||
RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
|
RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
|
||||||
this->~GenericValue();
|
this->~GenericValue();
|
||||||
new (this) GenericValue(rhs, allocator);
|
new (this) GenericValue(rhs, allocator);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -656,6 +662,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; }
|
||||||
|
@ -697,12 +717,15 @@ public:
|
||||||
return StringEqual(rhs);
|
return StringEqual(rhs);
|
||||||
|
|
||||||
case kNumberType:
|
case kNumberType:
|
||||||
if (IsDouble() || rhs.IsDouble())
|
if (IsDouble() || rhs.IsDouble()) {
|
||||||
return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
|
double a = GetDouble(); // May convert from integer to double.
|
||||||
|
double b = rhs.GetDouble(); // Ditto
|
||||||
|
return a >= b && a <= b; // Prevent -Wfloat-equal
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return data_.n.u64 == rhs.data_.n.u64;
|
return data_.n.u64 == rhs.data_.n.u64;
|
||||||
|
|
||||||
default: // kTrueType, kFalseType, kNullType
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,22 +820,32 @@ public:
|
||||||
//! Check whether the object is empty.
|
//! Check whether the object is empty.
|
||||||
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
|
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
|
||||||
|
|
||||||
//! Get the value associated with the name.
|
//! Get a value from an object associated with the name.
|
||||||
/*!
|
/*! \pre IsObject() == true
|
||||||
|
\tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
|
||||||
\note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
|
\note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
|
||||||
Since 0.2, if the name is not correct, it will assert.
|
Since 0.2, if the name is not correct, it will assert.
|
||||||
If user is unsure whether a member exists, user should use HasMember() first.
|
If user is unsure whether a member exists, user should use HasMember() first.
|
||||||
A better approach is to use FindMember().
|
A better approach is to use FindMember().
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
GenericValue& operator[](const Ch* name) {
|
template <typename T>
|
||||||
|
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
|
||||||
GenericValue n(StringRef(name));
|
GenericValue n(StringRef(name));
|
||||||
return (*this)[n];
|
return (*this)[n];
|
||||||
}
|
}
|
||||||
const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
template <typename T>
|
||||||
|
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||||
|
|
||||||
// This version is faster because it does not need a StrLen().
|
//! Get a value from an object associated with the name.
|
||||||
// It can also handle string with null character.
|
/*! \pre IsObject() == true
|
||||||
|
\tparam SourceAllocator Allocator of the \c name value
|
||||||
|
|
||||||
|
\note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
|
||||||
|
And it can also handle strings with embedded null characters.
|
||||||
|
|
||||||
|
\note Linear time complexity.
|
||||||
|
*/
|
||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
|
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
MemberIterator member = FindMember(name);
|
MemberIterator member = FindMember(name);
|
||||||
|
@ -820,13 +853,25 @@ public:
|
||||||
return member->value;
|
return member->value;
|
||||||
else {
|
else {
|
||||||
RAPIDJSON_ASSERT(false); // see above note
|
RAPIDJSON_ASSERT(false); // see above note
|
||||||
static GenericValue NullValue;
|
|
||||||
return NullValue;
|
// This will generate -Wexit-time-destructors in clang
|
||||||
|
// static GenericValue NullValue;
|
||||||
|
// return NullValue;
|
||||||
|
|
||||||
|
// Use static buffer and placement-new to prevent destruction
|
||||||
|
static char buffer[sizeof(GenericValue)];
|
||||||
|
return *new (buffer) GenericValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
|
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
//! Get a value from an object associated with name (string object).
|
||||||
|
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
|
||||||
|
const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! Const member iterator
|
//! Const member iterator
|
||||||
/*! \pre IsObject() == true */
|
/*! \pre IsObject() == true */
|
||||||
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
|
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
|
||||||
|
@ -850,6 +895,18 @@ public:
|
||||||
*/
|
*/
|
||||||
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
|
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
//! Check whether a member exists in the object with string object.
|
||||||
|
/*!
|
||||||
|
\param name Member name to be searched.
|
||||||
|
\pre IsObject() == true
|
||||||
|
\return Whether a member with that name exists.
|
||||||
|
\note It is better to use FindMember() directly if you need the obtain the value as well.
|
||||||
|
\note Linear time complexity.
|
||||||
|
*/
|
||||||
|
bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! Check whether a member exists in the object with GenericValue name.
|
//! Check whether a member exists in the object with GenericValue name.
|
||||||
/*!
|
/*!
|
||||||
This version is faster because it does not need a StrLen(). It can also handle string with null character.
|
This version is faster because it does not need a StrLen(). It can also handle string with null character.
|
||||||
|
@ -906,6 +963,18 @@ public:
|
||||||
}
|
}
|
||||||
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
//! Find member by string object name.
|
||||||
|
/*!
|
||||||
|
\param name Member name to be searched.
|
||||||
|
\pre IsObject() == true
|
||||||
|
\return Iterator to member, if it exists.
|
||||||
|
Otherwise returns \ref MemberEnd().
|
||||||
|
*/
|
||||||
|
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
|
||||||
|
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! Add a member (name-value pair) to the object.
|
//! Add a member (name-value pair) to the object.
|
||||||
/*! \param name A string value as name of member.
|
/*! \param name A string value as name of member.
|
||||||
\param value Value of any type.
|
\param value Value of any type.
|
||||||
|
@ -938,6 +1007,60 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Add a constant string value as member (name-value pair) to the object.
|
||||||
|
/*! \param name A string value as name of member.
|
||||||
|
\param value constant string reference as value of member.
|
||||||
|
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
|
||||||
|
\return The value itself for fluent API.
|
||||||
|
\pre IsObject()
|
||||||
|
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
|
||||||
|
\note Amortized Constant time complexity.
|
||||||
|
*/
|
||||||
|
GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
|
||||||
|
GenericValue v(value);
|
||||||
|
return AddMember(name, v, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
//! Add a string object as member (name-value pair) to the object.
|
||||||
|
/*! \param name A string value as name of member.
|
||||||
|
\param value constant string reference as value of member.
|
||||||
|
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
|
||||||
|
\return The value itself for fluent API.
|
||||||
|
\pre IsObject()
|
||||||
|
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
|
||||||
|
\note Amortized Constant time complexity.
|
||||||
|
*/
|
||||||
|
GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
|
||||||
|
GenericValue v(value, allocator);
|
||||||
|
return AddMember(name, v, allocator);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Add any primitive value as member (name-value pair) to the object.
|
||||||
|
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
|
||||||
|
\param name A string value as name of member.
|
||||||
|
\param value Value of primitive type \c T as value of member
|
||||||
|
\param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
|
||||||
|
\return The value itself for fluent API.
|
||||||
|
\pre IsObject()
|
||||||
|
|
||||||
|
\note The source type \c T explicitly disallows all pointer types,
|
||||||
|
especially (\c const) \ref Ch*. This helps avoiding implicitly
|
||||||
|
referencing character strings with insufficient lifetime, use
|
||||||
|
\ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
|
||||||
|
AddMember(StringRefType, StringRefType, Allocator&).
|
||||||
|
All other pointer types would implicitly convert to \c bool,
|
||||||
|
use an explicit cast instead, if needed.
|
||||||
|
\note Amortized Constant time complexity.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
||||||
|
AddMember(GenericValue& name, T value, Allocator& allocator) {
|
||||||
|
GenericValue v(value);
|
||||||
|
return AddMember(name, v, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
|
GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
|
||||||
return AddMember(name, value, allocator);
|
return AddMember(name, value, allocator);
|
||||||
|
@ -1005,8 +1128,7 @@ public:
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
||||||
AddMember(StringRefType name, T value, Allocator& allocator) {
|
AddMember(StringRefType name, T value, Allocator& allocator) {
|
||||||
GenericValue n(name);
|
GenericValue n(name);
|
||||||
GenericValue v(value);
|
return AddMember(n, value, allocator);
|
||||||
return AddMember(n, v, allocator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Remove all members in the object.
|
//! Remove all members in the object.
|
||||||
|
@ -1023,7 +1145,9 @@ public:
|
||||||
//! Remove a member in object by its name.
|
//! Remove a member in object by its name.
|
||||||
/*! \param name Name of member to be removed.
|
/*! \param name Name of member to be removed.
|
||||||
\return Whether the member existed.
|
\return Whether the member existed.
|
||||||
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
\note This function may reorder the object members. Use \ref
|
||||||
|
EraseMember(ConstMemberIterator) if you need to preserve the
|
||||||
|
relative order of the remaining members.
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
bool RemoveMember(const Ch* name) {
|
bool RemoveMember(const Ch* name) {
|
||||||
|
@ -1031,6 +1155,10 @@ public:
|
||||||
return RemoveMember(n);
|
return RemoveMember(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
MemberIterator m = FindMember(name);
|
MemberIterator m = FindMember(name);
|
||||||
|
@ -1045,8 +1173,9 @@ public:
|
||||||
//! Remove a member in object by iterator.
|
//! Remove a member in object by iterator.
|
||||||
/*! \param m member iterator (obtained by FindMember() or MemberBegin()).
|
/*! \param m member iterator (obtained by FindMember() or MemberBegin()).
|
||||||
\return the new iterator after removal.
|
\return the new iterator after removal.
|
||||||
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
\note This function may reorder the object members. Use \ref
|
||||||
\note Use \ref EraseMember(ConstMemberIterator) instead, if you need to rely on a stable member ordering.
|
EraseMember(ConstMemberIterator) if you need to preserve the
|
||||||
|
relative order of the remaining members.
|
||||||
\note Constant time complexity.
|
\note Constant time complexity.
|
||||||
*/
|
*/
|
||||||
MemberIterator RemoveMember(MemberIterator m) {
|
MemberIterator RemoveMember(MemberIterator m) {
|
||||||
|
@ -1073,7 +1202,8 @@ public:
|
||||||
\pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
|
\pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
|
||||||
\return Iterator following the removed element.
|
\return Iterator following the removed element.
|
||||||
If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
|
If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
|
||||||
\note Other than \ref RemoveMember(MemberIterator), this function preserves the ordering of the members.
|
\note This function preserves the relative order of the remaining object
|
||||||
|
members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
MemberIterator EraseMember(ConstMemberIterator pos) {
|
MemberIterator EraseMember(ConstMemberIterator pos) {
|
||||||
|
@ -1085,7 +1215,8 @@ public:
|
||||||
\param last iterator following the last member to remove
|
\param last iterator following the last member to remove
|
||||||
\pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
|
\pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
|
||||||
\return Iterator following the last removed element.
|
\return Iterator following the last removed element.
|
||||||
\note Other than \ref RemoveMember(MemberIterator), this function preserves the ordering of the members.
|
\note This function preserves the relative order of the remaining object
|
||||||
|
members.
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
|
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
|
||||||
|
@ -1099,11 +1230,36 @@ public:
|
||||||
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
||||||
for (MemberIterator itr = pos; itr != last; ++itr)
|
for (MemberIterator itr = pos; itr != last; ++itr)
|
||||||
itr->~Member();
|
itr->~Member();
|
||||||
std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
|
std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
||||||
data_.o.size -= (last - first);
|
data_.o.size -= static_cast<SizeType>(last - first);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Erase a member in object by its name.
|
||||||
|
/*! \param name Name of member to be removed.
|
||||||
|
\return Whether the member existed.
|
||||||
|
\note Linear time complexity.
|
||||||
|
*/
|
||||||
|
bool EraseMember(const Ch* name) {
|
||||||
|
GenericValue n(StringRef(name));
|
||||||
|
return EraseMember(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename SourceAllocator>
|
||||||
|
bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
|
MemberIterator m = FindMember(name);
|
||||||
|
if (m != MemberEnd()) {
|
||||||
|
EraseMember(m);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
//!@name Array
|
//!@name Array
|
||||||
|
@ -1134,14 +1290,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Get an element from array by index.
|
//! Get an element from array by index.
|
||||||
/*! \param index Zero-based index of element.
|
/*! \pre IsArray() == true
|
||||||
\code
|
\param index Zero-based index of element.
|
||||||
Value a(kArrayType);
|
\see operator[](T*)
|
||||||
a.PushBack(123);
|
|
||||||
int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
|
|
||||||
int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work.
|
|
||||||
int z = a[0u].GetInt(); // This works too.
|
|
||||||
\endcode
|
|
||||||
*/
|
*/
|
||||||
GenericValue& operator[](SizeType index) {
|
GenericValue& operator[](SizeType index) {
|
||||||
RAPIDJSON_ASSERT(IsArray());
|
RAPIDJSON_ASSERT(IsArray());
|
||||||
|
@ -1172,7 +1323,7 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
|
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
|
||||||
RAPIDJSON_ASSERT(IsArray());
|
RAPIDJSON_ASSERT(IsArray());
|
||||||
if (newCapacity > data_.a.capacity) {
|
if (newCapacity > data_.a.capacity) {
|
||||||
data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
|
data_.a.elements = static_cast<GenericValue*>(allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)));
|
||||||
data_.a.capacity = newCapacity;
|
data_.a.capacity = newCapacity;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -1279,8 +1430,8 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
ValueIterator pos = Begin() + (first - Begin());
|
ValueIterator pos = Begin() + (first - Begin());
|
||||||
for (ValueIterator itr = pos; itr != last; ++itr)
|
for (ValueIterator itr = pos; itr != last; ++itr)
|
||||||
itr->~GenericValue();
|
itr->~GenericValue();
|
||||||
std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
|
std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
||||||
data_.a.size -= (last - first);
|
data_.a.size -= static_cast<SizeType>(last - first);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1299,8 +1450,8 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
|
if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
|
||||||
if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
|
if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
|
||||||
if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
|
if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
|
||||||
if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
|
if ((flags_ & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
|
||||||
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
|
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
|
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
|
||||||
|
@ -1364,7 +1515,7 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
|
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
|
||||||
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
|
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
|
||||||
*/
|
*/
|
||||||
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
|
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
@ -1387,6 +1538,7 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
if (!handler.StartObject())
|
if (!handler.StartObject())
|
||||||
return false;
|
return false;
|
||||||
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
|
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
|
||||||
|
RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
|
||||||
if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
|
if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
|
||||||
return false;
|
return false;
|
||||||
if (!m->value.Accept(handler))
|
if (!m->value.Accept(handler))
|
||||||
|
@ -1405,17 +1557,14 @@ int z = a[0u].GetInt(); // This works too.
|
||||||
case kStringType:
|
case kStringType:
|
||||||
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
|
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
|
||||||
|
|
||||||
case kNumberType:
|
default:
|
||||||
|
RAPIDJSON_ASSERT(GetType() == kNumberType);
|
||||||
if (IsInt()) return handler.Int(data_.n.i.i);
|
if (IsInt()) return handler.Int(data_.n.i.i);
|
||||||
else if (IsUint()) return handler.Uint(data_.n.u.u);
|
else if (IsUint()) return handler.Uint(data_.n.u.u);
|
||||||
else if (IsInt64()) return handler.Int64(data_.n.i64);
|
else if (IsInt64()) return handler.Int64(data_.n.i64);
|
||||||
else if (IsUint64()) return handler.Uint64(data_.n.u64);
|
else if (IsUint64()) return handler.Uint64(data_.n.u64);
|
||||||
else return handler.Double(data_.n.d);
|
else return handler.Double(data_.n.d);
|
||||||
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1474,9 +1623,9 @@ private:
|
||||||
enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
|
enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
|
||||||
Ch str[MaxChars];
|
Ch str[MaxChars];
|
||||||
|
|
||||||
inline static bool Usable(SizeType len) { return (MaxSize >= len); }
|
inline static bool Usable(SizeType len) { return (MaxSize >= len); }
|
||||||
inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
|
inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
|
||||||
inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
|
inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
|
||||||
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
||||||
|
|
||||||
// By using proper binary layout, retrieval of different integer types do not need conversions.
|
// By using proper binary layout, retrieval of different integer types do not need conversions.
|
||||||
|
@ -1528,16 +1677,24 @@ private:
|
||||||
// Initialize this value as array with initial data, without calling destructor.
|
// Initialize this value as array with initial data, without calling destructor.
|
||||||
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
||||||
flags_ = kArrayFlag;
|
flags_ = kArrayFlag;
|
||||||
data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
|
if (count) {
|
||||||
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
data_.a.elements = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
|
||||||
|
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data_.a.elements = NULL;
|
||||||
data_.a.size = data_.a.capacity = count;
|
data_.a.size = data_.a.capacity = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Initialize this value as object with initial data, without calling destructor.
|
//! Initialize this value as object with initial data, without calling destructor.
|
||||||
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
|
||||||
flags_ = kObjectFlag;
|
flags_ = kObjectFlag;
|
||||||
data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
|
if (count) {
|
||||||
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
data_.o.members = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
||||||
|
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data_.o.members = NULL;
|
||||||
data_.o.size = data_.o.capacity = count;
|
data_.o.size = data_.o.capacity = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1558,7 +1715,7 @@ private:
|
||||||
} else {
|
} else {
|
||||||
flags_ = kCopyStringFlag;
|
flags_ = kCopyStringFlag;
|
||||||
data_.s.length = s.length;
|
data_.s.length = s.length;
|
||||||
str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
|
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
|
||||||
data_.s.str = str;
|
data_.s.str = str;
|
||||||
}
|
}
|
||||||
std::memcpy(str, s, s.length * sizeof(Ch));
|
std::memcpy(str, s, s.length * sizeof(Ch));
|
||||||
|
@ -1614,7 +1771,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.
|
||||||
*/
|
*/
|
||||||
|
@ -1622,12 +1794,80 @@ public:
|
||||||
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
|
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
|
||||||
{
|
{
|
||||||
if (!allocator_)
|
if (!allocator_)
|
||||||
ownAllocator_ = allocator_ = new Allocator();
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||||
}
|
}
|
||||||
|
|
||||||
~GenericDocument() {
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
delete ownAllocator_;
|
//! Move constructor in C++11
|
||||||
|
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
|
||||||
|
: ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
|
||||||
|
allocator_(rhs.allocator_),
|
||||||
|
ownAllocator_(rhs.ownAllocator_),
|
||||||
|
stack_(std::move(rhs.stack_)),
|
||||||
|
parseResult_(rhs.parseResult_)
|
||||||
|
{
|
||||||
|
rhs.allocator_ = 0;
|
||||||
|
rhs.ownAllocator_ = 0;
|
||||||
|
rhs.parseResult_ = ParseResult();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
~GenericDocument() {
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
//! Move assignment in C++11
|
||||||
|
GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
|
// The cast to ValueType is necessary here, because otherwise it would
|
||||||
|
// attempt to call GenericValue's templated assignment operator.
|
||||||
|
ValueType::operator=(std::forward<ValueType>(rhs));
|
||||||
|
|
||||||
|
// Calling the destructor here would prematurely call stack_'s destructor
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
allocator_ = rhs.allocator_;
|
||||||
|
ownAllocator_ = rhs.ownAllocator_;
|
||||||
|
stack_ = std::move(rhs.stack_);
|
||||||
|
parseResult_ = rhs.parseResult_;
|
||||||
|
|
||||||
|
rhs.allocator_ = 0;
|
||||||
|
rhs.ownAllocator_ = 0;
|
||||||
|
rhs.parseResult_ = ParseResult();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Exchange the contents of this document with those of another.
|
||||||
|
/*!
|
||||||
|
\param rhs 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
|
||||||
//!@{
|
//!@{
|
||||||
|
@ -1641,13 +1881,13 @@ public:
|
||||||
*/
|
*/
|
||||||
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
|
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
|
||||||
GenericDocument& ParseStream(InputStream& is) {
|
GenericDocument& ParseStream(InputStream& is) {
|
||||||
ValueType::SetNull(); // Remove existing root if exist
|
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
|
||||||
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
|
stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
|
||||||
ClearStackOnExit scope(*this);
|
ClearStackOnExit scope(*this);
|
||||||
parseResult_ = reader.template Parse<parseFlags>(is, *this);
|
parseResult_ = reader.template Parse<parseFlags>(is, *this);
|
||||||
if (parseResult_) {
|
if (parseResult_) {
|
||||||
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
|
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
|
||||||
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
|
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1660,7 +1900,7 @@ public:
|
||||||
*/
|
*/
|
||||||
template <unsigned parseFlags, typename InputStream>
|
template <unsigned parseFlags, typename InputStream>
|
||||||
GenericDocument& ParseStream(InputStream& is) {
|
GenericDocument& ParseStream(InputStream& is) {
|
||||||
return ParseStream<parseFlags,Encoding,InputStream>(is);
|
return ParseStream<parseFlags, Encoding, InputStream>(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
|
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
|
||||||
|
@ -1677,18 +1917,6 @@ public:
|
||||||
//!@name Parse in-place from mutable string
|
//!@name Parse in-place from mutable string
|
||||||
//!@{
|
//!@{
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string (with Encoding conversion)
|
|
||||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
|
||||||
\tparam SourceEncoding Transcoding from input Encoding
|
|
||||||
\param str Mutable zero-terminated string to be parsed.
|
|
||||||
\return The document itself for fluent API.
|
|
||||||
*/
|
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
|
||||||
GenericInsituStringStream<Encoding> s(str);
|
|
||||||
return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string
|
//! Parse JSON text from a mutable string
|
||||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||||
\param str Mutable zero-terminated string to be parsed.
|
\param str Mutable zero-terminated string to be parsed.
|
||||||
|
@ -1696,7 +1924,8 @@ public:
|
||||||
*/
|
*/
|
||||||
template <unsigned parseFlags>
|
template <unsigned parseFlags>
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
GenericDocument& ParseInsitu(Ch* str) {
|
||||||
return ParseInsitu<parseFlags, Encoding>(str);
|
GenericInsituStringStream<Encoding> s(str);
|
||||||
|
return ParseStream<parseFlags | kParseInsituFlag>(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
|
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
|
||||||
|
@ -1704,7 +1933,7 @@ public:
|
||||||
\return The document itself for fluent API.
|
\return The document itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericDocument& ParseInsitu(Ch* str) {
|
GenericDocument& ParseInsitu(Ch* str) {
|
||||||
return ParseInsitu<kParseDefaultFlags, Encoding>(str);
|
return ParseInsitu<kParseDefaultFlags>(str);
|
||||||
}
|
}
|
||||||
//!@}
|
//!@}
|
||||||
|
|
||||||
|
@ -1717,7 +1946,7 @@ public:
|
||||||
\param str Read-only zero-terminated string to be parsed.
|
\param str Read-only zero-terminated string to be parsed.
|
||||||
*/
|
*/
|
||||||
template <unsigned parseFlags, typename SourceEncoding>
|
template <unsigned parseFlags, typename SourceEncoding>
|
||||||
GenericDocument& Parse(const Ch* str) {
|
GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
|
||||||
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
|
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
|
||||||
GenericStringStream<SourceEncoding> s(str);
|
GenericStringStream<SourceEncoding> s(str);
|
||||||
return ParseStream<parseFlags, SourceEncoding>(s);
|
return ParseStream<parseFlags, SourceEncoding>(s);
|
||||||
|
@ -1738,16 +1967,6 @@ public:
|
||||||
GenericDocument& Parse(const Ch* str) {
|
GenericDocument& Parse(const Ch* str) {
|
||||||
return Parse<kParseDefaultFlags>(str);
|
return Parse<kParseDefaultFlags>(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericDocument& Parse(const Ch * str, size_t sz) {
|
|
||||||
const char* buf = (const char*) str;
|
|
||||||
size_t bufsz = sz * sizeof(Ch);
|
|
||||||
MemoryStream ms(buf, bufsz);
|
|
||||||
EncodedInputStream<Encoding, MemoryStream> is(ms);
|
|
||||||
ParseStream(is);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//!@}
|
//!@}
|
||||||
|
|
||||||
//!@name Handling parse errors
|
//!@name Handling parse errors
|
||||||
|
@ -1762,10 +1981,26 @@ public:
|
||||||
//! Get the position of last parsing error in input, 0 otherwise.
|
//! Get the position of last parsing error in input, 0 otherwise.
|
||||||
size_t GetErrorOffset() const { return parseResult_.Offset(); }
|
size_t GetErrorOffset() const { return parseResult_.Offset(); }
|
||||||
|
|
||||||
|
//! Implicit conversion to get the last parse result
|
||||||
|
#ifndef __clang // -Wdocumentation
|
||||||
|
/*! \return \ref ParseResult of the last parse operation
|
||||||
|
|
||||||
|
\code
|
||||||
|
Document doc;
|
||||||
|
ParseResult ok = doc.Parse(json);
|
||||||
|
if (!ok)
|
||||||
|
printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
operator ParseResult() const { return parseResult_; }
|
||||||
//!@}
|
//!@}
|
||||||
|
|
||||||
//! Get the allocator of this document.
|
//! Get the allocator of this document.
|
||||||
Allocator& GetAllocator() { return *allocator_; }
|
Allocator& GetAllocator() {
|
||||||
|
RAPIDJSON_ASSERT(allocator_);
|
||||||
|
return *allocator_;
|
||||||
|
}
|
||||||
|
|
||||||
//! Get the capacity of stack in bytes.
|
//! Get the capacity of stack in bytes.
|
||||||
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
|
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
|
||||||
|
@ -1808,7 +2043,7 @@ private:
|
||||||
|
|
||||||
bool EndObject(SizeType memberCount) {
|
bool EndObject(SizeType memberCount) {
|
||||||
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
|
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
|
||||||
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
|
stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1821,6 +2056,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//! Prohibit copying
|
||||||
|
GenericDocument(const GenericDocument&);
|
||||||
//! Prohibit assignment
|
//! Prohibit assignment
|
||||||
GenericDocument& operator=(const GenericDocument&);
|
GenericDocument& operator=(const GenericDocument&);
|
||||||
|
|
||||||
|
@ -1833,6 +2070,10 @@ private:
|
||||||
stack_.ShrinkToFit();
|
stack_.ShrinkToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Destroy() {
|
||||||
|
RAPIDJSON_DELETE(ownAllocator_);
|
||||||
|
}
|
||||||
|
|
||||||
static const size_t kDefaultStackCapacity = 1024;
|
static const size_t kDefaultStackCapacity = 1024;
|
||||||
Allocator* allocator_;
|
Allocator* allocator_;
|
||||||
Allocator* ownAllocator_;
|
Allocator* ownAllocator_;
|
||||||
|
@ -1849,14 +2090,40 @@ template <typename SourceAllocator>
|
||||||
inline
|
inline
|
||||||
GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
|
GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
|
||||||
{
|
{
|
||||||
GenericDocument<Encoding,Allocator> d(&allocator);
|
switch (rhs.GetType()) {
|
||||||
rhs.Accept(d);
|
case kObjectType:
|
||||||
RawAssign(*d.stack_.template Pop<GenericValue>(1));
|
case kArrayType: { // perform deep copy via SAX Handler
|
||||||
|
GenericDocument<Encoding,Allocator> d(&allocator);
|
||||||
|
rhs.Accept(d);
|
||||||
|
RawAssign(*d.stack_.template Pop<GenericValue>(1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kStringType:
|
||||||
|
if (rhs.flags_ == kConstStringFlag) {
|
||||||
|
flags_ = rhs.flags_;
|
||||||
|
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
|
||||||
|
} else {
|
||||||
|
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
flags_ = rhs.flags_;
|
||||||
|
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
#ifdef _MSC_VER
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
|
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
|
||||||
#define RAPIDJSON_ENCODEDSTREAM_H_
|
#define RAPIDJSON_ENCODEDSTREAM_H_
|
||||||
|
@ -28,7 +22,12 @@ RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Input byte stream wrapper with a statically bound encoding.
|
//! Input byte stream wrapper with a statically bound encoding.
|
||||||
/*!
|
/*!
|
||||||
|
@ -66,7 +65,7 @@ private:
|
||||||
//! Output byte stream wrapper with statically bound encoding.
|
//! Output byte stream wrapper with statically bound encoding.
|
||||||
/*!
|
/*!
|
||||||
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
||||||
\tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
|
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename OutputByteStream>
|
template <typename Encoding, typename OutputByteStream>
|
||||||
class EncodedOutputStream {
|
class EncodedOutputStream {
|
||||||
|
@ -83,8 +82,8 @@ public:
|
||||||
void Flush() { os_.Flush(); }
|
void Flush() { os_.Flush(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const { RAPIDJSON_ASSERT(false); }
|
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
Ch Take() { RAPIDJSON_ASSERT(false); }
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
|
@ -115,6 +114,7 @@ public:
|
||||||
\param type UTF encoding type if it is not detected from the stream.
|
\param type UTF encoding type if it is not detected from the stream.
|
||||||
*/
|
*/
|
||||||
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
||||||
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
DetectType();
|
DetectType();
|
||||||
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||||
takeFunc_ = f[type_];
|
takeFunc_ = f[type_];
|
||||||
|
@ -147,11 +147,11 @@ private:
|
||||||
// FF FE UTF-16LE
|
// FF FE UTF-16LE
|
||||||
// EF BB BF UTF-8
|
// EF BB BF UTF-8
|
||||||
|
|
||||||
const unsigned char* c = (const unsigned char *)is_->Peek4();
|
const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
|
||||||
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(); }
|
||||||
|
@ -183,21 +183,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||||
switch (type_) {
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
case kUTF8:
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
// Do nothing
|
|
||||||
break;
|
|
||||||
case kUTF16LE:
|
|
||||||
case kUTF16BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
|
||||||
break;
|
|
||||||
case kUTF32LE:
|
|
||||||
case kUTF32BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false); // Invalid type
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Ch (*TakeFunc)(InputByteStream& is);
|
typedef Ch (*TakeFunc)(InputByteStream& is);
|
||||||
|
@ -211,7 +198,7 @@ private:
|
||||||
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
|
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
|
||||||
/*!
|
/*!
|
||||||
\tparam CharType Type of character for writing.
|
\tparam CharType Type of character for writing.
|
||||||
\tparam InputByteStream type of output byte stream to be wrapped.
|
\tparam OutputByteStream type of output byte stream to be wrapped.
|
||||||
*/
|
*/
|
||||||
template <typename CharType, typename OutputByteStream>
|
template <typename CharType, typename OutputByteStream>
|
||||||
class AutoUTFOutputStream {
|
class AutoUTFOutputStream {
|
||||||
|
@ -226,22 +213,11 @@ public:
|
||||||
\param putBOM Whether to write BOM at the beginning of the stream.
|
\param putBOM Whether to write BOM at the beginning of the stream.
|
||||||
*/
|
*/
|
||||||
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
||||||
// RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
switch (type_) {
|
|
||||||
case kUTF16LE:
|
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||||
case kUTF16BE:
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
break;
|
|
||||||
case kUTF32LE:
|
|
||||||
case kUTF32BE:
|
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
|
||||||
break;
|
|
||||||
case kUTF8:
|
|
||||||
// Do nothing
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false); // Invalid UTFType
|
|
||||||
}
|
|
||||||
|
|
||||||
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||||
putFunc_ = f[type_];
|
putFunc_ = f[type_];
|
||||||
|
@ -256,8 +232,8 @@ public:
|
||||||
void Flush() { os_->Flush(); }
|
void Flush() { os_->Flush(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const { RAPIDJSON_ASSERT(false); }
|
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
Ch Take() { RAPIDJSON_ASSERT(false); }
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
|
@ -281,7 +257,11 @@ private:
|
||||||
|
|
||||||
#undef RAPIDJSON_ENCODINGS_FUNC
|
#undef RAPIDJSON_ENCODINGS_FUNC
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ENCODINGS_H_
|
#ifndef RAPIDJSON_ENCODINGS_H_
|
||||||
#define RAPIDJSON_ENCODINGS_H_
|
#define RAPIDJSON_ENCODINGS_H_
|
||||||
|
@ -30,9 +24,10 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
RAPIDJSON_DIAG_OFF(overflow)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Encoding
|
// Encoding
|
||||||
|
@ -127,17 +122,17 @@ struct UTF8 {
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
|
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||||
#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
|
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define TAIL() COPY(); TRANS(0x70)
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
Ch c = is.Take();
|
typename InputStream::Ch c = is.Take();
|
||||||
if (!(c & 0x80)) {
|
if (!(c & 0x80)) {
|
||||||
*codepoint = (unsigned char)c;
|
*codepoint = static_cast<unsigned char>(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char type = GetRange((unsigned char)c);
|
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
||||||
*codepoint = (0xFF >> type) & (unsigned char)c;
|
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 2: TAIL(); return result;
|
case 2: TAIL(); return result;
|
||||||
|
@ -157,7 +152,7 @@ struct UTF8 {
|
||||||
template <typename InputStream, typename OutputStream>
|
template <typename InputStream, typename OutputStream>
|
||||||
static bool Validate(InputStream& is, OutputStream& os) {
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
#define COPY() os.Put(c = is.Take())
|
#define COPY() os.Put(c = is.Take())
|
||||||
#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
|
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define TAIL() COPY(); TRANS(0x70)
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
Ch c;
|
Ch c;
|
||||||
COPY();
|
COPY();
|
||||||
|
@ -165,7 +160,7 @@ struct UTF8 {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (GetRange((unsigned char)c)) {
|
switch (GetRange(static_cast<unsigned char>(c))) {
|
||||||
case 2: TAIL(); return result;
|
case 2: TAIL(); return result;
|
||||||
case 3: TAIL(); TAIL(); return result;
|
case 3: TAIL(); TAIL(); return result;
|
||||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||||
|
@ -201,12 +196,12 @@ struct UTF8 {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
Ch c = Take(is);
|
typename InputByteStream::Ch c = Take(is);
|
||||||
if ((unsigned char)c != 0xEFu) return c;
|
if (static_cast<unsigned char>(c) != 0xEFu) return c;
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
if ((unsigned char)c != 0xBBu) return c;
|
if (static_cast<unsigned char>(c) != 0xBBu) return c;
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
if ((unsigned char)c != 0xBFu) return c;
|
if (static_cast<unsigned char>(c) != 0xBFu) return c;
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -214,13 +209,15 @@ struct UTF8 {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static Ch Take(InputByteStream& is) {
|
static Ch Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
return is.Take();
|
return static_cast<Ch>(is.Take());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
|
@ -267,15 +264,15 @@ struct UTF16 {
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||||
Ch c = is.Take();
|
typename InputStream::Ch c = is.Take();
|
||||||
if (c < 0xD800 || c > 0xDFFF) {
|
if (c < 0xD800 || c > 0xDFFF) {
|
||||||
*codepoint = c;
|
*codepoint = static_cast<unsigned>(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (c <= 0xDBFF) {
|
else if (c <= 0xDBFF) {
|
||||||
*codepoint = (c & 0x3FF) << 10;
|
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
*codepoint |= (c & 0x3FF);
|
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
|
||||||
*codepoint += 0x10000;
|
*codepoint += 0x10000;
|
||||||
return c >= 0xDC00 && c <= 0xDFFF;
|
return c >= 0xDC00 && c <= 0xDFFF;
|
||||||
}
|
}
|
||||||
|
@ -286,8 +283,8 @@ struct UTF16 {
|
||||||
static bool Validate(InputStream& is, OutputStream& os) {
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||||
Ch c;
|
typename InputStream::Ch c;
|
||||||
os.Put(c = is.Take());
|
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
|
||||||
if (c < 0xD800 || c > 0xDFFF)
|
if (c < 0xD800 || c > 0xDFFF)
|
||||||
return true;
|
return true;
|
||||||
else if (c <= 0xDBFF) {
|
else if (c <= 0xDBFF) {
|
||||||
|
@ -305,28 +302,29 @@ struct UTF16LE : UTF16<CharType> {
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return (unsigned short)c == 0xFEFFu ? Take(is) : c;
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = (unsigned char)is.Take();
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
c |= (unsigned char)is.Take() << 8;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
return c;
|
return static_cast<CharType>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(0xFFu); os.Put(0xFEu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void Put(OutputByteStream& os, CharType c) {
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(c & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||||
os.Put((c >> 8) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -337,28 +335,29 @@ struct UTF16BE : UTF16<CharType> {
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return (unsigned short)c == 0xFEFFu ? Take(is) : c;
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = (unsigned char)is.Take() << 8;
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
c |= (unsigned char)is.Take();
|
c |= static_cast<uint8_t>(is.Take());
|
||||||
return c;
|
return static_cast<CharType>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(0xFEu); os.Put(0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void Put(OutputByteStream& os, CharType c) {
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put((c >> 8) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||||
os.Put(c & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -411,32 +410,35 @@ struct UTF32LE : UTF32<CharType> {
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = (unsigned char)is.Take();
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
c |= (unsigned char)is.Take() << 8;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
c |= (unsigned char)is.Take() << 16;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||||
c |= (unsigned char)is.Take() << 24;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||||
return c;
|
return static_cast<CharType>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void Put(OutputByteStream& os, CharType c) {
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(c & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||||
os.Put((c >> 8) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||||
os.Put((c >> 16) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||||
os.Put((c >> 24) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -447,32 +449,35 @@ struct UTF32BE : UTF32<CharType> {
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = (unsigned char)is.Take() << 24;
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||||
c |= (unsigned char)is.Take() << 16;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||||
c |= (unsigned char)is.Take() << 8;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
c |= (unsigned char)is.Take();
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
|
||||||
return c;
|
return static_cast<CharType>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream& os) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void Put(OutputByteStream& os, CharType c) {
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put((c >> 24) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||||
os.Put((c >> 16) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||||
os.Put((c >> 8) & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||||
os.Put(c & 0xFFu);
|
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -498,29 +503,29 @@ struct ASCII {
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
unsigned char c = static_cast<unsigned char>(is.Take());
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
*codepoint = c;
|
*codepoint = c;
|
||||||
return c <= 0X7F;
|
return c <= 0X7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template <typename InputStream, typename OutputStream>
|
||||||
static bool Validate(InputStream& is, OutputStream& os) {
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
unsigned char c = is.Take();
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
os.Put(c);
|
os.Put(static_cast<typename OutputStream::Ch>(c));
|
||||||
return c <= 0x7F;
|
return c <= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
Ch c = Take(is);
|
uint8_t c = static_cast<uint8_t>(Take(is));
|
||||||
return c;
|
return static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static Ch Take(InputByteStream& is) {
|
static Ch Take(InputByteStream& is) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
return is.Take();
|
return static_cast<Ch>(is.Take());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
|
@ -621,9 +626,9 @@ struct Transcoder<Encoding, Encoding> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(_MSV_VER)
|
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ERROR_EN_H__
|
#ifndef RAPIDJSON_ERROR_EN_H_
|
||||||
#define RAPIDJSON_ERROR_EN_H__
|
#define RAPIDJSON_ERROR_EN_H_
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Maps error code of parsing into error message.
|
//! Maps error code of parsing into error message.
|
||||||
/*!
|
/*!
|
||||||
|
@ -61,11 +61,14 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
|
||||||
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
||||||
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
||||||
|
|
||||||
default:
|
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||||
return RAPIDJSON_ERROR_STRING("Unknown error.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_ERROR_EN_H__
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ERROR_EN_H_
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ERROR_ERROR_H__
|
#ifndef RAPIDJSON_ERROR_ERROR_H_
|
||||||
#define RAPIDJSON_ERROR_ERROR_H__
|
#define RAPIDJSON_ERROR_ERROR_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! \file error.h */
|
/*! \file error.h */
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@
|
||||||
#define RAPIDJSON_ERROR_STRING(x) x
|
#define RAPIDJSON_ERROR_STRING(x) x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ParseErrorCode
|
// ParseErrorCode
|
||||||
|
@ -85,7 +86,7 @@ enum ParseErrorCode {
|
||||||
kParseErrorNumberMissExponent, //!< Miss exponent in number.
|
kParseErrorNumberMissExponent, //!< Miss exponent in number.
|
||||||
|
|
||||||
kParseErrorTermination, //!< Parsing was terminated.
|
kParseErrorTermination, //!< Parsing was terminated.
|
||||||
kParseErrorUnspecificSyntaxError, //!< Unspecific syntax error.
|
kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Result of parsing (wraps ParseErrorCode)
|
//! Result of parsing (wraps ParseErrorCode)
|
||||||
|
@ -103,7 +104,7 @@ enum ParseErrorCode {
|
||||||
\see GenericReader::Parse, GenericDocument::Parse
|
\see GenericReader::Parse, GenericDocument::Parse
|
||||||
*/
|
*/
|
||||||
struct ParseResult {
|
struct ParseResult {
|
||||||
|
public:
|
||||||
//! Default constructor, no error.
|
//! Default constructor, no error.
|
||||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||||
//! Constructor to set an error.
|
//! Constructor to set an error.
|
||||||
|
@ -145,6 +146,10 @@ private:
|
||||||
*/
|
*/
|
||||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
|
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_ERROR_ERROR_H__
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ERROR_ERROR_H_
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_FILEREADSTREAM_H_
|
#ifndef RAPIDJSON_FILEREADSTREAM_H_
|
||||||
#define RAPIDJSON_FILEREADSTREAM_H_
|
#define RAPIDJSON_FILEREADSTREAM_H_
|
||||||
|
@ -24,7 +18,14 @@
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! File byte stream for input using fread().
|
//! File byte stream for input using fread().
|
||||||
/*!
|
/*!
|
||||||
|
@ -40,7 +41,7 @@ public:
|
||||||
\param buffer user-supplied buffer.
|
\param buffer user-supplied buffer.
|
||||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
||||||
*/
|
*/
|
||||||
FileReadStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||||
RAPIDJSON_ASSERT(fp_ != 0);
|
RAPIDJSON_ASSERT(fp_ != 0);
|
||||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||||
Read();
|
Read();
|
||||||
|
@ -79,7 +80,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* fp_;
|
std::FILE* fp_;
|
||||||
Ch *buffer_;
|
Ch *buffer_;
|
||||||
size_t bufferSize_;
|
size_t bufferSize_;
|
||||||
Ch *bufferLast_;
|
Ch *bufferLast_;
|
||||||
|
@ -89,6 +90,10 @@ private:
|
||||||
bool eof_;
|
bool eof_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_FILESTREAM_H_
|
#endif // RAPIDJSON_FILESTREAM_H_
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_FILESTREAM_H_
|
|
||||||
#define RAPIDJSON_FILESTREAM_H_
|
|
||||||
|
|
||||||
#include "rapidjson.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
namespace rapidjson {
|
|
||||||
|
|
||||||
//! (Depreciated) Wrapper of C file stream for input or output.
|
|
||||||
/*!
|
|
||||||
This simple wrapper does not check the validity of the stream.
|
|
||||||
\note implements Stream concept
|
|
||||||
\note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead.
|
|
||||||
*/
|
|
||||||
class FileStream {
|
|
||||||
public:
|
|
||||||
typedef char Ch; //!< Character type. Only support char.
|
|
||||||
|
|
||||||
FileStream(FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
|
|
||||||
char Peek() const { return current_; }
|
|
||||||
char Take() { char c = current_; Read(); return c; }
|
|
||||||
size_t Tell() const { return count_; }
|
|
||||||
void Put(char c) { fputc(c, fp_); }
|
|
||||||
void Flush() { fflush(fp_); }
|
|
||||||
|
|
||||||
// Not implemented
|
|
||||||
char* PutBegin() { return 0; }
|
|
||||||
size_t PutEnd(char*) { return 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Prohibit copy constructor & assignment operator.
|
|
||||||
FileStream(const FileStream&);
|
|
||||||
FileStream& operator=(const FileStream&);
|
|
||||||
|
|
||||||
void Read() {
|
|
||||||
RAPIDJSON_ASSERT(fp_ != 0);
|
|
||||||
int c = fgetc(fp_);
|
|
||||||
if (c != EOF) {
|
|
||||||
current_ = (char)c;
|
|
||||||
count_++;
|
|
||||||
}
|
|
||||||
else if (current_ != '\0')
|
|
||||||
current_ = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* fp_;
|
|
||||||
char current_;
|
|
||||||
size_t count_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace rapidjson
|
|
||||||
|
|
||||||
#endif // RAPIDJSON_FILESTREAM_H_
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
|
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
|
||||||
#define RAPIDJSON_FILEWRITESTREAM_H_
|
#define RAPIDJSON_FILEWRITESTREAM_H_
|
||||||
|
@ -24,7 +18,12 @@
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Wrapper of C file stream for input using fread().
|
//! Wrapper of C file stream for input using fread().
|
||||||
/*!
|
/*!
|
||||||
|
@ -34,7 +33,7 @@ class FileWriteStream {
|
||||||
public:
|
public:
|
||||||
typedef char Ch; //!< Character type. Only support char.
|
typedef char Ch; //!< Character type. Only support char.
|
||||||
|
|
||||||
FileWriteStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
|
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
|
||||||
RAPIDJSON_ASSERT(fp_ != 0);
|
RAPIDJSON_ASSERT(fp_ != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +62,11 @@ public:
|
||||||
|
|
||||||
void Flush() {
|
void Flush() {
|
||||||
if (current_ != buffer_) {
|
if (current_ != buffer_) {
|
||||||
fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||||
|
if (result < static_cast<size_t>(current_ - buffer_)) {
|
||||||
|
// failure deliberately ignored at this time
|
||||||
|
// added to avoid warn_unused_result build errors
|
||||||
|
}
|
||||||
current_ = buffer_;
|
current_ = buffer_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +83,7 @@ private:
|
||||||
FileWriteStream(const FileWriteStream&);
|
FileWriteStream(const FileWriteStream&);
|
||||||
FileWriteStream& operator=(const FileWriteStream&);
|
FileWriteStream& operator=(const FileWriteStream&);
|
||||||
|
|
||||||
FILE* fp_;
|
std::FILE* fp_;
|
||||||
char *buffer_;
|
char *buffer_;
|
||||||
char *bufferEnd_;
|
char *bufferEnd_;
|
||||||
char *current_;
|
char *current_;
|
||||||
|
@ -92,6 +95,10 @@ inline void PutN(FileWriteStream& stream, char c, size_t n) {
|
||||||
stream.PutN(c, n);
|
stream.PutN(c, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_FILESTREAM_H_
|
#endif // RAPIDJSON_FILESTREAM_H_
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
// 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_BIGINTEGER_H_
|
||||||
|
#define RAPIDJSON_BIGINTEGER_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
#include <intrin.h> // for _umul128
|
||||||
|
#pragma intrinsic(_umul128)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class BigInteger {
|
||||||
|
public:
|
||||||
|
typedef uint64_t Type;
|
||||||
|
|
||||||
|
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
|
||||||
|
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit BigInteger(uint64_t u) : count_(1) {
|
||||||
|
digits_[0] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger(const char* decimals, size_t length) : count_(1) {
|
||||||
|
RAPIDJSON_ASSERT(length > 0);
|
||||||
|
digits_[0] = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
|
||||||
|
while (length >= kMaxDigitPerIteration) {
|
||||||
|
AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
|
||||||
|
length -= kMaxDigitPerIteration;
|
||||||
|
i += kMaxDigitPerIteration;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger& operator+=(uint64_t u) {
|
||||||
|
Type backup = digits_[0];
|
||||||
|
digits_[0] += u;
|
||||||
|
for (size_t i = 0; i < count_ - 1; i++) {
|
||||||
|
if (digits_[i] >= backup)
|
||||||
|
return *this; // no carry
|
||||||
|
backup = digits_[i + 1];
|
||||||
|
digits_[i + 1] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last carry
|
||||||
|
if (digits_[count_ - 1] < backup)
|
||||||
|
PushBack(1);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger& operator*=(uint64_t u) {
|
||||||
|
if (u == 0) return *this = 0;
|
||||||
|
if (u == 1) return *this;
|
||||||
|
if (*this == 1) return *this = u;
|
||||||
|
|
||||||
|
uint64_t k = 0;
|
||||||
|
for (size_t i = 0; i < count_; i++) {
|
||||||
|
uint64_t hi;
|
||||||
|
digits_[i] = MulAdd64(digits_[i], u, k, &hi);
|
||||||
|
k = hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k > 0)
|
||||||
|
PushBack(k);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger& operator*=(uint32_t u) {
|
||||||
|
if (u == 0) return *this = 0;
|
||||||
|
if (u == 1) return *this;
|
||||||
|
if (*this == 1) return *this = u;
|
||||||
|
|
||||||
|
uint64_t k = 0;
|
||||||
|
for (size_t i = 0; i < count_; i++) {
|
||||||
|
const uint64_t c = digits_[i] >> 32;
|
||||||
|
const uint64_t d = digits_[i] & 0xFFFFFFFF;
|
||||||
|
const uint64_t uc = u * c;
|
||||||
|
const uint64_t ud = u * d;
|
||||||
|
const uint64_t p0 = ud + k;
|
||||||
|
const uint64_t p1 = uc + (p0 >> 32);
|
||||||
|
digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
|
||||||
|
k = p1 >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k > 0)
|
||||||
|
PushBack(k);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger& operator<<=(size_t shift) {
|
||||||
|
if (IsZero() || shift == 0) return *this;
|
||||||
|
|
||||||
|
size_t offset = shift / kTypeBit;
|
||||||
|
size_t interShift = shift % kTypeBit;
|
||||||
|
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||||
|
|
||||||
|
if (interShift == 0) {
|
||||||
|
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||||
|
count_ += offset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
digits_[count_] = 0;
|
||||||
|
for (size_t i = count_; i > 0; i--)
|
||||||
|
digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
|
||||||
|
digits_[offset] = digits_[0] << interShift;
|
||||||
|
count_ += offset;
|
||||||
|
if (digits_[count_])
|
||||||
|
count_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memset(digits_, 0, offset * sizeof(Type));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const BigInteger& rhs) const {
|
||||||
|
return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Type rhs) const {
|
||||||
|
return count_ == 1 && digits_[0] == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger& MultiplyPow5(unsigned exp) {
|
||||||
|
static const uint32_t kPow5[12] = {
|
||||||
|
5,
|
||||||
|
5 * 5,
|
||||||
|
5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||||
|
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
|
||||||
|
};
|
||||||
|
if (exp == 0) return *this;
|
||||||
|
for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
|
||||||
|
for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
|
||||||
|
if (exp > 0) *this *= kPow5[exp - 1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute absolute difference of this and rhs.
|
||||||
|
// Assume this != rhs
|
||||||
|
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
||||||
|
int cmp = Compare(rhs);
|
||||||
|
RAPIDJSON_ASSERT(cmp != 0);
|
||||||
|
const BigInteger *a, *b; // Makes a > b
|
||||||
|
bool ret;
|
||||||
|
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
||||||
|
else { a = this; b = &rhs; ret = false; }
|
||||||
|
|
||||||
|
Type borrow = 0;
|
||||||
|
for (size_t i = 0; i < a->count_; i++) {
|
||||||
|
Type d = a->digits_[i] - borrow;
|
||||||
|
if (i < b->count_)
|
||||||
|
d -= b->digits_[i];
|
||||||
|
borrow = (d > a->digits_[i]) ? 1 : 0;
|
||||||
|
out->digits_[i] = d;
|
||||||
|
if (d != 0)
|
||||||
|
out->count_ = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const BigInteger& rhs) const {
|
||||||
|
if (count_ != rhs.count_)
|
||||||
|
return count_ < rhs.count_ ? -1 : 1;
|
||||||
|
|
||||||
|
for (size_t i = count_; i-- > 0;)
|
||||||
|
if (digits_[i] != rhs.digits_[i])
|
||||||
|
return digits_[i] < rhs.digits_[i] ? -1 : 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetCount() const { return count_; }
|
||||||
|
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
||||||
|
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AppendDecimal64(const char* begin, const char* end) {
|
||||||
|
uint64_t u = ParseUint64(begin, end);
|
||||||
|
if (IsZero())
|
||||||
|
*this = u;
|
||||||
|
else {
|
||||||
|
unsigned exp = static_cast<unsigned>(end - begin);
|
||||||
|
(MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushBack(Type digit) {
|
||||||
|
RAPIDJSON_ASSERT(count_ < kCapacity);
|
||||||
|
digits_[count_++] = digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t ParseUint64(const char* begin, const char* end) {
|
||||||
|
uint64_t r = 0;
|
||||||
|
for (const char* p = begin; p != end; ++p) {
|
||||||
|
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
|
||||||
|
r = r * 10u + static_cast<unsigned>(*p - '0');
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume a * b + k < 2^128
|
||||||
|
static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
uint64_t low = _umul128(a, b, outHigh) + k;
|
||||||
|
if (low < k)
|
||||||
|
(*outHigh)++;
|
||||||
|
return low;
|
||||||
|
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||||
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
|
||||||
|
p += k;
|
||||||
|
*outHigh = static_cast<uint64_t>(p >> 64);
|
||||||
|
return static_cast<uint64_t>(p);
|
||||||
|
#else
|
||||||
|
const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
|
||||||
|
uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
|
||||||
|
x1 += (x0 >> 32); // can't give carry
|
||||||
|
x1 += x2;
|
||||||
|
if (x1 < x2)
|
||||||
|
x3 += (static_cast<uint64_t>(1) << 32);
|
||||||
|
uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
|
||||||
|
uint64_t hi = x3 + (x1 >> 32);
|
||||||
|
|
||||||
|
lo += k;
|
||||||
|
if (lo < k)
|
||||||
|
hi++;
|
||||||
|
*outHigh = hi;
|
||||||
|
return lo;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
|
||||||
|
static const size_t kCapacity = kBitCount / sizeof(Type);
|
||||||
|
static const size_t kTypeBit = sizeof(Type) * 8;
|
||||||
|
|
||||||
|
Type digits_[kCapacity];
|
||||||
|
size_t count_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_BIGINTEGER_H_
|
|
@ -0,0 +1,258 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||||
|
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||||
|
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_DIYFP_H_
|
||||||
|
#define RAPIDJSON_DIYFP_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma intrinsic(_BitScanReverse64)
|
||||||
|
#pragma intrinsic(_umul128)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct DiyFp {
|
||||||
|
DiyFp() {}
|
||||||
|
|
||||||
|
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
||||||
|
|
||||||
|
explicit DiyFp(double d) {
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t u64;
|
||||||
|
} u = { d };
|
||||||
|
|
||||||
|
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
||||||
|
uint64_t significand = (u.u64 & kDpSignificandMask);
|
||||||
|
if (biased_e != 0) {
|
||||||
|
f = significand + kDpHiddenBit;
|
||||||
|
e = biased_e - kDpExponentBias;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f = significand;
|
||||||
|
e = kDpMinExponent + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyFp operator-(const DiyFp& rhs) const {
|
||||||
|
return DiyFp(f - rhs.f, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyFp operator*(const DiyFp& rhs) const {
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
uint64_t h;
|
||||||
|
uint64_t l = _umul128(f, rhs.f, &h);
|
||||||
|
if (l & (uint64_t(1) << 63)) // rounding
|
||||||
|
h++;
|
||||||
|
return DiyFp(h, e + rhs.e + 64);
|
||||||
|
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||||
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
||||||
|
uint64_t h = static_cast<uint64_t>(p >> 64);
|
||||||
|
uint64_t l = static_cast<uint64_t>(p);
|
||||||
|
if (l & (uint64_t(1) << 63)) // rounding
|
||||||
|
h++;
|
||||||
|
return DiyFp(h, e + rhs.e + 64);
|
||||||
|
#else
|
||||||
|
const uint64_t M32 = 0xFFFFFFFF;
|
||||||
|
const uint64_t a = f >> 32;
|
||||||
|
const uint64_t b = f & M32;
|
||||||
|
const uint64_t c = rhs.f >> 32;
|
||||||
|
const uint64_t d = rhs.f & M32;
|
||||||
|
const uint64_t ac = a * c;
|
||||||
|
const uint64_t bc = b * c;
|
||||||
|
const uint64_t ad = a * d;
|
||||||
|
const uint64_t bd = b * d;
|
||||||
|
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
|
||||||
|
tmp += 1U << 31; /// mult_round
|
||||||
|
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyFp Normalize() const {
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
unsigned long index;
|
||||||
|
_BitScanReverse64(&index, f);
|
||||||
|
return DiyFp(f << (63 - index), e - (63 - index));
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
int s = __builtin_clzll(f);
|
||||||
|
return DiyFp(f << s, e - s);
|
||||||
|
#else
|
||||||
|
DiyFp res = *this;
|
||||||
|
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
|
||||||
|
res.f <<= 1;
|
||||||
|
res.e--;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyFp NormalizeBoundary() const {
|
||||||
|
DiyFp res = *this;
|
||||||
|
while (!(res.f & (kDpHiddenBit << 1))) {
|
||||||
|
res.f <<= 1;
|
||||||
|
res.e--;
|
||||||
|
}
|
||||||
|
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
|
||||||
|
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
|
||||||
|
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
||||||
|
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
||||||
|
mi.f <<= mi.e - pl.e;
|
||||||
|
mi.e = pl.e;
|
||||||
|
*plus = pl;
|
||||||
|
*minus = mi;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ToDouble() const {
|
||||||
|
union {
|
||||||
|
double d;
|
||||||
|
uint64_t u64;
|
||||||
|
}u;
|
||||||
|
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||||
|
static_cast<uint64_t>(e + kDpExponentBias);
|
||||||
|
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||||
|
return u.d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int kDiySignificandSize = 64;
|
||||||
|
static const int kDpSignificandSize = 52;
|
||||||
|
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
|
||||||
|
static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
|
||||||
|
static const int kDpMinExponent = -kDpExponentBias;
|
||||||
|
static const int kDpDenormalExponent = -kDpExponentBias + 1;
|
||||||
|
static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||||
|
static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||||
|
static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||||
|
|
||||||
|
uint64_t f;
|
||||||
|
int e;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||||
|
// 10^-348, 10^-340, ..., 10^340
|
||||||
|
static const uint64_t kCachedPowers_F[] = {
|
||||||
|
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||||
|
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||||
|
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
||||||
|
RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
||||||
|
RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
||||||
|
RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
||||||
|
RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
||||||
|
RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
||||||
|
RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
||||||
|
RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
||||||
|
RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
||||||
|
RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
||||||
|
RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
||||||
|
RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
||||||
|
RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
||||||
|
RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
||||||
|
RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
||||||
|
RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
||||||
|
RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
||||||
|
RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
||||||
|
RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
||||||
|
RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
||||||
|
RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
||||||
|
RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
||||||
|
RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
||||||
|
RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
||||||
|
RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
||||||
|
RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
||||||
|
RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
||||||
|
RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
||||||
|
RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
||||||
|
RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
||||||
|
RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
||||||
|
RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
||||||
|
RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
||||||
|
RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
||||||
|
RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
||||||
|
RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
||||||
|
RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
||||||
|
RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
||||||
|
RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
||||||
|
RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
||||||
|
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||||
|
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
||||||
|
};
|
||||||
|
static const int16_t kCachedPowers_E[] = {
|
||||||
|
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
||||||
|
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
||||||
|
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
||||||
|
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
|
||||||
|
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
|
||||||
|
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
|
||||||
|
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
|
||||||
|
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||||
|
907, 933, 960, 986, 1013, 1039, 1066
|
||||||
|
};
|
||||||
|
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DiyFp GetCachedPower(int e, int* K) {
|
||||||
|
|
||||||
|
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||||
|
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||||
|
int k = static_cast<int>(dk);
|
||||||
|
if (dk - k > 0.0)
|
||||||
|
k++;
|
||||||
|
|
||||||
|
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||||
|
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||||
|
|
||||||
|
return GetCachedPowerByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||||
|
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||||
|
*outExp = -348 + static_cast<int>(index) * 8;
|
||||||
|
return GetCachedPowerByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_DIYFP_H_
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||||
|
@ -25,16 +19,11 @@
|
||||||
#ifndef RAPIDJSON_DTOA_
|
#ifndef RAPIDJSON_DTOA_
|
||||||
#define RAPIDJSON_DTOA_
|
#define RAPIDJSON_DTOA_
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <intrin.h>
|
|
||||||
#if defined(_M_AMD64)
|
|
||||||
#pragma intrinsic(_BitScanReverse64)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "itoa.h" // GetDigitsLut()
|
#include "itoa.h" // GetDigitsLut()
|
||||||
|
#include "diyfp.h"
|
||||||
|
#include "ieee754.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -42,193 +31,6 @@ RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct DiyFp {
|
|
||||||
DiyFp() {}
|
|
||||||
|
|
||||||
DiyFp(uint64_t f, int e) : f(f), e(e) {}
|
|
||||||
|
|
||||||
DiyFp(double d) {
|
|
||||||
union {
|
|
||||||
double d;
|
|
||||||
uint64_t u64;
|
|
||||||
} u = { d };
|
|
||||||
|
|
||||||
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
|
||||||
uint64_t significand = (u.u64 & kDpSignificandMask);
|
|
||||||
if (biased_e != 0) {
|
|
||||||
f = significand + kDpHiddenBit;
|
|
||||||
e = biased_e - kDpExponentBias;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
f = significand;
|
|
||||||
e = kDpMinExponent + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DiyFp operator-(const DiyFp& rhs) const {
|
|
||||||
return DiyFp(f - rhs.f, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DiyFp operator*(const DiyFp& rhs) const {
|
|
||||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
|
||||||
uint64_t h;
|
|
||||||
uint64_t l = _umul128(f, rhs.f, &h);
|
|
||||||
if (l & (uint64_t(1) << 63)) // rounding
|
|
||||||
h++;
|
|
||||||
return DiyFp(h, e + rhs.e + 64);
|
|
||||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
|
||||||
unsigned __int128 p = static_cast<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
|
|
||||||
uint64_t h = static_cast<uint64_t>(p >> 64);
|
|
||||||
uint64_t l = static_cast<uint64_t>(p);
|
|
||||||
if (l & (uint64_t(1) << 63)) // rounding
|
|
||||||
h++;
|
|
||||||
return DiyFp(h, e + rhs.e + 64);
|
|
||||||
#else
|
|
||||||
const uint64_t M32 = 0xFFFFFFFF;
|
|
||||||
const uint64_t a = f >> 32;
|
|
||||||
const uint64_t b = f & M32;
|
|
||||||
const uint64_t c = rhs.f >> 32;
|
|
||||||
const uint64_t d = rhs.f & M32;
|
|
||||||
const uint64_t ac = a * c;
|
|
||||||
const uint64_t bc = b * c;
|
|
||||||
const uint64_t ad = a * d;
|
|
||||||
const uint64_t bd = b * d;
|
|
||||||
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
|
|
||||||
tmp += 1U << 31; /// mult_round
|
|
||||||
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
DiyFp Normalize() const {
|
|
||||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
|
||||||
unsigned long index;
|
|
||||||
_BitScanReverse64(&index, f);
|
|
||||||
return DiyFp(f << (63 - index), e - (63 - index));
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
int s = __builtin_clzll(f);
|
|
||||||
return DiyFp(f << s, e - s);
|
|
||||||
#else
|
|
||||||
DiyFp res = *this;
|
|
||||||
while (!(res.f & kDpHiddenBit)) {
|
|
||||||
res.f <<= 1;
|
|
||||||
res.e--;
|
|
||||||
}
|
|
||||||
res.f <<= (kDiySignificandSize - kDpSignificandSize - 1);
|
|
||||||
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1);
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
DiyFp NormalizeBoundary() const {
|
|
||||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
|
||||||
unsigned long index;
|
|
||||||
_BitScanReverse64(&index, f);
|
|
||||||
return DiyFp (f << (63 - index), e - (63 - index));
|
|
||||||
#else
|
|
||||||
DiyFp res = *this;
|
|
||||||
while (!(res.f & (kDpHiddenBit << 1))) {
|
|
||||||
res.f <<= 1;
|
|
||||||
res.e--;
|
|
||||||
}
|
|
||||||
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
|
|
||||||
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
|
|
||||||
return res;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
|
|
||||||
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
|
||||||
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
|
||||||
mi.f <<= mi.e - pl.e;
|
|
||||||
mi.e = pl.e;
|
|
||||||
*plus = pl;
|
|
||||||
*minus = mi;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int kDiySignificandSize = 64;
|
|
||||||
static const int kDpSignificandSize = 52;
|
|
||||||
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
|
|
||||||
static const int kDpMinExponent = -kDpExponentBias;
|
|
||||||
static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
|
||||||
static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
|
||||||
static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
|
||||||
|
|
||||||
uint64_t f;
|
|
||||||
int e;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline DiyFp GetCachedPower(int e, int* K) {
|
|
||||||
// 10^-348, 10^-340, ..., 10^340
|
|
||||||
static const uint64_t kCachedPowers_F[] = {
|
|
||||||
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
|
||||||
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
|
||||||
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
|
||||||
RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
|
||||||
RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
|
||||||
RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
|
||||||
RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
|
||||||
RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
|
||||||
RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
|
||||||
RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
|
||||||
RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
|
||||||
RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
|
||||||
RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
|
||||||
RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
|
||||||
RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
|
||||||
RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
|
||||||
RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
|
||||||
RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
|
||||||
RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
|
||||||
RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
|
||||||
RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
|
||||||
RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
|
||||||
RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
|
||||||
RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
|
||||||
RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
|
||||||
RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
|
||||||
RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
|
||||||
RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
|
||||||
RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
|
||||||
RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
|
||||||
RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
|
||||||
RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
|
||||||
RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
|
||||||
RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
|
||||||
RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
|
||||||
RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
|
||||||
RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
|
||||||
RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
|
||||||
RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
|
||||||
RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
|
||||||
RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
|
||||||
RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
|
||||||
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
|
||||||
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
|
||||||
};
|
|
||||||
static const int16_t kCachedPowers_E[] = {
|
|
||||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
|
||||||
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
|
||||||
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
|
||||||
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
|
|
||||||
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
|
|
||||||
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
|
|
||||||
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
|
|
||||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
|
||||||
907, 933, 960, 986, 1013, 1039, 1066
|
|
||||||
};
|
|
||||||
|
|
||||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
|
||||||
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
|
||||||
int k = static_cast<int>(dk);
|
|
||||||
if (k != dk)
|
|
||||||
k++;
|
|
||||||
|
|
||||||
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
|
||||||
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
|
||||||
|
|
||||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
||||||
while (rest < wp_w && delta - rest >= ten_kappa &&
|
while (rest < wp_w && delta - rest >= ten_kappa &&
|
||||||
(rest + ten_kappa < wp_w || /// closer
|
(rest + ten_kappa < wp_w || /// closer
|
||||||
|
@ -248,8 +50,10 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
|
||||||
if (n < 1000000) return 6;
|
if (n < 1000000) return 6;
|
||||||
if (n < 10000000) return 7;
|
if (n < 10000000) return 7;
|
||||||
if (n < 100000000) return 8;
|
if (n < 100000000) return 8;
|
||||||
if (n < 1000000000) return 9;
|
// Will not reach 10 digits in DigitGen()
|
||||||
return 10;
|
//if (n < 1000000000) return 9;
|
||||||
|
//return 10;
|
||||||
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
||||||
|
@ -258,13 +62,12 @@ 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);
|
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
while (kappa > 0) {
|
while (kappa > 0) {
|
||||||
uint32_t d;
|
uint32_t d = 0;
|
||||||
switch (kappa) {
|
switch (kappa) {
|
||||||
case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
|
|
||||||
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
||||||
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
||||||
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
||||||
|
@ -274,14 +77,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||||
case 3: d = p1 / 100; p1 %= 100; break;
|
case 3: d = p1 / 100; p1 %= 100; break;
|
||||||
case 2: d = p1 / 10; p1 %= 10; break;
|
case 2: d = p1 / 10; p1 %= 10; break;
|
||||||
case 1: d = p1; p1 = 0; break;
|
case 1: d = p1; p1 = 0; break;
|
||||||
default:
|
default:;
|
||||||
#if defined(_MSC_VER)
|
|
||||||
__assume(0);
|
|
||||||
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
|
||||||
__builtin_unreachable();
|
|
||||||
#else
|
|
||||||
d = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (d || *len)
|
if (d || *len)
|
||||||
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
||||||
|
@ -305,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,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++)
|
||||||
|
@ -383,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]);
|
||||||
|
@ -391,7 +187,10 @@ inline char* Prettify(char* buffer, int length, int k) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* dtoa(double value, char* buffer) {
|
inline char* dtoa(double value, char* buffer) {
|
||||||
if (value == 0) {
|
Double d(value);
|
||||||
|
if (d.IsZero()) {
|
||||||
|
if (d.Sign())
|
||||||
|
*buffer++ = '-'; // -0.0, Issue #289
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
buffer[2] = '0';
|
buffer[2] = '0';
|
||||||
|
@ -413,6 +212,6 @@ RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_DTOA_
|
#endif // RAPIDJSON_DTOA_
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
// 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_IEEE754_
|
||||||
|
#define RAPIDJSON_IEEE754_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class Double {
|
||||||
|
public:
|
||||||
|
Double() {}
|
||||||
|
Double(double d) : d_(d) {}
|
||||||
|
Double(uint64_t u) : u_(u) {}
|
||||||
|
|
||||||
|
double Value() const { return d_; }
|
||||||
|
uint64_t Uint64Value() const { return u_; }
|
||||||
|
|
||||||
|
double NextPositiveDouble() const {
|
||||||
|
RAPIDJSON_ASSERT(!Sign());
|
||||||
|
return Double(u_ + 1).Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sign() const { return (u_ & kSignMask) != 0; }
|
||||||
|
uint64_t Significand() const { return u_ & kSignificandMask; }
|
||||||
|
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
||||||
|
|
||||||
|
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||||
|
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||||
|
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
||||||
|
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
|
||||||
|
|
||||||
|
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
||||||
|
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||||
|
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
||||||
|
|
||||||
|
static unsigned EffectiveSignificandSize(int order) {
|
||||||
|
if (order >= -1021)
|
||||||
|
return 53;
|
||||||
|
else if (order <= -1074)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return static_cast<unsigned>(order) + 1074;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int kSignificandSize = 52;
|
||||||
|
static const int kExponentBias = 0x3FF;
|
||||||
|
static const int kDenormalExponent = 1 - kExponentBias;
|
||||||
|
static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
||||||
|
static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||||
|
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||||
|
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||||
|
|
||||||
|
union {
|
||||||
|
double d_;
|
||||||
|
uint64_t u_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_IEEE754_
|
|
@ -1,27 +1,23 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_ITOA_
|
#ifndef RAPIDJSON_ITOA_
|
||||||
#define RAPIDJSON_ITOA_
|
#define RAPIDJSON_ITOA_
|
||||||
|
|
||||||
namespace rapidjson {
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
inline const char* GetDigitsLut() {
|
inline const char* GetDigitsLut() {
|
||||||
|
@ -115,12 +111,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* i32toa(int32_t value, char* buffer) {
|
inline char* i32toa(int32_t value, char* buffer) {
|
||||||
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
value = -value;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return u32toa(static_cast<uint32_t>(value), buffer);
|
return u32toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* u64toa(uint64_t value, char* buffer) {
|
inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
|
@ -292,15 +289,16 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* i64toa(int64_t value, char* buffer) {
|
inline char* i64toa(int64_t value, char* buffer) {
|
||||||
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
value = -value;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return u64toa(static_cast<uint64_t>(value), buffer);
|
return u64toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_ITOA_
|
#endif // RAPIDJSON_ITOA_
|
||||||
|
|
|
@ -1,29 +1,21 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_INTERNAL_META_H_
|
#ifndef RAPIDJSON_INTERNAL_META_H_
|
||||||
#define RAPIDJSON_INTERNAL_META_H_
|
#define RAPIDJSON_INTERNAL_META_H_
|
||||||
|
|
||||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
#include "../rapidjson.h"
|
||||||
#error <rapidjson.h> not yet included. Do not include this file directly.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
@ -39,7 +31,7 @@ RAPIDJSON_DIAG_OFF(6334)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//@cond RAPIDJSON_INTERNAL
|
//@cond RAPIDJSON_INTERNAL
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||||
|
@ -157,29 +149,29 @@ template <typename T> struct RemoveSfinaeTag;
|
||||||
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
|
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
|
||||||
|
|
||||||
#define RAPIDJSON_REMOVEFPTR_(type) \
|
#define RAPIDJSON_REMOVEFPTR_(type) \
|
||||||
typename ::rapidjson::internal::RemoveSfinaeTag \
|
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||||
< ::rapidjson::internal::SfinaeTag&(*) type>::Type
|
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
|
||||||
|
|
||||||
#define RAPIDJSON_ENABLEIF(cond) \
|
#define RAPIDJSON_ENABLEIF(cond) \
|
||||||
typename ::rapidjson::internal::EnableIf \
|
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
#define RAPIDJSON_DISABLEIF(cond) \
|
#define RAPIDJSON_DISABLEIF(cond) \
|
||||||
typename ::rapidjson::internal::DisableIf \
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||||
typename ::rapidjson::internal::EnableIf \
|
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||||
|
|
||||||
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||||
typename ::rapidjson::internal::DisableIf \
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
//@endcond
|
//@endcond
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||||
|
|
|
@ -1,27 +1,23 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_POW10_
|
#ifndef RAPIDJSON_POW10_
|
||||||
#define RAPIDJSON_POW10_
|
#define RAPIDJSON_POW10_
|
||||||
|
|
||||||
namespace rapidjson {
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
//! Computes integer powers of 10 in double (10.0^n).
|
//! Computes integer powers of 10 in double (10.0^n).
|
||||||
|
@ -54,6 +50,6 @@ inline double Pow10(int n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_POW10_
|
#endif // RAPIDJSON_POW10_
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||||
#define RAPIDJSON_INTERNAL_STACK_H_
|
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||||
|
|
||||||
namespace rapidjson {
|
#include "../rapidjson.h"
|
||||||
|
#include "swap.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -35,15 +32,63 @@ class Stack {
|
||||||
public:
|
public:
|
||||||
// Optimization note: Do not allocate memory for stack_ in constructor.
|
// Optimization note: Do not allocate memory for stack_ in constructor.
|
||||||
// Do it lazily when first Push() -> Expand() -> Resize().
|
// Do it lazily when first Push() -> Expand() -> Resize().
|
||||||
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
|
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
|
||||||
RAPIDJSON_ASSERT(stackCapacity > 0);
|
RAPIDJSON_ASSERT(stackCapacity > 0);
|
||||||
if (!allocator_)
|
|
||||||
ownAllocator = allocator_ = new Allocator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
Stack(Stack&& rhs)
|
||||||
|
: allocator_(rhs.allocator_),
|
||||||
|
ownAllocator_(rhs.ownAllocator_),
|
||||||
|
stack_(rhs.stack_),
|
||||||
|
stackTop_(rhs.stackTop_),
|
||||||
|
stackEnd_(rhs.stackEnd_),
|
||||||
|
initialCapacity_(rhs.initialCapacity_)
|
||||||
|
{
|
||||||
|
rhs.allocator_ = 0;
|
||||||
|
rhs.ownAllocator_ = 0;
|
||||||
|
rhs.stack_ = 0;
|
||||||
|
rhs.stackTop_ = 0;
|
||||||
|
rhs.stackEnd_ = 0;
|
||||||
|
rhs.initialCapacity_ = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
~Stack() {
|
~Stack() {
|
||||||
Allocator::Free(stack_);
|
Destroy();
|
||||||
delete ownAllocator; // Only delete if it is owned by the stack
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
Stack& operator=(Stack&& rhs) {
|
||||||
|
if (&rhs != this)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
allocator_ = rhs.allocator_;
|
||||||
|
ownAllocator_ = rhs.ownAllocator_;
|
||||||
|
stack_ = rhs.stack_;
|
||||||
|
stackTop_ = rhs.stackTop_;
|
||||||
|
stackEnd_ = rhs.stackEnd_;
|
||||||
|
initialCapacity_ = rhs.initialCapacity_;
|
||||||
|
|
||||||
|
rhs.allocator_ = 0;
|
||||||
|
rhs.ownAllocator_ = 0;
|
||||||
|
rhs.stack_ = 0;
|
||||||
|
rhs.stackTop_ = 0;
|
||||||
|
rhs.stackEnd_ = 0;
|
||||||
|
rhs.initialCapacity_ = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#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_; }
|
||||||
|
@ -87,9 +132,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Bottom() { return (T*)stack_; }
|
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
||||||
|
|
||||||
Allocator& GetAllocator() { return *allocator_; }
|
bool HasAllocator() const {
|
||||||
|
return allocator_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator& GetAllocator() {
|
||||||
|
RAPIDJSON_ASSERT(allocator_);
|
||||||
|
return *allocator_;
|
||||||
|
}
|
||||||
bool Empty() const { return stackTop_ == stack_; }
|
bool Empty() const { return stackTop_ == stack_; }
|
||||||
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
||||||
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
|
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
|
||||||
|
@ -99,9 +151,11 @@ private:
|
||||||
void Expand(size_t count) {
|
void Expand(size_t count) {
|
||||||
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
|
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
|
||||||
size_t newCapacity;
|
size_t newCapacity;
|
||||||
if (stack_ == 0)
|
if (stack_ == 0) {
|
||||||
|
if (!allocator_)
|
||||||
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||||
newCapacity = initialCapacity_;
|
newCapacity = initialCapacity_;
|
||||||
else {
|
} else {
|
||||||
newCapacity = GetCapacity();
|
newCapacity = GetCapacity();
|
||||||
newCapacity += (newCapacity + 1) / 2;
|
newCapacity += (newCapacity + 1) / 2;
|
||||||
}
|
}
|
||||||
|
@ -114,17 +168,22 @@ private:
|
||||||
|
|
||||||
void Resize(size_t newCapacity) {
|
void Resize(size_t newCapacity) {
|
||||||
const size_t size = GetSize(); // Backup the current size
|
const size_t size = GetSize(); // Backup the current size
|
||||||
stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
|
stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
|
||||||
stackTop_ = stack_ + size;
|
stackTop_ = stack_ + size;
|
||||||
stackEnd_ = stack_ + newCapacity;
|
stackEnd_ = stack_ + newCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Destroy() {
|
||||||
|
Allocator::Free(stack_);
|
||||||
|
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
||||||
|
}
|
||||||
|
|
||||||
// Prohibit copy constructor & assignment operator.
|
// Prohibit copy constructor & assignment operator.
|
||||||
Stack(const Stack&);
|
Stack(const Stack&);
|
||||||
Stack& operator=(const Stack&);
|
Stack& operator=(const Stack&);
|
||||||
|
|
||||||
Allocator* allocator_;
|
Allocator* allocator_;
|
||||||
Allocator* ownAllocator;
|
Allocator* ownAllocator_;
|
||||||
char *stack_;
|
char *stack_;
|
||||||
char *stackTop_;
|
char *stackTop_;
|
||||||
char *stackEnd_;
|
char *stackEnd_;
|
||||||
|
@ -132,6 +191,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_STACK_H_
|
#endif // RAPIDJSON_STACK_H_
|
||||||
|
|
|
@ -1,27 +1,23 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
|
|
||||||
namespace rapidjson {
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
//! Custom strlen() which works on different character types.
|
//! Custom strlen() which works on different character types.
|
||||||
|
@ -38,6 +34,6 @@ inline SizeType StrLen(const Ch* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
// 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_STRTOD_
|
||||||
|
#define RAPIDJSON_STRTOD_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
#include "ieee754.h"
|
||||||
|
#include "biginteger.h"
|
||||||
|
#include "diyfp.h"
|
||||||
|
#include "pow10.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
inline double FastPath(double significand, int exp) {
|
||||||
|
if (exp < -308)
|
||||||
|
return 0.0;
|
||||||
|
else if (exp >= 0)
|
||||||
|
return significand * internal::Pow10(exp);
|
||||||
|
else
|
||||||
|
return significand / internal::Pow10(-exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double StrtodNormalPrecision(double d, int p) {
|
||||||
|
if (p < -308) {
|
||||||
|
// Prevent expSum < -308, making Pow10(p) = 0
|
||||||
|
d = FastPath(d, -308);
|
||||||
|
d = FastPath(d, p + 308);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
d = FastPath(d, p);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T Min3(T a, T b, T c) {
|
||||||
|
T m = a;
|
||||||
|
if (m > b) m = b;
|
||||||
|
if (m > c) m = c;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||||
|
const Double db(b);
|
||||||
|
const uint64_t bInt = db.IntegerSignificand();
|
||||||
|
const int bExp = db.IntegerExponent();
|
||||||
|
const int hExp = bExp - 1;
|
||||||
|
|
||||||
|
int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
|
||||||
|
|
||||||
|
// Adjust for decimal exponent
|
||||||
|
if (dExp >= 0) {
|
||||||
|
dS_Exp2 += dExp;
|
||||||
|
dS_Exp5 += dExp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bS_Exp2 -= dExp;
|
||||||
|
bS_Exp5 -= dExp;
|
||||||
|
hS_Exp2 -= dExp;
|
||||||
|
hS_Exp5 -= dExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for binary exponent
|
||||||
|
if (bExp >= 0)
|
||||||
|
bS_Exp2 += bExp;
|
||||||
|
else {
|
||||||
|
dS_Exp2 -= bExp;
|
||||||
|
hS_Exp2 -= bExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for half ulp exponent
|
||||||
|
if (hExp >= 0)
|
||||||
|
hS_Exp2 += hExp;
|
||||||
|
else {
|
||||||
|
dS_Exp2 -= hExp;
|
||||||
|
bS_Exp2 -= hExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove common power of two factor from all three scaled values
|
||||||
|
int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
|
||||||
|
dS_Exp2 -= common_Exp2;
|
||||||
|
bS_Exp2 -= common_Exp2;
|
||||||
|
hS_Exp2 -= common_Exp2;
|
||||||
|
|
||||||
|
BigInteger dS = d;
|
||||||
|
dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
|
||||||
|
|
||||||
|
BigInteger bS(bInt);
|
||||||
|
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
|
||||||
|
|
||||||
|
BigInteger hS(1);
|
||||||
|
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
|
||||||
|
|
||||||
|
BigInteger delta(0);
|
||||||
|
dS.Difference(bS, &delta);
|
||||||
|
|
||||||
|
return delta.Compare(hS);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool StrtodFast(double d, int p, double* result) {
|
||||||
|
// Use fast path for string-to-double conversion if possible
|
||||||
|
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||||
|
if (p > 22 && p < 22 + 16) {
|
||||||
|
// Fast Path Cases In Disguise
|
||||||
|
d *= internal::Pow10(p - 22);
|
||||||
|
p = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
|
||||||
|
*result = FastPath(d, p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute an approximation and see if it is within 1/2 ULP
|
||||||
|
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
|
||||||
|
uint64_t significand = 0;
|
||||||
|
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||||
|
for (; i < length; i++) {
|
||||||
|
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||||
|
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||||
|
break;
|
||||||
|
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < length && decimals[i] >= '5') // Rounding
|
||||||
|
significand++;
|
||||||
|
|
||||||
|
size_t remaining = length - i;
|
||||||
|
const unsigned kUlpShift = 3;
|
||||||
|
const unsigned kUlp = 1 << kUlpShift;
|
||||||
|
int error = (remaining == 0) ? 0 : kUlp / 2;
|
||||||
|
|
||||||
|
DiyFp v(significand, 0);
|
||||||
|
v = v.Normalize();
|
||||||
|
error <<= -v.e;
|
||||||
|
|
||||||
|
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
|
||||||
|
|
||||||
|
int actualExp;
|
||||||
|
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||||
|
if (actualExp != dExp) {
|
||||||
|
static const DiyFp kPow10[] = {
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
|
||||||
|
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
|
||||||
|
};
|
||||||
|
int adjustment = dExp - actualExp - 1;
|
||||||
|
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||||
|
v = v * kPow10[adjustment];
|
||||||
|
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
|
||||||
|
error += kUlp / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = v * cachedPower;
|
||||||
|
|
||||||
|
error += kUlp + (error == 0 ? 0 : 1);
|
||||||
|
|
||||||
|
const int oldExp = v.e;
|
||||||
|
v = v.Normalize();
|
||||||
|
error <<= oldExp - v.e;
|
||||||
|
|
||||||
|
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||||
|
unsigned precisionSize = 64 - effectiveSignificandSize;
|
||||||
|
if (precisionSize + kUlpShift >= 64) {
|
||||||
|
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
||||||
|
v.f >>= scaleExp;
|
||||||
|
v.e += scaleExp;
|
||||||
|
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
|
||||||
|
precisionSize -= scaleExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + static_cast<unsigned>(error)) {
|
||||||
|
rounded.f++;
|
||||||
|
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
|
||||||
|
rounded.f >>= 1;
|
||||||
|
rounded.e++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = rounded.ToDouble();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
const BigInteger dInt(decimals, length);
|
||||||
|
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||||
|
Double a(approx);
|
||||||
|
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||||
|
if (cmp < 0)
|
||||||
|
return a.Value(); // within half ULP
|
||||||
|
else if (cmp == 0) {
|
||||||
|
// Round towards even
|
||||||
|
if (a.Significand() & 1)
|
||||||
|
return a.NextPositiveDouble();
|
||||||
|
else
|
||||||
|
return a.Value();
|
||||||
|
}
|
||||||
|
else // adjustment
|
||||||
|
return a.NextPositiveDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||||
|
RAPIDJSON_ASSERT(d >= 0.0);
|
||||||
|
RAPIDJSON_ASSERT(length >= 1);
|
||||||
|
|
||||||
|
double result;
|
||||||
|
if (StrtodFast(d, p, &result))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Trim leading zeros
|
||||||
|
while (*decimals == '0' && length > 1) {
|
||||||
|
length--;
|
||||||
|
decimals++;
|
||||||
|
decimalPosition--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim trailing zeros
|
||||||
|
while (decimals[length - 1] == '0' && length > 1) {
|
||||||
|
length--;
|
||||||
|
decimalPosition--;
|
||||||
|
exp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim right-most digits
|
||||||
|
const int kMaxDecimalDigit = 780;
|
||||||
|
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||||
|
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||||
|
exp += delta;
|
||||||
|
decimalPosition -= static_cast<unsigned>(delta);
|
||||||
|
length = kMaxDecimalDigit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If too small, underflow to zero
|
||||||
|
if (int(length) + exp < -324)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||||
|
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_STRTOD_
|
|
@ -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++ <algorithm> 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_
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_MEMORYBUFFER_H_
|
#ifndef RAPIDJSON_MEMORYBUFFER_H_
|
||||||
#define RAPIDJSON_MEMORYBUFFER_H_
|
#define RAPIDJSON_MEMORYBUFFER_H_
|
||||||
|
@ -24,7 +18,7 @@
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
#include "internal/stack.h"
|
#include "internal/stack.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Represents an in-memory output byte stream.
|
//! Represents an in-memory output byte stream.
|
||||||
/*!
|
/*!
|
||||||
|
@ -71,6 +65,6 @@ inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
|
||||||
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
|
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_MEMORYSTREAM_H_
|
#ifndef RAPIDJSON_MEMORYSTREAM_H_
|
||||||
#define RAPIDJSON_MEMORYSTREAM_H_
|
#define RAPIDJSON_MEMORYSTREAM_H_
|
||||||
|
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Represents an in-memory input byte stream.
|
//! Represents an in-memory input byte stream.
|
||||||
/*!
|
/*!
|
||||||
|
@ -42,7 +42,7 @@ struct MemoryStream {
|
||||||
|
|
||||||
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
|
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
|
||||||
|
|
||||||
Ch Peek() const { return *src_; }
|
Ch Peek() const { return (src_ == end_) ? '\0' : *src_; }
|
||||||
Ch Take() { return (src_ == end_) ? '\0' : *src_++; }
|
Ch Take() { return (src_ == end_) ? '\0' : *src_++; }
|
||||||
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
|
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
|
||||||
|
|
||||||
|
@ -62,6 +62,10 @@ struct MemoryStream {
|
||||||
size_t size_; //!< Size of the stream.
|
size_t size_; //!< Size of the stream.
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// The above software in this distribution may have been modified by
|
||||||
|
// THL A29 Limited ("Tencent Modifications").
|
||||||
|
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||||
|
|
||||||
#ifndef _MSC_VER // [
|
#ifndef _MSC_VER // [
|
||||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
#endif // _MSC_VER ]
|
#endif // _MSC_VER ]
|
||||||
|
@ -43,6 +47,11 @@
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
|
// miloyip: VC supports inttypes.h since VC2013
|
||||||
|
#if _MSC_VER >= 1800
|
||||||
|
#include <inttypes.h>
|
||||||
|
#else
|
||||||
|
|
||||||
// 7.8 Format conversion of integer types
|
// 7.8 Format conversion of integer types
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -302,5 +311,6 @@ imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||||
#define wcstoimax _wcstoi64
|
#define wcstoimax _wcstoi64
|
||||||
#define wcstoumax _wcstoui64
|
#define wcstoumax _wcstoui64
|
||||||
|
|
||||||
|
#endif // _MSC_VER >= 1800
|
||||||
|
|
||||||
#endif // _MSC_INTTYPES_H_ ]
|
#endif // _MSC_INTTYPES_H_ ]
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// The above software in this distribution may have been modified by
|
||||||
|
// THL A29 Limited ("Tencent Modifications").
|
||||||
|
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||||
|
|
||||||
#ifndef _MSC_VER // [
|
#ifndef _MSC_VER // [
|
||||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||||
#endif // _MSC_VER ]
|
#endif // _MSC_VER ]
|
||||||
|
@ -85,14 +89,14 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
|
||||||
// or compiler give many errors like this:
|
// or compiler would give many errors like this:
|
||||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||||
#ifdef __cplusplus
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
# include <wchar.h>
|
# include <wchar.h>
|
||||||
#ifdef __cplusplus
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_PRETTYWRITER_H_
|
#ifndef RAPIDJSON_PRETTYWRITER_H_
|
||||||
#define RAPIDJSON_PRETTYWRITER_H_
|
#define RAPIDJSON_PRETTYWRITER_H_
|
||||||
|
@ -28,7 +22,7 @@ RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Writer with indentation and spacing.
|
//! Writer with indentation and spacing.
|
||||||
/*!
|
/*!
|
||||||
|
@ -82,6 +76,12 @@ public:
|
||||||
return Base::WriteString(str, length);
|
return Base::WriteString(str, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
bool String(const std::basic_string<Ch>& str) {
|
||||||
|
return String(str.data(), SizeType(str.size()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool StartObject() {
|
bool StartObject() {
|
||||||
PrettyPrefix(kObjectType);
|
PrettyPrefix(kObjectType);
|
||||||
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
|
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
|
||||||
|
@ -100,8 +100,9 @@ public:
|
||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
if (!Base::WriteEndObject())
|
bool ret = Base::WriteEndObject();
|
||||||
return false;
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
if (Base::level_stack_.Empty()) // end of json text
|
if (Base::level_stack_.Empty()) // end of json text
|
||||||
Base::os_->Flush();
|
Base::os_->Flush();
|
||||||
return true;
|
return true;
|
||||||
|
@ -123,8 +124,9 @@ public:
|
||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
if (!Base::WriteEndArray())
|
bool ret = Base::WriteEndArray();
|
||||||
return false;
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
if (Base::level_stack_.Empty()) // end of json text
|
if (Base::level_stack_.Empty()) // end of json text
|
||||||
Base::os_->Flush();
|
Base::os_->Flush();
|
||||||
return true;
|
return true;
|
||||||
|
@ -184,7 +186,7 @@ protected:
|
||||||
|
|
||||||
void WriteIndent() {
|
void WriteIndent() {
|
||||||
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
||||||
PutN(*Base::os_, indentChar_, count);
|
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch indentChar_;
|
Ch indentChar_;
|
||||||
|
@ -196,7 +198,7 @@ private:
|
||||||
PrettyWriter& operator=(const PrettyWriter&);
|
PrettyWriter& operator=(const PrettyWriter&);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
#ifndef RAPIDJSON_RAPIDJSON_H_
|
||||||
#define RAPIDJSON_RAPIDJSON_H_
|
#define RAPIDJSON_RAPIDJSON_H_
|
||||||
|
|
||||||
// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
|
|
||||||
// Version 0.1
|
|
||||||
|
|
||||||
/*!\file rapidjson.h
|
/*!\file rapidjson.h
|
||||||
\brief common definitions and configuration
|
\brief common definitions and configuration
|
||||||
|
|
||||||
|
@ -48,6 +39,111 @@
|
||||||
#include <cstdlib> // malloc(), realloc(), free(), size_t
|
#include <cstdlib> // malloc(), realloc(), free(), size_t
|
||||||
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_VERSION_STRING
|
||||||
|
//
|
||||||
|
// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
|
||||||
|
//
|
||||||
|
|
||||||
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
|
// token stringification
|
||||||
|
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
||||||
|
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
||||||
|
//!@endcond
|
||||||
|
|
||||||
|
/*! \def RAPIDJSON_MAJOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Major version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_MINOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Minor version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_PATCH_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Patch version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_VERSION_STRING
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
|
||||||
|
*/
|
||||||
|
#define RAPIDJSON_MAJOR_VERSION 1
|
||||||
|
#define RAPIDJSON_MINOR_VERSION 0
|
||||||
|
#define RAPIDJSON_PATCH_VERSION 2
|
||||||
|
#define RAPIDJSON_VERSION_STRING \
|
||||||
|
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_NAMESPACE_(BEGIN|END)
|
||||||
|
/*! \def RAPIDJSON_NAMESPACE
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief provide custom rapidjson namespace
|
||||||
|
|
||||||
|
In order to avoid symbol clashes and/or "One Definition Rule" errors
|
||||||
|
between multiple inclusions of (different versions of) RapidJSON in
|
||||||
|
a single binary, users can customize the name of the main RapidJSON
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
|
||||||
|
to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
|
||||||
|
levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
|
||||||
|
RAPIDJSON_NAMESPACE_END need to be defined as well:
|
||||||
|
|
||||||
|
\code
|
||||||
|
// in some .cpp file
|
||||||
|
#define RAPIDJSON_NAMESPACE my::rapidjson
|
||||||
|
#define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
|
||||||
|
#define RAPIDJSON_NAMESPACE_END } }
|
||||||
|
#include "rapidjson/..."
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\see rapidjson
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief provide custom rapidjson namespace (opening expression)
|
||||||
|
\see RAPIDJSON_NAMESPACE
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_NAMESPACE_END
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief provide custom rapidjson namespace (closing expression)
|
||||||
|
\see RAPIDJSON_NAMESPACE
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_NAMESPACE
|
||||||
|
#define RAPIDJSON_NAMESPACE rapidjson
|
||||||
|
#endif
|
||||||
|
#ifndef RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
|
||||||
|
#endif
|
||||||
|
#ifndef RAPIDJSON_NAMESPACE_END
|
||||||
|
#define RAPIDJSON_NAMESPACE_END }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_HAS_STDSTRING
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_HAS_STDSTRING
|
||||||
|
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||||
|
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
|
||||||
|
#endif
|
||||||
|
/*! \def RAPIDJSON_HAS_STDSTRING
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Enable RapidJSON support for \c std::string
|
||||||
|
|
||||||
|
By defining this preprocessor symbol to \c 1, several convenience functions for using
|
||||||
|
\ref rapidjson::GenericValue with \c std::string are enabled, especially
|
||||||
|
for construction and comparison.
|
||||||
|
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#endif // !defined(RAPIDJSON_HAS_STDSTRING)
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
#include <string>
|
||||||
|
#endif // RAPIDJSON_HAS_STDSTRING
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_NO_INT64DEFINE
|
// RAPIDJSON_NO_INT64DEFINE
|
||||||
|
|
||||||
|
@ -82,9 +178,9 @@
|
||||||
|
|
||||||
#ifndef RAPIDJSON_FORCEINLINE
|
#ifndef RAPIDJSON_FORCEINLINE
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||||
#define RAPIDJSON_FORCEINLINE __forceinline
|
#define RAPIDJSON_FORCEINLINE __forceinline
|
||||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
|
||||||
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_FORCEINLINE
|
#define RAPIDJSON_FORCEINLINE
|
||||||
|
@ -140,6 +236,8 @@
|
||||||
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||||
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
|
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
|
||||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
|
# elif defined(_MSC_VER) && defined(_M_ARM)
|
||||||
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||||
# define RAPIDJSON_ENDIAN
|
# define RAPIDJSON_ENDIAN
|
||||||
# else
|
# else
|
||||||
|
@ -152,7 +250,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
|
||||||
|
@ -167,10 +265,14 @@
|
||||||
\param x pointer to align
|
\param x pointer to align
|
||||||
|
|
||||||
Some machines require strict data alignment. Currently the default uses 4 bytes
|
Some machines require strict data alignment. Currently the default uses 4 bytes
|
||||||
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.,
|
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.
|
||||||
*/
|
*/
|
||||||
#ifndef RAPIDJSON_ALIGN
|
#ifndef RAPIDJSON_ALIGN
|
||||||
#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
|
#if RAPIDJSON_64BIT == 1
|
||||||
|
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -238,20 +340,20 @@
|
||||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||||
#define RAPIDJSON_NO_SIZETYPEDEFINE
|
#define RAPIDJSON_NO_SIZETYPEDEFINE
|
||||||
#endif
|
#endif
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
//! Size type (for string lengths, array sizes, etc.)
|
//! Size type (for string lengths, array sizes, etc.)
|
||||||
/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
|
/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
|
||||||
instead of using \c size_t. Users may override the SizeType by defining
|
instead of using \c size_t. Users may override the SizeType by defining
|
||||||
\ref RAPIDJSON_NO_SIZETYPEDEFINE.
|
\ref RAPIDJSON_NO_SIZETYPEDEFINE.
|
||||||
*/
|
*/
|
||||||
typedef unsigned SizeType;
|
typedef unsigned SizeType;
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// always import std::size_t to rapidjson namespace
|
// always import std::size_t to rapidjson namespace
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_ASSERT
|
// RAPIDJSON_ASSERT
|
||||||
|
@ -274,13 +376,14 @@ using std::size_t;
|
||||||
|
|
||||||
// Adopt from boost
|
// Adopt from boost
|
||||||
#ifndef RAPIDJSON_STATIC_ASSERT
|
#ifndef RAPIDJSON_STATIC_ASSERT
|
||||||
|
#ifndef __clang__
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
namespace rapidjson {
|
#endif
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||||
template<int x> struct StaticAssertTest {};
|
template<int x> struct StaticAssertTest {};
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
|
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
|
||||||
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
|
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
|
||||||
|
@ -291,15 +394,18 @@ template<int x> struct StaticAssertTest {};
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __clang__
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! \def RAPIDJSON_STATIC_ASSERT
|
/*! \def RAPIDJSON_STATIC_ASSERT
|
||||||
\brief (Internal) macro to check for conditions at compile-time
|
\brief (Internal) macro to check for conditions at compile-time
|
||||||
\param x compile-time condition
|
\param x compile-time condition
|
||||||
\hideinitializer
|
\hideinitializer
|
||||||
*/
|
*/
|
||||||
#define RAPIDJSON_STATIC_ASSERT(x) typedef ::rapidjson::StaticAssertTest<\
|
#define RAPIDJSON_STATIC_ASSERT(x) \
|
||||||
sizeof(::rapidjson::STATIC_ASSERTION_FAILURE<bool(x) >)>\
|
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
||||||
|
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
|
||||||
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -316,10 +422,6 @@ template<int x> struct StaticAssertTest {};
|
||||||
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||||
(((x)*100000) + ((y)*100) + (z))
|
(((x)*100000) + ((y)*100) + (z))
|
||||||
|
|
||||||
// token stringification
|
|
||||||
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
|
||||||
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
||||||
|
|
||||||
|
@ -367,7 +469,8 @@ template<int x> struct StaticAssertTest {};
|
||||||
|
|
||||||
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references)
|
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \
|
||||||
|
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||||
(defined(_MSC_VER) && _MSC_VER >= 1600)
|
(defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||||
|
|
||||||
|
@ -400,14 +503,29 @@ template<int x> struct StaticAssertTest {};
|
||||||
|
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// new/delete
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_NEW
|
||||||
|
///! customization point for global \c new
|
||||||
|
#define RAPIDJSON_NEW(x) new x
|
||||||
|
#endif
|
||||||
|
#ifndef RAPIDJSON_DELETE
|
||||||
|
///! customization point for global \c delete
|
||||||
|
#define RAPIDJSON_DELETE(x) delete x
|
||||||
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Allocators and Encodings
|
// Allocators and Encodings
|
||||||
|
|
||||||
#include "allocators.h"
|
#include "allocators.h"
|
||||||
#include "encodings.h"
|
#include "encodings.h"
|
||||||
|
|
||||||
//! main RapidJSON namespace
|
/*! \namespace rapidjson
|
||||||
namespace rapidjson {
|
\brief main RapidJSON namespace
|
||||||
|
\see RAPIDJSON_NAMESPACE
|
||||||
|
*/
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Stream
|
// Stream
|
||||||
|
@ -562,6 +680,6 @@ enum Type {
|
||||||
kNumberType = 6 //!< number
|
kNumberType = 6 //!< number
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_READER_H_
|
#ifndef RAPIDJSON_READER_H_
|
||||||
#define RAPIDJSON_READER_H_
|
#define RAPIDJSON_READER_H_
|
||||||
|
@ -26,8 +20,8 @@
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
#include "encodings.h"
|
#include "encodings.h"
|
||||||
#include "internal/meta.h"
|
#include "internal/meta.h"
|
||||||
#include "internal/pow10.h"
|
|
||||||
#include "internal/stack.h"
|
#include "internal/stack.h"
|
||||||
|
#include "internal/strtod.h"
|
||||||
|
|
||||||
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
|
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
@ -45,6 +39,17 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||||
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#define RAPIDJSON_NOTHING /* deliberately empty */
|
#define RAPIDJSON_NOTHING /* deliberately empty */
|
||||||
#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
|
#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
|
||||||
|
@ -116,20 +121,33 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||||
|
|
||||||
#include "error/error.h" // ParseErrorCode, ParseResult
|
#include "error/error.h" // ParseErrorCode, ParseResult
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ParseFlag
|
// ParseFlag
|
||||||
|
|
||||||
|
/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief User-defined kParseDefaultFlags definition.
|
||||||
|
|
||||||
|
User can define this as any \c ParseFlag combinations.
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||||
|
#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
|
||||||
|
#endif
|
||||||
|
|
||||||
//! Combination of parseFlags
|
//! Combination of parseFlags
|
||||||
/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
|
/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
|
||||||
*/
|
*/
|
||||||
enum ParseFlag {
|
enum ParseFlag {
|
||||||
kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer.
|
kParseNoFlags = 0, //!< No flags are set.
|
||||||
kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
|
kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
|
||||||
kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
|
kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
|
||||||
kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
|
kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
|
||||||
kParseStopWhenDoneFlag = 8 //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
|
kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
|
||||||
|
kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
|
||||||
|
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
|
||||||
|
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -244,27 +262,27 @@ void SkipWhitespace(InputStream& is) {
|
||||||
#ifdef RAPIDJSON_SSE42
|
#ifdef RAPIDJSON_SSE42
|
||||||
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
||||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// 16-byte align to the next boundary
|
// 16-byte align to the next boundary
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
||||||
while (p != nextAligned)
|
while (p != nextAligned)
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return 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_loadu_si128((const __m128i *)&whitespace[0]);
|
const __m128i w = _mm_loadu_si128(reinterpret_cast<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(reinterpret_cast<const __m128i *>(p));
|
||||||
const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
|
const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
|
||||||
if (r != 0) { // some of characters is non-whitespace
|
if (r != 0) { // some of characters is non-whitespace
|
||||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
@ -281,39 +299,39 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||||
|
|
||||||
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
||||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// 16-byte align to the next boundary
|
// 16-byte align to the next boundary
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
||||||
while (p != nextAligned)
|
while (p != nextAligned)
|
||||||
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// The rest of string
|
// The rest of string
|
||||||
static const char whitespaces[4][17] = {
|
static const char whitespaces[4][17] = {
|
||||||
" ",
|
" ",
|
||||||
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||||
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
|
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
|
||||||
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
|
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
|
||||||
|
|
||||||
const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
|
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
|
||||||
const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
|
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
|
||||||
const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
|
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
|
||||||
const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
|
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const __m128i s = _mm_load_si128((const __m128i *)p);
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
__m128i x = _mm_cmpeq_epi8(s, w0);
|
__m128i x = _mm_cmpeq_epi8(s, w0);
|
||||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
|
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
|
||||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
|
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
|
||||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
|
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
|
||||||
unsigned short r = (unsigned short)~_mm_movemask_epi8(x);
|
unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
|
||||||
if (r != 0) { // some of characters may be non-whitespace
|
if (r != 0) { // some of characters may be non-whitespace
|
||||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
@ -365,7 +383,7 @@ public:
|
||||||
typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
|
typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
|
||||||
|
|
||||||
//! Constructor.
|
//! Constructor.
|
||||||
/*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
|
/*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
|
||||||
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
|
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
|
||||||
*/
|
*/
|
||||||
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
|
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
|
||||||
|
@ -387,7 +405,8 @@ public:
|
||||||
|
|
||||||
ClearStackOnExit scope(*this);
|
ClearStackOnExit scope(*this);
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
||||||
|
|
||||||
if (is.Peek() == '\0') {
|
if (is.Peek() == '\0') {
|
||||||
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
|
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
|
||||||
|
@ -398,7 +417,8 @@ public:
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
||||||
|
|
||||||
if (!(parseFlags & kParseStopWhenDoneFlag)) {
|
if (!(parseFlags & kParseStopWhenDoneFlag)) {
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
||||||
|
|
||||||
if (is.Peek() != '\0') {
|
if (is.Peek() != '\0') {
|
||||||
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
|
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
|
||||||
|
@ -451,6 +471,40 @@ private:
|
||||||
ClearStackOnExit& operator=(const ClearStackOnExit&);
|
ClearStackOnExit& operator=(const ClearStackOnExit&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<unsigned parseFlags, typename InputStream>
|
||||||
|
void SkipWhitespaceAndComments(InputStream& is) {
|
||||||
|
SkipWhitespace(is);
|
||||||
|
|
||||||
|
if (parseFlags & kParseCommentsFlag) {
|
||||||
|
while (is.Peek() == '/') {
|
||||||
|
is.Take();
|
||||||
|
|
||||||
|
if (is.Peek() == '*') {
|
||||||
|
is.Take();
|
||||||
|
while (true) {
|
||||||
|
if (is.Peek() == '\0')
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
|
||||||
|
|
||||||
|
if (is.Take() == '*') {
|
||||||
|
if (is.Peek() == '\0')
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
|
||||||
|
|
||||||
|
if (is.Take() == '/')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (is.Peek() == '/') {
|
||||||
|
is.Take();
|
||||||
|
while (is.Peek() != '\0' && is.Take() != '\n') { }
|
||||||
|
} else {
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
|
||||||
|
}
|
||||||
|
|
||||||
|
SkipWhitespace(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse object: { string : value, ... }
|
// Parse object: { string : value, ... }
|
||||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseObject(InputStream& is, Handler& handler) {
|
void ParseObject(InputStream& is, Handler& handler) {
|
||||||
|
@ -460,7 +514,8 @@ private:
|
||||||
if (!handler.StartObject())
|
if (!handler.StartObject())
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
if (is.Peek() == '}') {
|
if (is.Peek() == '}') {
|
||||||
is.Take();
|
is.Take();
|
||||||
|
@ -476,28 +531,35 @@ private:
|
||||||
ParseString<parseFlags>(is, handler, true);
|
ParseString<parseFlags>(is, handler, true);
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
if (is.Take() != ':')
|
if (is.Take() != ':')
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
ParseValue<parseFlags>(is, handler);
|
ParseValue<parseFlags>(is, handler);
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
++memberCount;
|
++memberCount;
|
||||||
|
|
||||||
switch (is.Take()) {
|
switch (is.Take()) {
|
||||||
case ',': SkipWhitespace(is); break;
|
case ',':
|
||||||
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
break;
|
||||||
case '}':
|
case '}':
|
||||||
if (!handler.EndObject(memberCount))
|
if (!handler.EndObject(memberCount))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
else
|
return;
|
||||||
return;
|
default:
|
||||||
default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,7 +573,8 @@ private:
|
||||||
if (!handler.StartArray())
|
if (!handler.StartArray())
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
if (is.Peek() == ']') {
|
if (is.Peek() == ']') {
|
||||||
is.Take();
|
is.Take();
|
||||||
|
@ -525,16 +588,21 @@ private:
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
++elementCount;
|
++elementCount;
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
switch (is.Take()) {
|
switch (is.Take()) {
|
||||||
case ',': SkipWhitespace(is); break;
|
case ',':
|
||||||
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
break;
|
||||||
case ']':
|
case ']':
|
||||||
if (!handler.EndArray(elementCount))
|
if (!handler.EndArray(elementCount))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
else
|
return;
|
||||||
return;
|
default:
|
||||||
default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -600,21 +668,27 @@ private:
|
||||||
return codepoint;
|
return codepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharType>
|
||||||
class StackStream {
|
class StackStream {
|
||||||
public:
|
public:
|
||||||
typedef typename TargetEncoding::Ch Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
|
StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
|
||||||
RAPIDJSON_FORCEINLINE void Put(Ch c) {
|
RAPIDJSON_FORCEINLINE void Put(Ch c) {
|
||||||
*stack_.template Push<Ch>() = c;
|
*stack_.template Push<Ch>() = c;
|
||||||
++length_;
|
++length_;
|
||||||
}
|
}
|
||||||
internal::Stack<StackAllocator>& stack_;
|
size_t Length() const { return length_; }
|
||||||
SizeType length_;
|
Ch* Pop() {
|
||||||
|
return stack_.template Pop<Ch>(length_);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StackStream(const StackStream&);
|
StackStream(const StackStream&);
|
||||||
StackStream& operator=(const StackStream&);
|
StackStream& operator=(const StackStream&);
|
||||||
|
|
||||||
|
internal::Stack<StackAllocator>& stack_;
|
||||||
|
SizeType length_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse string and generate String event. Different code paths for kParseInsituFlag.
|
// Parse string and generate String event. Different code paths for kParseInsituFlag.
|
||||||
|
@ -630,15 +704,16 @@ private:
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
size_t length = s.PutEnd(head) - 1;
|
size_t length = s.PutEnd(head) - 1;
|
||||||
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
|
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
|
||||||
const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
|
const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
|
||||||
success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
|
success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StackStream stackStream(stack_);
|
StackStream<typename TargetEncoding::Ch> stackStream(stack_);
|
||||||
ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
|
ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
const typename TargetEncoding::Ch* const str = stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_);
|
SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
|
||||||
success = (isKey ? handler.Key(str, stackStream.length_ - 1, true) : handler.String(str, stackStream.length_ - 1, true));
|
const typename TargetEncoding::Ch* const str = stackStream.Pop();
|
||||||
|
success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
|
||||||
}
|
}
|
||||||
if (!success)
|
if (!success)
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
|
||||||
|
@ -668,16 +743,17 @@ private:
|
||||||
if (c == '\\') { // Escape
|
if (c == '\\') { // Escape
|
||||||
is.Take();
|
is.Take();
|
||||||
Ch e = is.Take();
|
Ch e = is.Take();
|
||||||
if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
|
if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[static_cast<unsigned char>(e)])
|
||||||
os.Put(escape[(unsigned char)e]);
|
os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
|
||||||
}
|
|
||||||
else if (e == 'u') { // Unicode
|
else if (e == 'u') { // Unicode
|
||||||
unsigned codepoint = ParseHex4(is);
|
unsigned codepoint = ParseHex4(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
|
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
|
||||||
// Handle UTF-16 surrogate pair
|
// Handle UTF-16 surrogate pair
|
||||||
if (is.Take() != '\\' || is.Take() != 'u')
|
if (is.Take() != '\\' || is.Take() != 'u')
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
||||||
unsigned codepoint2 = ParseHex4(is);
|
unsigned codepoint2 = ParseHex4(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
|
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
|
||||||
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
||||||
|
@ -694,7 +770,7 @@ private:
|
||||||
}
|
}
|
||||||
else if (c == '\0')
|
else if (c == '\0')
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
|
||||||
else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
else if (static_cast<unsigned>(c) < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
|
||||||
else {
|
else {
|
||||||
if (parseFlags & kParseValidateEncodingFlag ?
|
if (parseFlags & kParseValidateEncodingFlag ?
|
||||||
|
@ -705,22 +781,55 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double StrtodFastPath(double significand, int exp) {
|
template<typename InputStream, bool backup>
|
||||||
// Fast path only works on limited range of values.
|
class NumberStream;
|
||||||
// But for simplicity and performance, currently only implement this.
|
|
||||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
template<typename InputStream>
|
||||||
if (exp < -308)
|
class NumberStream<InputStream, false> {
|
||||||
return 0.0;
|
public:
|
||||||
else if (exp >= 0)
|
NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
|
||||||
return significand * internal::Pow10(exp);
|
~NumberStream() {}
|
||||||
else
|
|
||||||
return significand / internal::Pow10(-exp);
|
RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
|
||||||
}
|
RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
|
||||||
|
RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
|
||||||
|
size_t Tell() { return is.Tell(); }
|
||||||
|
size_t Length() { return 0; }
|
||||||
|
const char* Pop() { return 0; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NumberStream& operator=(const NumberStream&);
|
||||||
|
|
||||||
|
InputStream& is;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename InputStream>
|
||||||
|
class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
|
||||||
|
typedef NumberStream<InputStream, false> Base;
|
||||||
|
public:
|
||||||
|
NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
|
||||||
|
~NumberStream() {}
|
||||||
|
|
||||||
|
RAPIDJSON_FORCEINLINE Ch TakePush() {
|
||||||
|
stackStream.Put(static_cast<char>(Base::is.Peek()));
|
||||||
|
return Base::is.Take();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Length() { return stackStream.Length(); }
|
||||||
|
|
||||||
|
const char* Pop() {
|
||||||
|
stackStream.Put('\0');
|
||||||
|
return stackStream.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StackStream<char> stackStream;
|
||||||
|
};
|
||||||
|
|
||||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseNumber(InputStream& is, Handler& handler) {
|
void ParseNumber(InputStream& is, Handler& handler) {
|
||||||
internal::StreamLocalCopy<InputStream> copy(is);
|
internal::StreamLocalCopy<InputStream> copy(is);
|
||||||
InputStream& s(copy.s);
|
NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s);
|
||||||
|
|
||||||
// Parse minus
|
// Parse minus
|
||||||
bool minus = false;
|
bool minus = false;
|
||||||
|
@ -733,12 +842,13 @@ private:
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
uint64_t i64 = 0;
|
uint64_t i64 = 0;
|
||||||
bool use64bit = false;
|
bool use64bit = false;
|
||||||
|
int significandDigit = 0;
|
||||||
if (s.Peek() == '0') {
|
if (s.Peek() == '0') {
|
||||||
i = 0;
|
i = 0;
|
||||||
s.Take();
|
s.TakePush();
|
||||||
}
|
}
|
||||||
else if (s.Peek() >= '1' && s.Peek() <= '9') {
|
else if (s.Peek() >= '1' && s.Peek() <= '9') {
|
||||||
i = static_cast<unsigned>(s.Take() - '0');
|
i = static_cast<unsigned>(s.TakePush() - '0');
|
||||||
|
|
||||||
if (minus)
|
if (minus)
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
|
@ -749,7 +859,8 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i = i * 10 + static_cast<unsigned>(s.Take() - '0');
|
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||||
|
significandDigit++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
|
@ -760,35 +871,38 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i = i * 10 + static_cast<unsigned>(s.Take() - '0');
|
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||||
|
significandDigit++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||||
|
|
||||||
// Parse 64bit int
|
// Parse 64bit int
|
||||||
double d = 0.0;
|
|
||||||
bool useDouble = false;
|
bool useDouble = false;
|
||||||
|
double d = 0.0;
|
||||||
if (use64bit) {
|
if (use64bit) {
|
||||||
if (minus)
|
if (minus)
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
|
if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
|
||||||
if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
|
if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
|
||||||
d = (double)i64;
|
d = i64;
|
||||||
useDouble = true;
|
useDouble = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
|
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||||
|
significandDigit++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
|
if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
|
||||||
if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
|
if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
|
||||||
d = (double)i64;
|
d = i64;
|
||||||
useDouble = true;
|
useDouble = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
|
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||||
|
significandDigit++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,53 +911,64 @@ private:
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
|
if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
||||||
d = d * 10 + (s.Take() - '0');
|
d = d * 10 + (s.TakePush() - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse frac = decimal-point 1*DIGIT
|
// Parse frac = decimal-point 1*DIGIT
|
||||||
int expFrac = 0;
|
int expFrac = 0;
|
||||||
|
size_t decimalPosition;
|
||||||
if (s.Peek() == '.') {
|
if (s.Peek() == '.') {
|
||||||
s.Take();
|
s.Take();
|
||||||
|
decimalPosition = s.Length();
|
||||||
|
|
||||||
|
if (!(s.Peek() >= '0' && s.Peek() <= '9'))
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
|
||||||
|
|
||||||
#if RAPIDJSON_64BIT
|
|
||||||
// Use i64 to store significand in 64-bit architecture
|
|
||||||
if (!useDouble) {
|
if (!useDouble) {
|
||||||
|
#if RAPIDJSON_64BIT
|
||||||
|
// Use i64 to store significand in 64-bit architecture
|
||||||
if (!use64bit)
|
if (!use64bit)
|
||||||
i64 = i;
|
i64 = i;
|
||||||
|
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))
|
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
|
||||||
break;
|
break;
|
||||||
else {
|
else {
|
||||||
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
|
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
|
||||||
--expFrac;
|
--expFrac;
|
||||||
|
if (i64 != 0)
|
||||||
|
significandDigit++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d = (double)i64;
|
d = static_cast<double>(i64);
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
// Use double to store significand in 32-bit architecture
|
// Use double to store significand in 32-bit architecture
|
||||||
if (!useDouble)
|
d = static_cast<double>(use64bit ? i64 : i);
|
||||||
d = use64bit ? (double)i64 : (double)i;
|
|
||||||
#endif
|
#endif
|
||||||
useDouble = true;
|
useDouble = true;
|
||||||
|
}
|
||||||
|
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
d = d * 10 + (s.Take() - '0');
|
if (significandDigit < 17) {
|
||||||
--expFrac;
|
d = d * 10.0 + (s.TakePush() - '0');
|
||||||
|
--expFrac;
|
||||||
|
if (d > 0.0)
|
||||||
|
significandDigit++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.TakePush();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expFrac == 0)
|
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
decimalPosition = s.Length(); // decimal position at the end of integer.
|
||||||
|
|
||||||
// Parse exp = e [ minus / plus ] 1*DIGIT
|
// Parse exp = e [ minus / plus ] 1*DIGIT
|
||||||
int exp = 0;
|
int exp = 0;
|
||||||
if (s.Peek() == 'e' || s.Peek() == 'E') {
|
if (s.Peek() == 'e' || s.Peek() == 'E') {
|
||||||
if (!useDouble) {
|
if (!useDouble) {
|
||||||
d = use64bit ? (double)i64 : (double)i;
|
d = use64bit ? i64 : i;
|
||||||
useDouble = true;
|
useDouble = true;
|
||||||
}
|
}
|
||||||
s.Take();
|
s.Take();
|
||||||
|
@ -857,11 +982,23 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
exp = s.Take() - '0';
|
exp = static_cast<int>(s.Take() - '0');
|
||||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
if (expMinus) {
|
||||||
exp = exp * 10 + (s.Take() - '0');
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
|
exp = exp * 10 + static_cast<int>(s.Take() - '0');
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
if (exp >= 214748364) { // Issue #313: prevent overflow exponent
|
||||||
|
while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent
|
||||||
|
s.Take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // positive exp
|
||||||
|
int maxExp = 308 - expFrac;
|
||||||
|
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||||
|
exp = exp * 10 + static_cast<int>(s.Take() - '0');
|
||||||
|
if (exp > maxExp)
|
||||||
|
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -873,28 +1010,28 @@ private:
|
||||||
|
|
||||||
// Finish parsing, call event according to the type of number.
|
// Finish parsing, call event according to the type of number.
|
||||||
bool cont = true;
|
bool cont = true;
|
||||||
|
size_t length = s.Length();
|
||||||
|
const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
|
||||||
|
|
||||||
if (useDouble) {
|
if (useDouble) {
|
||||||
int expSum = exp + expFrac;
|
int p = exp + expFrac;
|
||||||
if (expSum < -308) {
|
if (parseFlags & kParseFullPrecisionFlag)
|
||||||
// Prevent expSum < -308, making Pow10(expSum) = 0
|
d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
|
||||||
d = StrtodFastPath(d, exp);
|
|
||||||
d = StrtodFastPath(d, expFrac);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
d = StrtodFastPath(d, expSum);
|
d = internal::StrtodNormalPrecision(d, p);
|
||||||
|
|
||||||
cont = handler.Double(minus ? -d : d);
|
cont = handler.Double(minus ? -d : d);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (use64bit) {
|
if (use64bit) {
|
||||||
if (minus)
|
if (minus)
|
||||||
cont = handler.Int64(-(int64_t)i64);
|
cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
|
||||||
else
|
else
|
||||||
cont = handler.Uint64(i64);
|
cont = handler.Uint64(i64);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (minus)
|
if (minus)
|
||||||
cont = handler.Int(-(int)i);
|
cont = handler.Int(static_cast<int32_t>(~i + 1));
|
||||||
else
|
else
|
||||||
cont = handler.Uint(i);
|
cont = handler.Uint(i);
|
||||||
}
|
}
|
||||||
|
@ -913,7 +1050,10 @@ private:
|
||||||
case '"': ParseString<parseFlags>(is, handler); break;
|
case '"': ParseString<parseFlags>(is, handler); break;
|
||||||
case '{': ParseObject<parseFlags>(is, handler); break;
|
case '{': ParseObject<parseFlags>(is, handler); break;
|
||||||
case '[': ParseArray <parseFlags>(is, handler); break;
|
case '[': ParseArray <parseFlags>(is, handler); break;
|
||||||
default : ParseNumber<parseFlags>(is, handler);
|
default :
|
||||||
|
ParseNumber<parseFlags>(is, handler);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,11 +1080,11 @@ private:
|
||||||
IterativeParsingArrayFinishState,
|
IterativeParsingArrayFinishState,
|
||||||
|
|
||||||
// Single value state
|
// Single value state
|
||||||
IterativeParsingValueState,
|
IterativeParsingValueState
|
||||||
|
|
||||||
cIterativeParsingStateCount
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
|
||||||
|
|
||||||
// Tokens
|
// Tokens
|
||||||
enum Token {
|
enum Token {
|
||||||
LeftBracketToken = 0,
|
LeftBracketToken = 0,
|
||||||
|
@ -986,8 +1126,8 @@ private:
|
||||||
#undef N16
|
#undef N16
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
if (sizeof(Ch) == 1 || unsigned(c) < 256)
|
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
|
||||||
return (Token)tokenMap[(unsigned char)c];
|
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
|
||||||
else
|
else
|
||||||
return NumberToken;
|
return NumberToken;
|
||||||
}
|
}
|
||||||
|
@ -1153,21 +1293,16 @@ private:
|
||||||
}
|
}
|
||||||
}; // End of G
|
}; // End of G
|
||||||
|
|
||||||
return (IterativeParsingState)G[state][token];
|
return static_cast<IterativeParsingState>(G[state][token]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
|
// Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
|
||||||
// May return a new state on state pop.
|
// May return a new state on state pop.
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template <unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
|
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
|
||||||
|
(void)token;
|
||||||
|
|
||||||
switch (dst) {
|
switch (dst) {
|
||||||
case IterativeParsingStartState:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
|
|
||||||
case IterativeParsingFinishState:
|
|
||||||
return dst;
|
|
||||||
|
|
||||||
case IterativeParsingErrorState:
|
case IterativeParsingErrorState:
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
|
@ -1206,12 +1341,9 @@ private:
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
case IterativeParsingKeyValueDelimiterState:
|
case IterativeParsingKeyValueDelimiterState:
|
||||||
if (token == ColonToken) {
|
RAPIDJSON_ASSERT(token == ColonToken);
|
||||||
is.Take();
|
is.Take();
|
||||||
return dst;
|
return dst;
|
||||||
}
|
|
||||||
else
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
|
|
||||||
case IterativeParsingMemberValueState:
|
case IterativeParsingMemberValueState:
|
||||||
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
||||||
|
@ -1286,17 +1418,25 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case IterativeParsingValueState:
|
default:
|
||||||
|
// This branch is for IterativeParsingValueState actually.
|
||||||
|
// Use `default:` rather than
|
||||||
|
// `case IterativeParsingValueState:` is for code coverage.
|
||||||
|
|
||||||
|
// The IterativeParsingStartState is not enumerated in this switch-case.
|
||||||
|
// It is impossible for that case. And it can be caught by following assertion.
|
||||||
|
|
||||||
|
// The IterativeParsingFinishState is not enumerated in this switch-case either.
|
||||||
|
// It is a "derivative" state which cannot triggered from Predict() directly.
|
||||||
|
// Therefore it cannot happen here. And it can be caught by following assertion.
|
||||||
|
RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
|
||||||
|
|
||||||
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
|
||||||
ParseValue<parseFlags>(is, handler);
|
ParseValue<parseFlags>(is, handler);
|
||||||
if (HasParseError()) {
|
if (HasParseError()) {
|
||||||
return IterativeParsingErrorState;
|
return IterativeParsingErrorState;
|
||||||
}
|
}
|
||||||
return IterativeParsingFinishState;
|
return IterativeParsingFinishState;
|
||||||
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return IterativeParsingErrorState;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,14 +1448,14 @@ 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()); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1325,7 +1465,8 @@ private:
|
||||||
ClearStackOnExit scope(*this);
|
ClearStackOnExit scope(*this);
|
||||||
IterativeParsingState state = IterativeParsingStartState;
|
IterativeParsingState state = IterativeParsingStartState;
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
||||||
while (is.Peek() != '\0') {
|
while (is.Peek() != '\0') {
|
||||||
Token t = Tokenize(is.Peek());
|
Token t = Tokenize(is.Peek());
|
||||||
IterativeParsingState n = Predict(state, t);
|
IterativeParsingState n = Predict(state, t);
|
||||||
|
@ -1342,7 +1483,8 @@ private:
|
||||||
if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
|
if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
SkipWhitespace(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the end of file.
|
// Handle the end of file.
|
||||||
|
@ -1360,7 +1502,16 @@ private:
|
||||||
//! Reader with UTF8 encoding and default allocator.
|
//! Reader with UTF8 encoding and default allocator.
|
||||||
typedef GenericReader<UTF8<>, UTF8<> > Reader;
|
typedef GenericReader<UTF8<>, UTF8<> > Reader;
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_STRINGBUFFER_H_
|
#ifndef RAPIDJSON_STRINGBUFFER_H_
|
||||||
#define RAPIDJSON_STRINGBUFFER_H_
|
#define RAPIDJSON_STRINGBUFFER_H_
|
||||||
|
|
||||||
#include "rapidjson.h"
|
#include "rapidjson.h"
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
#include <utility> // std::move
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "internal/stack.h"
|
#include "internal/stack.h"
|
||||||
|
|
||||||
namespace rapidjson {
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Represents an in-memory output stream.
|
//! Represents an in-memory output stream.
|
||||||
/*!
|
/*!
|
||||||
|
@ -33,11 +32,21 @@ namespace rapidjson {
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||||
struct GenericStringBuffer {
|
class GenericStringBuffer {
|
||||||
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
|
||||||
|
GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
|
||||||
|
if (&rhs != this)
|
||||||
|
stack_ = std::move(rhs.stack_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
||||||
void Flush() {}
|
void Flush() {}
|
||||||
|
|
||||||
|
@ -63,6 +72,11 @@ struct GenericStringBuffer {
|
||||||
|
|
||||||
static const size_t kDefaultCapacity = 256;
|
static const size_t kDefaultCapacity = 256;
|
||||||
mutable internal::Stack<Allocator> stack_;
|
mutable internal::Stack<Allocator> stack_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Prohibit copy constructor & assignment operator.
|
||||||
|
GenericStringBuffer(const GenericStringBuffer&);
|
||||||
|
GenericStringBuffer& operator=(const GenericStringBuffer&);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! String buffer with UTF8 encoding
|
//! String buffer with UTF8 encoding
|
||||||
|
@ -74,6 +88,6 @@ inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
|
||||||
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
|
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // RAPIDJSON_STRINGBUFFER_H_
|
#endif // RAPIDJSON_STRINGBUFFER_H_
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
// Copyright (C) 2011 Milo Yip
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
//
|
||||||
// The above copyright notice and this permission notice shall be included in
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
// all copies or substantial portions of the Software.
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// http://opensource.org/licenses/MIT
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
//
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// specific language governing permissions and limitations under the License.
|
||||||
// THE SOFTWARE.
|
|
||||||
|
|
||||||
#ifndef RAPIDJSON_WRITER_H_
|
#ifndef RAPIDJSON_WRITER_H_
|
||||||
#define RAPIDJSON_WRITER_H_
|
#define RAPIDJSON_WRITER_H_
|
||||||
|
@ -34,7 +28,12 @@ RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rapidjson {
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! JSON writer
|
//! JSON writer
|
||||||
/*! Writer implements the concept Handler.
|
/*! Writer implements the concept Handler.
|
||||||
|
@ -59,12 +58,14 @@ public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
/*! \param os Output stream.
|
/*! \param os Output stream.
|
||||||
\param allocator User supplied allocator. If it is null, it will create a private one.
|
\param stackAllocator User supplied allocator. If it is null, it will create a private one.
|
||||||
\param levelDepth Initial capacity of stack.
|
\param levelDepth Initial capacity of stack.
|
||||||
*/
|
*/
|
||||||
|
explicit
|
||||||
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||||
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
|
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
|
||||||
|
|
||||||
|
explicit
|
||||||
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||||
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
|
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
|
||||||
|
|
||||||
|
@ -125,6 +126,12 @@ public:
|
||||||
return WriteString(str, length);
|
return WriteString(str, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
bool String(const std::basic_string<Ch>& str) {
|
||||||
|
return String(str.data(), SizeType(str.size()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool StartObject() {
|
bool StartObject() {
|
||||||
Prefix(kObjectType);
|
Prefix(kObjectType);
|
||||||
new (level_stack_.template Push<Level>()) Level(false);
|
new (level_stack_.template Push<Level>()) Level(false);
|
||||||
|
@ -199,7 +206,7 @@ protected:
|
||||||
char buffer[11];
|
char buffer[11];
|
||||||
const char* end = internal::i32toa(i, buffer);
|
const char* end = internal::i32toa(i, buffer);
|
||||||
for (const char* p = buffer; p != end; ++p)
|
for (const char* p = buffer; p != end; ++p)
|
||||||
os_->Put(*p);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +214,7 @@ protected:
|
||||||
char buffer[10];
|
char buffer[10];
|
||||||
const char* end = internal::u32toa(u, buffer);
|
const char* end = internal::u32toa(u, buffer);
|
||||||
for (const char* p = buffer; p != end; ++p)
|
for (const char* p = buffer; p != end; ++p)
|
||||||
os_->Put(*p);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +222,7 @@ protected:
|
||||||
char buffer[21];
|
char buffer[21];
|
||||||
const char* end = internal::i64toa(i64, buffer);
|
const char* end = internal::i64toa(i64, buffer);
|
||||||
for (const char* p = buffer; p != end; ++p)
|
for (const char* p = buffer; p != end; ++p)
|
||||||
os_->Put(*p);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +230,7 @@ protected:
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
char* end = internal::u64toa(u64, buffer);
|
char* end = internal::u64toa(u64, buffer);
|
||||||
for (char* p = buffer; p != end; ++p)
|
for (char* p = buffer; p != end; ++p)
|
||||||
os_->Put(*p);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,12 +238,12 @@ protected:
|
||||||
char buffer[25];
|
char buffer[25];
|
||||||
char* end = internal::dtoa(d, buffer);
|
char* end = internal::dtoa(d, buffer);
|
||||||
for (char* p = buffer; p != end; ++p)
|
for (char* p = buffer; p != end; ++p)
|
||||||
os_->Put(*p);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteString(const Ch* str, SizeType length) {
|
bool WriteString(const Ch* str, SizeType length) {
|
||||||
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
static const char escape[256] = {
|
static const char escape[256] = {
|
||||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
@ -253,7 +260,7 @@ protected:
|
||||||
GenericStringStream<SourceEncoding> is(str);
|
GenericStringStream<SourceEncoding> is(str);
|
||||||
while (is.Tell() < length) {
|
while (is.Tell() < length) {
|
||||||
const Ch c = is.Peek();
|
const Ch c = is.Peek();
|
||||||
if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
|
if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
|
||||||
// Unicode escaping
|
// Unicode escaping
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
if (!SourceEncoding::Decode(is, &codepoint))
|
if (!SourceEncoding::Decode(is, &codepoint))
|
||||||
|
@ -266,7 +273,8 @@ protected:
|
||||||
os_->Put(hexDigits[(codepoint >> 4) & 15]);
|
os_->Put(hexDigits[(codepoint >> 4) & 15]);
|
||||||
os_->Put(hexDigits[(codepoint ) & 15]);
|
os_->Put(hexDigits[(codepoint ) & 15]);
|
||||||
}
|
}
|
||||||
else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) {
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||||
// Surrogate pair
|
// Surrogate pair
|
||||||
unsigned s = codepoint - 0x010000;
|
unsigned s = codepoint - 0x010000;
|
||||||
unsigned lead = (s >> 10) + 0xD800;
|
unsigned lead = (s >> 10) + 0xD800;
|
||||||
|
@ -282,22 +290,21 @@ protected:
|
||||||
os_->Put(hexDigits[(trail >> 4) & 15]);
|
os_->Put(hexDigits[(trail >> 4) & 15]);
|
||||||
os_->Put(hexDigits[(trail ) & 15]);
|
os_->Put(hexDigits[(trail ) & 15]);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false; // invalid code point
|
|
||||||
}
|
}
|
||||||
else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
|
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && escape[static_cast<unsigned char>(c)]) {
|
||||||
is.Take();
|
is.Take();
|
||||||
os_->Put('\\');
|
os_->Put('\\');
|
||||||
os_->Put(escape[(unsigned char)c]);
|
os_->Put(static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
|
||||||
if (escape[(unsigned char)c] == 'u') {
|
if (escape[static_cast<unsigned char>(c)] == 'u') {
|
||||||
os_->Put('0');
|
os_->Put('0');
|
||||||
os_->Put('0');
|
os_->Put('0');
|
||||||
os_->Put(hexDigits[(unsigned char)c >> 4]);
|
os_->Put(hexDigits[static_cast<unsigned char>(c) >> 4]);
|
||||||
os_->Put(hexDigits[(unsigned char)c & 0xF]);
|
os_->Put(hexDigits[static_cast<unsigned char>(c) & 0xF]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
|
if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
os_->Put('\"');
|
os_->Put('\"');
|
||||||
return true;
|
return true;
|
||||||
|
@ -344,7 +351,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +359,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +367,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +375,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,14 +383,18 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rapidjson
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||||
|
|
|
@ -894,7 +894,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
|
||||||
|
|
||||||
// The contents should be JSON if the wallet follows the new format.
|
// The contents should be JSON if the wallet follows the new format.
|
||||||
rapidjson::Document json;
|
rapidjson::Document json;
|
||||||
if (json.Parse(account_data.c_str(), keys_file_data.account_data.size()).HasParseError())
|
if (json.Parse(account_data.c_str()).HasParseError())
|
||||||
{
|
{
|
||||||
is_old_file_format = true;
|
is_old_file_format = true;
|
||||||
m_watch_only = false;
|
m_watch_only = false;
|
||||||
|
@ -972,7 +972,7 @@ bool wallet2::verify_password(const std::string& password) const
|
||||||
|
|
||||||
// The contents should be JSON if the wallet follows the new format.
|
// The contents should be JSON if the wallet follows the new format.
|
||||||
rapidjson::Document json;
|
rapidjson::Document json;
|
||||||
if (json.Parse(account_data.c_str(), keys_file_data.account_data.size()).HasParseError())
|
if (json.Parse(account_data.c_str()).HasParseError())
|
||||||
{
|
{
|
||||||
// old format before JSON wallet key file format
|
// old format before JSON wallet key file format
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue