mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-02-03 05:14:44 +01:00
fixes
This commit is contained in:
parent
07294034f6
commit
db8f736d58
@ -96,7 +96,7 @@ public:
|
|||||||
}
|
}
|
||||||
return RAPIDJSON_REALLOC(originalPtr, newSize);
|
return RAPIDJSON_REALLOC(originalPtr, newSize);
|
||||||
}
|
}
|
||||||
static void Free(void* ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
|
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
|
||||||
|
|
||||||
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
|
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
|
||||||
return true;
|
return true;
|
||||||
@ -133,11 +133,11 @@ class MemoryPoolAllocator {
|
|||||||
struct ChunkHeader {
|
struct ChunkHeader {
|
||||||
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||||
size_t size; //!< Current size of allocated memory in bytes.
|
size_t size; //!< Current size of allocated memory in bytes.
|
||||||
ChunkHeader* next; //!< Next chunk in the linked list.
|
ChunkHeader *next; //!< Next chunk in the linked list.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SharedData {
|
struct SharedData {
|
||||||
ChunkHeader* chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
||||||
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
|
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
|
||||||
size_t refcount;
|
size_t refcount;
|
||||||
bool ownBuffer;
|
bool ownBuffer;
|
||||||
@ -146,10 +146,12 @@ class MemoryPoolAllocator {
|
|||||||
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
|
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
|
||||||
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
|
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
|
||||||
|
|
||||||
static inline ChunkHeader* GetChunkHead(SharedData* shared) {
|
static inline ChunkHeader *GetChunkHead(SharedData *shared)
|
||||||
|
{
|
||||||
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
|
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
|
||||||
}
|
}
|
||||||
static inline uint8_t* GetChunkBuffer(SharedData* shared) {
|
static inline uint8_t *GetChunkBuffer(SharedData *shared)
|
||||||
|
{
|
||||||
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
|
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,9 +165,12 @@ public:
|
|||||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||||
\param baseAllocator The allocator for allocating memory chunks.
|
\param baseAllocator The allocator for allocating memory chunks.
|
||||||
*/
|
*/
|
||||||
explicit MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize),
|
explicit
|
||||||
|
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||||
|
chunk_capacity_(chunkSize),
|
||||||
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
|
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
|
||||||
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) {
|
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(baseAllocator_ != 0);
|
RAPIDJSON_ASSERT(baseAllocator_ != 0);
|
||||||
RAPIDJSON_ASSERT(shared_ != 0);
|
RAPIDJSON_ASSERT(shared_ != 0);
|
||||||
if (baseAllocator) {
|
if (baseAllocator) {
|
||||||
@ -192,9 +197,11 @@ public:
|
|||||||
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||||
\param baseAllocator The allocator for allocating memory chunks.
|
\param baseAllocator The allocator for allocating memory chunks.
|
||||||
*/
|
*/
|
||||||
MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize),
|
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||||
|
chunk_capacity_(chunkSize),
|
||||||
baseAllocator_(baseAllocator),
|
baseAllocator_(baseAllocator),
|
||||||
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size))) {
|
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
|
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
|
||||||
shared_->chunkHead = GetChunkHead(shared_);
|
shared_->chunkHead = GetChunkHead(shared_);
|
||||||
shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
|
shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
|
||||||
@ -205,13 +212,16 @@ public:
|
|||||||
shared_->refcount = 1;
|
shared_->refcount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_),
|
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
|
chunk_capacity_(rhs.chunk_capacity_),
|
||||||
baseAllocator_(rhs.baseAllocator_),
|
baseAllocator_(rhs.baseAllocator_),
|
||||||
shared_(rhs.shared_) {
|
shared_(rhs.shared_)
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||||
++shared_->refcount;
|
++shared_->refcount;
|
||||||
}
|
}
|
||||||
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT {
|
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||||
++rhs.shared_->refcount;
|
++rhs.shared_->refcount;
|
||||||
this->~MemoryPoolAllocator();
|
this->~MemoryPoolAllocator();
|
||||||
@ -222,13 +232,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_),
|
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
|
chunk_capacity_(rhs.chunk_capacity_),
|
||||||
baseAllocator_(rhs.baseAllocator_),
|
baseAllocator_(rhs.baseAllocator_),
|
||||||
shared_(rhs.shared_) {
|
shared_(rhs.shared_)
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||||
rhs.shared_ = 0;
|
rhs.shared_ = 0;
|
||||||
}
|
}
|
||||||
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT {
|
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||||
this->~MemoryPoolAllocator();
|
this->~MemoryPoolAllocator();
|
||||||
baseAllocator_ = rhs.baseAllocator_;
|
baseAllocator_ = rhs.baseAllocator_;
|
||||||
@ -252,7 +265,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Clear();
|
Clear();
|
||||||
BaseAllocator* a = shared_->ownBaseAllocator;
|
BaseAllocator *a = shared_->ownBaseAllocator;
|
||||||
if (shared_->ownBuffer) {
|
if (shared_->ownBuffer) {
|
||||||
baseAllocator_->Free(shared_);
|
baseAllocator_->Free(shared_);
|
||||||
}
|
}
|
||||||
@ -314,7 +327,7 @@ public:
|
|||||||
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
void* buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
|
void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
|
||||||
shared_->chunkHead->size += size;
|
shared_->chunkHead->size += size;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@ -355,7 +368,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Frees a memory block (concept Allocator)
|
//! Frees a memory block (concept Allocator)
|
||||||
static void Free(void* ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
|
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
|
||||||
|
|
||||||
//! Compare (equality) with another MemoryPoolAllocator
|
//! Compare (equality) with another MemoryPoolAllocator
|
||||||
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
|
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
|
||||||
@ -387,7 +400,8 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* AlignBuffer(void* buf, size_t& size) {
|
static inline void* AlignBuffer(void* buf, size_t &size)
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
|
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
|
||||||
const uintptr_t mask = sizeof(void*) - 1;
|
const uintptr_t mask = sizeof(void*) - 1;
|
||||||
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
|
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
|
||||||
@ -402,29 +416,36 @@ private:
|
|||||||
|
|
||||||
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
|
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
|
||||||
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
|
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
|
||||||
SharedData* shared_; //!< The shared data of the allocator
|
SharedData *shared_; //!< The shared data of the allocator
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template <typename, typename = void>
|
template<typename, typename = void>
|
||||||
struct IsRefCounted : public FalseType {};
|
struct IsRefCounted :
|
||||||
template <typename T>
|
public FalseType
|
||||||
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : public TrueType {};
|
{ };
|
||||||
|
template<typename T>
|
||||||
|
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
|
||||||
|
public TrueType
|
||||||
|
{ };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename A>
|
template<typename T, typename A>
|
||||||
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) {
|
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
|
||||||
|
{
|
||||||
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T));
|
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T));
|
||||||
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
|
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename A>
|
template<typename T, typename A>
|
||||||
inline T* Malloc(A& a, size_t n = 1) {
|
inline T *Malloc(A& a, size_t n = 1)
|
||||||
|
{
|
||||||
return Realloc<T, A>(a, NULL, 0, n);
|
return Realloc<T, A>(a, NULL, 0, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename A>
|
template<typename T, typename A>
|
||||||
inline void Free(A& a, T* p, size_t n = 1) {
|
inline void Free(A& a, T *p, size_t n = 1)
|
||||||
|
{
|
||||||
static_cast<void>(Realloc<T, A>(a, p, n, 0));
|
static_cast<void>(Realloc<T, A>(a, p, n, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +455,9 @@ RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename BaseAllocator = CrtAllocator>
|
template <typename T, typename BaseAllocator = CrtAllocator>
|
||||||
class StdAllocator : public std::allocator<T> {
|
class StdAllocator :
|
||||||
|
public std::allocator<T>
|
||||||
|
{
|
||||||
typedef std::allocator<T> allocator_type;
|
typedef std::allocator<T> allocator_type;
|
||||||
#if RAPIDJSON_HAS_CXX11
|
#if RAPIDJSON_HAS_CXX11
|
||||||
typedef std::allocator_traits<allocator_type> traits_type;
|
typedef std::allocator_traits<allocator_type> traits_type;
|
||||||
@ -445,19 +468,27 @@ class StdAllocator : public std::allocator<T> {
|
|||||||
public:
|
public:
|
||||||
typedef BaseAllocator BaseAllocatorType;
|
typedef BaseAllocator BaseAllocatorType;
|
||||||
|
|
||||||
StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(),
|
StdAllocator() RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_() {}
|
allocator_type(),
|
||||||
|
baseAllocator_()
|
||||||
|
{ }
|
||||||
|
|
||||||
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
|
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(rhs.baseAllocator_) {}
|
allocator_type(rhs),
|
||||||
|
baseAllocator_(rhs.baseAllocator_)
|
||||||
|
{ }
|
||||||
|
|
||||||
template <typename U>
|
template<typename U>
|
||||||
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
|
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(rhs.baseAllocator_) {}
|
allocator_type(rhs),
|
||||||
|
baseAllocator_(rhs.baseAllocator_)
|
||||||
|
{ }
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : allocator_type(std::move(rhs)),
|
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(std::move(rhs.baseAllocator_)) {}
|
allocator_type(std::move(rhs)),
|
||||||
|
baseAllocator_(std::move(rhs.baseAllocator_))
|
||||||
|
{ }
|
||||||
#endif
|
#endif
|
||||||
#if RAPIDJSON_HAS_CXX11
|
#if RAPIDJSON_HAS_CXX11
|
||||||
using propagate_on_container_move_assignment = std::true_type;
|
using propagate_on_container_move_assignment = std::true_type;
|
||||||
@ -465,12 +496,15 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* implicit */
|
/* implicit */
|
||||||
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(),
|
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(allocator) {}
|
allocator_type(),
|
||||||
|
baseAllocator_(allocator)
|
||||||
|
{ }
|
||||||
|
|
||||||
~StdAllocator() RAPIDJSON_NOEXCEPT {}
|
~StdAllocator() RAPIDJSON_NOEXCEPT
|
||||||
|
{ }
|
||||||
|
|
||||||
template <typename U>
|
template<typename U>
|
||||||
struct rebind {
|
struct rebind {
|
||||||
typedef StdAllocator<U, BaseAllocator> other;
|
typedef StdAllocator<U, BaseAllocator> other;
|
||||||
};
|
};
|
||||||
@ -484,25 +518,30 @@ public:
|
|||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11
|
#if RAPIDJSON_HAS_CXX11
|
||||||
|
|
||||||
typedef typename std::add_lvalue_reference<value_type>::type& reference;
|
typedef typename std::add_lvalue_reference<value_type>::type &reference;
|
||||||
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type& const_reference;
|
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
|
||||||
|
|
||||||
pointer address(reference r) const RAPIDJSON_NOEXCEPT {
|
pointer address(reference r) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return std::addressof(r);
|
return std::addressof(r);
|
||||||
}
|
}
|
||||||
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT {
|
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return std::addressof(r);
|
return std::addressof(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type max_size() const RAPIDJSON_NOEXCEPT {
|
size_type max_size() const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return traits_type::max_size(*this);
|
return traits_type::max_size(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename ...Args>
|
||||||
void construct(pointer p, Args&&... args) {
|
void construct(pointer p, Args&&... args)
|
||||||
|
{
|
||||||
traits_type::construct(*this, p, std::forward<Args>(args)...);
|
traits_type::construct(*this, p, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
void destroy(pointer p) {
|
void destroy(pointer p)
|
||||||
|
{
|
||||||
traits_type::destroy(*this, p);
|
traits_type::destroy(*this, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,39 +550,48 @@ public:
|
|||||||
typedef typename allocator_type::reference reference;
|
typedef typename allocator_type::reference reference;
|
||||||
typedef typename allocator_type::const_reference const_reference;
|
typedef typename allocator_type::const_reference const_reference;
|
||||||
|
|
||||||
pointer address(reference r) const RAPIDJSON_NOEXCEPT {
|
pointer address(reference r) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return allocator_type::address(r);
|
return allocator_type::address(r);
|
||||||
}
|
}
|
||||||
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT {
|
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return allocator_type::address(r);
|
return allocator_type::address(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type max_size() const RAPIDJSON_NOEXCEPT {
|
size_type max_size() const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return allocator_type::max_size();
|
return allocator_type::max_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void construct(pointer p, const_reference r) {
|
void construct(pointer p, const_reference r)
|
||||||
|
{
|
||||||
allocator_type::construct(p, r);
|
allocator_type::construct(p, r);
|
||||||
}
|
}
|
||||||
void destroy(pointer p) {
|
void destroy(pointer p)
|
||||||
|
{
|
||||||
allocator_type::destroy(p);
|
allocator_type::destroy(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !RAPIDJSON_HAS_CXX11
|
#endif // !RAPIDJSON_HAS_CXX11
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
U* allocate(size_type n = 1, const void* = 0) {
|
U* allocate(size_type n = 1, const void* = 0)
|
||||||
|
{
|
||||||
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
|
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
|
||||||
}
|
}
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void deallocate(U* p, size_type n = 1) {
|
void deallocate(U* p, size_type n = 1)
|
||||||
|
{
|
||||||
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
|
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer allocate(size_type n = 1, const void* = 0) {
|
pointer allocate(size_type n = 1, const void* = 0)
|
||||||
|
{
|
||||||
return allocate<value_type>(n);
|
return allocate<value_type>(n);
|
||||||
}
|
}
|
||||||
void deallocate(pointer p, size_type n = 1) {
|
void deallocate(pointer p, size_type n = 1)
|
||||||
|
{
|
||||||
deallocate<value_type>(p, n);
|
deallocate<value_type>(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,25 +599,30 @@ public:
|
|||||||
using is_always_equal = std::is_empty<BaseAllocator>;
|
using is_always_equal = std::is_empty<BaseAllocator>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename U>
|
template<typename U>
|
||||||
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT {
|
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return baseAllocator_ == rhs.baseAllocator_;
|
return baseAllocator_ == rhs.baseAllocator_;
|
||||||
}
|
}
|
||||||
template <typename U>
|
template<typename U>
|
||||||
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT {
|
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! rapidjson Allocator concept
|
//! rapidjson Allocator concept
|
||||||
static const bool kNeedFree = BaseAllocator::kNeedFree;
|
static const bool kNeedFree = BaseAllocator::kNeedFree;
|
||||||
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
|
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size)
|
||||||
|
{
|
||||||
return baseAllocator_.Malloc(size);
|
return baseAllocator_.Malloc(size);
|
||||||
}
|
}
|
||||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
|
||||||
|
{
|
||||||
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
|
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
|
||||||
}
|
}
|
||||||
static void Free(void* ptr) RAPIDJSON_NOEXCEPT {
|
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
BaseAllocator::Free(ptr);
|
BaseAllocator::Free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,29 +635,40 @@ private:
|
|||||||
|
|
||||||
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
|
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
|
||||||
template <typename BaseAllocator>
|
template <typename BaseAllocator>
|
||||||
class StdAllocator<void, BaseAllocator> : public std::allocator<void> {
|
class StdAllocator<void, BaseAllocator> :
|
||||||
|
public std::allocator<void>
|
||||||
|
{
|
||||||
typedef std::allocator<void> allocator_type;
|
typedef std::allocator<void> allocator_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef BaseAllocator BaseAllocatorType;
|
typedef BaseAllocator BaseAllocatorType;
|
||||||
|
|
||||||
StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(),
|
StdAllocator() RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_() {}
|
allocator_type(),
|
||||||
|
baseAllocator_()
|
||||||
|
{ }
|
||||||
|
|
||||||
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
|
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(rhs.baseAllocator_) {}
|
allocator_type(rhs),
|
||||||
|
baseAllocator_(rhs.baseAllocator_)
|
||||||
|
{ }
|
||||||
|
|
||||||
template <typename U>
|
template<typename U>
|
||||||
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
|
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(rhs.baseAllocator_) {}
|
allocator_type(rhs),
|
||||||
|
baseAllocator_(rhs.baseAllocator_)
|
||||||
|
{ }
|
||||||
|
|
||||||
/* implicit */
|
/* implicit */
|
||||||
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(),
|
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
|
||||||
baseAllocator_(allocator) {}
|
allocator_type(),
|
||||||
|
baseAllocator_(allocator)
|
||||||
|
{ }
|
||||||
|
|
||||||
~StdAllocator() RAPIDJSON_NOEXCEPT {}
|
~StdAllocator() RAPIDJSON_NOEXCEPT
|
||||||
|
{ }
|
||||||
|
|
||||||
template <typename U>
|
template<typename U>
|
||||||
struct rebind {
|
struct rebind {
|
||||||
typedef StdAllocator<U, BaseAllocator> other;
|
typedef StdAllocator<U, BaseAllocator> other;
|
||||||
};
|
};
|
||||||
|
@ -35,22 +35,22 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
/*!
|
/*!
|
||||||
\tparam InputStream Any stream that implements Stream Concept
|
\tparam InputStream Any stream that implements Stream Concept
|
||||||
*/
|
*/
|
||||||
template <typename InputStream, typename Encoding = UTF8<>>
|
template <typename InputStream, typename Encoding = UTF8<> >
|
||||||
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
|
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
CursorStreamWrapper(InputStream& is) : GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
|
CursorStreamWrapper(InputStream& is):
|
||||||
|
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
|
||||||
|
|
||||||
// counting line and column number
|
// counting line and column number
|
||||||
Ch Take() {
|
Ch Take() {
|
||||||
Ch ch = this->is_.Take();
|
Ch ch = this->is_.Take();
|
||||||
if (ch == '\n') {
|
if(ch == '\n') {
|
||||||
line_++;
|
line_ ++;
|
||||||
col_ = 0;
|
col_ = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
col_ ++;
|
||||||
col_++;
|
|
||||||
}
|
}
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,6 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
template <typename Encoding, typename InputByteStream>
|
template <typename Encoding, typename InputByteStream>
|
||||||
class EncodedInputStream {
|
class EncodedInputStream {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
@ -47,24 +46,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ch Peek() const { return current_; }
|
Ch Peek() const { return current_; }
|
||||||
Ch Take() {
|
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
|
||||||
Ch c = current_;
|
|
||||||
current_ = Encoding::Take(is_);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
size_t Tell() const { return is_.Tell(); }
|
size_t Tell() const { return is_.Tell(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncodedInputStream(const EncodedInputStream&);
|
EncodedInputStream(const EncodedInputStream&);
|
||||||
@ -110,7 +99,6 @@ private:
|
|||||||
template <typename Encoding, typename OutputByteStream>
|
template <typename Encoding, typename OutputByteStream>
|
||||||
class EncodedOutputStream {
|
class EncodedOutputStream {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
@ -123,26 +111,11 @@ public:
|
|||||||
void Flush() { os_.Flush(); }
|
void Flush() { os_.Flush(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const {
|
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
RAPIDJSON_ASSERT(false);
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
return 0;
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
}
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
Ch Take() {
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t Tell() const {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Ch* PutBegin() {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncodedOutputStream(const EncodedOutputStream&);
|
EncodedOutputStream(const EncodedOutputStream&);
|
||||||
@ -161,7 +134,6 @@ private:
|
|||||||
template <typename CharType, typename InputByteStream>
|
template <typename CharType, typename InputByteStream>
|
||||||
class AutoUTFInputStream {
|
class AutoUTFInputStream {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
@ -182,24 +154,14 @@ public:
|
|||||||
bool HasBOM() const { return hasBOM_; }
|
bool HasBOM() const { return hasBOM_; }
|
||||||
|
|
||||||
Ch Peek() const { return current_; }
|
Ch Peek() const { return current_; }
|
||||||
Ch Take() {
|
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
|
||||||
Ch c = current_;
|
|
||||||
current_ = takeFunc_(*is_);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
size_t Tell() const { return is_->Tell(); }
|
size_t Tell() const { return is_->Tell(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AutoUTFInputStream(const AutoUTFInputStream&);
|
AutoUTFInputStream(const AutoUTFInputStream&);
|
||||||
@ -214,47 +176,17 @@ private:
|
|||||||
// FF FE UTF-16LE
|
// FF FE UTF-16LE
|
||||||
// EF BB BF UTF-8
|
// EF BB BF UTF-8
|
||||||
|
|
||||||
const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4());
|
const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
|
||||||
if (!c)
|
if (!c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned bom = static_cast<unsigned>(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) {
|
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
|
||||||
type_ = kUTF32BE;
|
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
|
||||||
hasBOM_ = true;
|
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
|
||||||
is_->Take();
|
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
|
||||||
is_->Take();
|
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); 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 & 0xFFFF) == 0xFFFE) {
|
|
||||||
type_ = kUTF16BE;
|
|
||||||
hasBOM_ = true;
|
|
||||||
is_->Take();
|
|
||||||
is_->Take();
|
|
||||||
}
|
|
||||||
else if ((bom & 0xFFFF) == 0xFEFF) {
|
|
||||||
type_ = kUTF16LE;
|
|
||||||
hasBOM_ = true;
|
|
||||||
is_->Take();
|
|
||||||
is_->Take();
|
|
||||||
}
|
|
||||||
else if ((bom & 0xFFFFFF) == 0xBFBBEF) {
|
|
||||||
type_ = kUTF8;
|
|
||||||
hasBOM_ = true;
|
|
||||||
is_->Take();
|
|
||||||
is_->Take();
|
|
||||||
is_->Take();
|
|
||||||
}
|
|
||||||
|
|
||||||
// RFC 4627: Section 3
|
// RFC 4627: Section 3
|
||||||
// "Since the first two characters of a JSON text will always be ASCII
|
// "Since the first two characters of a JSON text will always be ASCII
|
||||||
@ -270,23 +202,12 @@ private:
|
|||||||
if (!hasBOM_) {
|
if (!hasBOM_) {
|
||||||
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||||
switch (pattern) {
|
switch (pattern) {
|
||||||
case 0x08:
|
case 0x08: type_ = kUTF32BE; break;
|
||||||
type_ = kUTF32BE;
|
case 0x0A: type_ = kUTF16BE; break;
|
||||||
break;
|
case 0x01: type_ = kUTF32LE; break;
|
||||||
case 0x0A:
|
case 0x05: type_ = kUTF16LE; break;
|
||||||
type_ = kUTF16BE;
|
case 0x0F: type_ = kUTF8; break;
|
||||||
break;
|
default: break; // Use type defined by user.
|
||||||
case 0x01:
|
|
||||||
type_ = kUTF32LE;
|
|
||||||
break;
|
|
||||||
case 0x05:
|
|
||||||
type_ = kUTF16LE;
|
|
||||||
break;
|
|
||||||
case 0x0F:
|
|
||||||
type_ = kUTF8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; // Use type defined by user.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +232,6 @@ private:
|
|||||||
template <typename CharType, typename OutputByteStream>
|
template <typename CharType, typename OutputByteStream>
|
||||||
class AutoUTFOutputStream {
|
class AutoUTFOutputStream {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
@ -341,26 +261,11 @@ public:
|
|||||||
void Flush() { os_->Flush(); }
|
void Flush() { os_->Flush(); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const {
|
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
RAPIDJSON_ASSERT(false);
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
return 0;
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
}
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
Ch Take() {
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t Tell() const {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Ch* PutBegin() {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AutoUTFOutputStream(const AutoUTFOutputStream&);
|
AutoUTFOutputStream(const AutoUTFOutputStream&);
|
||||||
|
@ -92,13 +92,13 @@ concept Encoding {
|
|||||||
\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
|
\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
|
||||||
\note implements Encoding concept
|
\note implements Encoding concept
|
||||||
*/
|
*/
|
||||||
template <typename CharType = char>
|
template<typename CharType = char>
|
||||||
struct UTF8 {
|
struct UTF8 {
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
if (codepoint <= 0x7F)
|
if (codepoint <= 0x7F)
|
||||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||||
@ -120,7 +120,7 @@ struct UTF8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
if (codepoint <= 0x7F)
|
if (codepoint <= 0x7F)
|
||||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||||
@ -144,13 +144,9 @@ struct UTF8 {
|
|||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
#define RAPIDJSON_COPY() \
|
#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||||
c = is.Take(); \
|
|
||||||
*codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
|
||||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define RAPIDJSON_TAIL() \
|
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
||||||
RAPIDJSON_COPY(); \
|
|
||||||
RAPIDJSON_TRANS(0x70)
|
|
||||||
typename InputStream::Ch c = is.Take();
|
typename InputStream::Ch c = is.Take();
|
||||||
if (!(c & 0x80)) {
|
if (!(c & 0x80)) {
|
||||||
*codepoint = static_cast<unsigned char>(c);
|
*codepoint = static_cast<unsigned char>(c);
|
||||||
@ -160,48 +156,19 @@ struct UTF8 {
|
|||||||
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
||||||
if (type >= 32) {
|
if (type >= 32) {
|
||||||
*codepoint = 0;
|
*codepoint = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
|
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
|
||||||
}
|
}
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 2:
|
case 2: RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
return result;
|
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
||||||
case 3:
|
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
||||||
return result;
|
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
case 4:
|
default: return false;
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x50);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 5:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x10);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 6:
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 10:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x20);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 11:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x60);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
#undef RAPIDJSON_COPY
|
#undef RAPIDJSON_COPY
|
||||||
#undef RAPIDJSON_TRANS
|
#undef RAPIDJSON_TRANS
|
||||||
@ -212,9 +179,7 @@ struct UTF8 {
|
|||||||
static bool Validate(InputStream& is, OutputStream& os) {
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
#define RAPIDJSON_COPY() os.Put(c = is.Take())
|
#define RAPIDJSON_COPY() os.Put(c = is.Take())
|
||||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define RAPIDJSON_TAIL() \
|
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
||||||
RAPIDJSON_COPY(); \
|
|
||||||
RAPIDJSON_TRANS(0x70)
|
|
||||||
Ch c;
|
Ch c;
|
||||||
RAPIDJSON_COPY();
|
RAPIDJSON_COPY();
|
||||||
if (!(c & 0x80))
|
if (!(c & 0x80))
|
||||||
@ -222,42 +187,14 @@ struct UTF8 {
|
|||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (GetRange(static_cast<unsigned char>(c))) {
|
switch (GetRange(static_cast<unsigned char>(c))) {
|
||||||
case 2:
|
case 2: RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
return result;
|
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
||||||
case 3:
|
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
RAPIDJSON_TAIL();
|
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
||||||
return result;
|
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||||
case 4:
|
default: return false;
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x50);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 5:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x10);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 6:
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 10:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x20);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
case 11:
|
|
||||||
RAPIDJSON_COPY();
|
|
||||||
RAPIDJSON_TRANS(0x60);
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
RAPIDJSON_TAIL();
|
|
||||||
return result;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
#undef RAPIDJSON_COPY
|
#undef RAPIDJSON_COPY
|
||||||
#undef RAPIDJSON_TRANS
|
#undef RAPIDJSON_TRANS
|
||||||
@ -268,262 +205,16 @@ struct UTF8 {
|
|||||||
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||||
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
|
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
|
||||||
static const unsigned char type[] = {
|
static const unsigned char type[] = {
|
||||||
0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,
|
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||||
0,
|
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
|
||||||
0,
|
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||||
0,
|
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||||
0,
|
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||||
0,
|
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x10,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x40,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
0x20,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
10,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
11,
|
|
||||||
6,
|
|
||||||
6,
|
|
||||||
6,
|
|
||||||
5,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
};
|
};
|
||||||
return type[c];
|
return type[c];
|
||||||
}
|
}
|
||||||
@ -574,14 +265,14 @@ struct UTF8 {
|
|||||||
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
||||||
For streaming, use UTF16LE and UTF16BE, which handle endianness.
|
For streaming, use UTF16LE and UTF16BE, which handle endianness.
|
||||||
*/
|
*/
|
||||||
template <typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16 {
|
struct UTF16 {
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||||
if (codepoint <= 0xFFFF) {
|
if (codepoint <= 0xFFFF) {
|
||||||
@ -597,7 +288,7 @@ struct UTF16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||||
if (codepoint <= 0xFFFF) {
|
if (codepoint <= 0xFFFF) {
|
||||||
@ -647,7 +338,7 @@ struct UTF16 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! UTF-16 little endian encoding.
|
//! UTF-16 little endian encoding.
|
||||||
template <typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16LE : UTF16<CharType> {
|
struct UTF16LE : UTF16<CharType> {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
@ -680,7 +371,7 @@ struct UTF16LE : UTF16<CharType> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! UTF-16 big endian encoding.
|
//! UTF-16 big endian encoding.
|
||||||
template <typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16BE : UTF16<CharType> {
|
struct UTF16BE : UTF16<CharType> {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
@ -723,21 +414,21 @@ struct UTF16BE : UTF16<CharType> {
|
|||||||
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
||||||
For streaming, use UTF32LE and UTF32BE, which handle endianness.
|
For streaming, use UTF32LE and UTF32BE, which handle endianness.
|
||||||
*/
|
*/
|
||||||
template <typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32 {
|
struct UTF32 {
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
os.Put(codepoint);
|
os.Put(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
@ -762,7 +453,7 @@ struct UTF32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! UTF-32 little endian enocoding.
|
//! UTF-32 little endian enocoding.
|
||||||
template <typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32LE : UTF32<CharType> {
|
struct UTF32LE : UTF32<CharType> {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
@ -801,7 +492,7 @@ struct UTF32LE : UTF32<CharType> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! UTF-32 big endian encoding.
|
//! UTF-32 big endian encoding.
|
||||||
template <typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32BE : UTF32<CharType> {
|
struct UTF32BE : UTF32<CharType> {
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
@ -847,19 +538,19 @@ struct UTF32BE : UTF32<CharType> {
|
|||||||
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
|
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
|
||||||
\note implements Encoding concept
|
\note implements Encoding concept
|
||||||
*/
|
*/
|
||||||
template <typename CharType = char>
|
template<typename CharType = char>
|
||||||
struct ASCII {
|
struct ASCII {
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
enum { supportUnicode = 0 };
|
enum { supportUnicode = 0 };
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||||
@ -920,7 +611,7 @@ enum UTFType {
|
|||||||
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
|
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
|
||||||
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
|
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
|
||||||
*/
|
*/
|
||||||
template <typename CharType>
|
template<typename CharType>
|
||||||
struct AutoUTF {
|
struct AutoUTF {
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
@ -928,14 +619,14 @@ struct AutoUTF {
|
|||||||
|
|
||||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
|
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||||
(*f[os.GetType()])(os, codepoint);
|
(*f[os.GetType()])(os, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||||
@ -963,10 +654,10 @@ struct AutoUTF {
|
|||||||
// Transcoder
|
// Transcoder
|
||||||
|
|
||||||
//! Encoding conversion.
|
//! Encoding conversion.
|
||||||
template <typename SourceEncoding, typename TargetEncoding>
|
template<typename SourceEncoding, typename TargetEncoding>
|
||||||
struct Transcoder {
|
struct Transcoder {
|
||||||
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
if (!SourceEncoding::Decode(is, &codepoint))
|
if (!SourceEncoding::Decode(is, &codepoint))
|
||||||
@ -975,7 +666,7 @@ struct Transcoder {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
if (!SourceEncoding::Decode(is, &codepoint))
|
if (!SourceEncoding::Decode(is, &codepoint))
|
||||||
@ -985,32 +676,32 @@ struct Transcoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Validate one Unicode codepoint from an encoded stream.
|
//! Validate one Unicode codepoint from an encoded stream.
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||||
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Forward declaration.
|
// Forward declaration.
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
||||||
|
|
||||||
//! Specialization of Transcoder with same source and target encoding.
|
//! Specialization of Transcoder with same source and target encoding.
|
||||||
template <typename Encoding>
|
template<typename Encoding>
|
||||||
struct Transcoder<Encoding, Encoding> {
|
struct Transcoder<Encoding, Encoding> {
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||||
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||||
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||||
return Encoding::Validate(is, os); // source/target encoding are the same
|
return Encoding::Validate(is, os); // source/target encoding are the same
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(switch - enum)
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
RAPIDJSON_DIAG_OFF(covered - switch - default)
|
RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -35,52 +35,33 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
*/
|
*/
|
||||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
||||||
switch (parseErrorCode) {
|
switch (parseErrorCode) {
|
||||||
case kParseErrorNone:
|
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
||||||
return RAPIDJSON_ERROR_STRING("No error.");
|
|
||||||
|
|
||||||
case kParseErrorDocumentEmpty:
|
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
|
||||||
return RAPIDJSON_ERROR_STRING("The document is empty.");
|
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
||||||
case kParseErrorDocumentRootNotSingular:
|
|
||||||
return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
|
||||||
|
|
||||||
case kParseErrorValueInvalid:
|
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
|
||||||
return RAPIDJSON_ERROR_STRING("Invalid value.");
|
|
||||||
|
|
||||||
case kParseErrorObjectMissName:
|
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
||||||
return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
||||||
case kParseErrorObjectMissColon:
|
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
|
||||||
return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
|
||||||
case kParseErrorObjectMissCommaOrCurlyBracket:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
|
|
||||||
|
|
||||||
case kParseErrorArrayMissCommaOrSquareBracket:
|
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
|
||||||
return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
|
|
||||||
|
|
||||||
case kParseErrorStringUnicodeEscapeInvalidHex:
|
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
||||||
return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
||||||
case kParseErrorStringUnicodeSurrogateInvalid:
|
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
||||||
return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
||||||
case kParseErrorStringEscapeInvalid:
|
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
||||||
return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
|
||||||
case kParseErrorStringMissQuotationMark:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
|
||||||
case kParseErrorStringInvalidEncoding:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
|
||||||
|
|
||||||
case kParseErrorNumberTooBig:
|
case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
||||||
return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
||||||
case kParseErrorNumberMissFraction:
|
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
||||||
return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
|
||||||
case kParseErrorNumberMissExponent:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
|
||||||
|
|
||||||
case kParseErrorTermination:
|
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
||||||
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.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,69 +75,41 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
|
|||||||
*/
|
*/
|
||||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
|
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
|
||||||
switch (validateErrorCode) {
|
switch (validateErrorCode) {
|
||||||
case kValidateErrors:
|
case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
|
||||||
return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
|
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
||||||
case kValidateErrorNone:
|
|
||||||
return RAPIDJSON_ERROR_STRING("No error.");
|
|
||||||
|
|
||||||
case kValidateErrorMultipleOf:
|
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
|
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
|
||||||
case kValidateErrorMaximum:
|
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
|
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
|
||||||
case kValidateErrorExclusiveMaximum:
|
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
|
|
||||||
case kValidateErrorMinimum:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
|
|
||||||
case kValidateErrorExclusiveMinimum:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
|
|
||||||
|
|
||||||
case kValidateErrorMaxLength:
|
case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
|
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
|
||||||
case kValidateErrorMinLength:
|
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
|
||||||
return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
|
|
||||||
case kValidateErrorPattern:
|
|
||||||
return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
|
|
||||||
|
|
||||||
case kValidateErrorMaxItems:
|
case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
|
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
|
||||||
case kValidateErrorMinItems:
|
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
|
||||||
return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
|
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
|
||||||
case kValidateErrorUniqueItems:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
|
|
||||||
case kValidateErrorAdditionalItems:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
|
|
||||||
|
|
||||||
case kValidateErrorMaxProperties:
|
case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
|
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
|
||||||
case kValidateErrorMinProperties:
|
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
|
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
|
||||||
case kValidateErrorRequired:
|
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
|
||||||
return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
|
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
|
||||||
case kValidateErrorAdditionalProperties:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
|
|
||||||
case kValidateErrorPatternProperties:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
|
|
||||||
case kValidateErrorDependencies:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
|
|
||||||
|
|
||||||
case kValidateErrorEnum:
|
case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
|
||||||
return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
|
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
|
||||||
case kValidateErrorType:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
|
|
||||||
|
|
||||||
case kValidateErrorOneOf:
|
case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
|
||||||
return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
|
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
|
||||||
case kValidateErrorOneOfMatch:
|
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
|
||||||
return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
|
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
|
||||||
case kValidateErrorAllOf:
|
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
|
||||||
return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
|
|
||||||
case kValidateErrorAnyOf:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
|
|
||||||
case kValidateErrorNot:
|
|
||||||
return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
|
|
||||||
|
|
||||||
default:
|
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||||
return RAPIDJSON_ERROR_STRING("Unknown error.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,6 @@ enum ParseErrorCode {
|
|||||||
struct ParseResult {
|
struct ParseResult {
|
||||||
//!! Unspecified boolean type
|
//!! Unspecified boolean type
|
||||||
typedef bool (ParseResult::*BooleanType)() const;
|
typedef bool (ParseResult::*BooleanType)() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! Default constructor, no error.
|
//! Default constructor, no error.
|
||||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||||
@ -125,19 +124,16 @@ public:
|
|||||||
|
|
||||||
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
|
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
|
||||||
bool operator==(ParseErrorCode code) const { return code_ == code; }
|
bool operator==(ParseErrorCode code) const { return code_ == code; }
|
||||||
friend bool operator==(ParseErrorCode code, const ParseResult& err) { return code == err.code_; }
|
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
|
||||||
|
|
||||||
bool operator!=(const ParseResult& that) const { return !(*this == that); }
|
bool operator!=(const ParseResult& that) const { return !(*this == that); }
|
||||||
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
|
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
|
||||||
friend bool operator!=(ParseErrorCode code, const ParseResult& err) { return err != code; }
|
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
|
||||||
|
|
||||||
//! Reset error code.
|
//! Reset error code.
|
||||||
void Clear() { Set(kParseErrorNone); }
|
void Clear() { Set(kParseErrorNone); }
|
||||||
//! Update error code and offset.
|
//! Update error code and offset.
|
||||||
void Set(ParseErrorCode code, size_t offset = 0) {
|
void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
|
||||||
code_ = code;
|
|
||||||
offset_ = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ParseErrorCode code_;
|
ParseErrorCode code_;
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
RAPIDJSON_DIAG_OFF(unreachable - code)
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
RAPIDJSON_DIAG_OFF(missing - noreturn)
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -48,24 +48,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ch Peek() const { return *current_; }
|
Ch Peek() const { return *current_; }
|
||||||
Ch Take() {
|
Ch Take() { Ch c = *current_; Read(); return c; }
|
||||||
Ch c = *current_;
|
|
||||||
Read();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For encoding detection only.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const {
|
||||||
@ -91,10 +81,10 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::FILE* fp_;
|
std::FILE* fp_;
|
||||||
Ch* buffer_;
|
Ch *buffer_;
|
||||||
size_t bufferSize_;
|
size_t bufferSize_;
|
||||||
Ch* bufferLast_;
|
Ch *bufferLast_;
|
||||||
Ch* current_;
|
Ch *current_;
|
||||||
size_t readCount_;
|
size_t readCount_;
|
||||||
size_t count_; //!< Number of characters read
|
size_t count_; //!< Number of characters read
|
||||||
bool eof_;
|
bool eof_;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(unreachable - code)
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -72,26 +72,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
char Peek() const {
|
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
}
|
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
char Take() {
|
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t Tell() const {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
char* PutBegin() {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(char*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Prohibit copy constructor & assignment operator.
|
// Prohibit copy constructor & assignment operator.
|
||||||
@ -99,13 +84,13 @@ private:
|
|||||||
FileWriteStream& operator=(const FileWriteStream&);
|
FileWriteStream& operator=(const FileWriteStream&);
|
||||||
|
|
||||||
std::FILE* fp_;
|
std::FILE* fp_;
|
||||||
char* buffer_;
|
char *buffer_;
|
||||||
char* bufferEnd_;
|
char *bufferEnd_;
|
||||||
char* current_;
|
char *current_;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template <>
|
template<>
|
||||||
inline void PutN(FileWriteStream& stream, char c, size_t n) {
|
inline void PutN(FileWriteStream& stream, char c, size_t n) {
|
||||||
stream.PutN(c, n);
|
stream.PutN(c, n);
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,17 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
// encodings.h
|
// encodings.h
|
||||||
|
|
||||||
template <typename CharType>
|
template<typename CharType> struct UTF8;
|
||||||
struct UTF8;
|
template<typename CharType> struct UTF16;
|
||||||
template <typename CharType>
|
template<typename CharType> struct UTF16BE;
|
||||||
struct UTF16;
|
template<typename CharType> struct UTF16LE;
|
||||||
template <typename CharType>
|
template<typename CharType> struct UTF32;
|
||||||
struct UTF16BE;
|
template<typename CharType> struct UTF32BE;
|
||||||
template <typename CharType>
|
template<typename CharType> struct UTF32LE;
|
||||||
struct UTF16LE;
|
template<typename CharType> struct ASCII;
|
||||||
template <typename CharType>
|
template<typename CharType> struct AutoUTF;
|
||||||
struct UTF32;
|
|
||||||
template <typename CharType>
|
|
||||||
struct UTF32BE;
|
|
||||||
template <typename CharType>
|
|
||||||
struct UTF32LE;
|
|
||||||
template <typename CharType>
|
|
||||||
struct ASCII;
|
|
||||||
template <typename CharType>
|
|
||||||
struct AutoUTF;
|
|
||||||
|
|
||||||
template <typename SourceEncoding, typename TargetEncoding>
|
template<typename SourceEncoding, typename TargetEncoding>
|
||||||
struct Transcoder;
|
struct Transcoder;
|
||||||
|
|
||||||
// allocators.h
|
// allocators.h
|
||||||
@ -55,12 +46,12 @@ class MemoryPoolAllocator;
|
|||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct GenericStringStream;
|
struct GenericStringStream;
|
||||||
|
|
||||||
typedef GenericStringStream<UTF8<char>> StringStream;
|
typedef GenericStringStream<UTF8<char> > StringStream;
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct GenericInsituStringStream;
|
struct GenericInsituStringStream;
|
||||||
|
|
||||||
typedef GenericInsituStringStream<UTF8<char>> InsituStringStream;
|
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
|
||||||
|
|
||||||
// stringbuffer.h
|
// stringbuffer.h
|
||||||
|
|
||||||
@ -90,7 +81,7 @@ struct MemoryStream;
|
|||||||
|
|
||||||
// reader.h
|
// reader.h
|
||||||
|
|
||||||
template <typename Encoding, typename Derived>
|
template<typename Encoding, typename Derived>
|
||||||
struct BaseReaderHandler;
|
struct BaseReaderHandler;
|
||||||
|
|
||||||
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
|
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
|
||||||
@ -100,12 +91,12 @@ typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
|
|||||||
|
|
||||||
// writer.h
|
// writer.h
|
||||||
|
|
||||||
template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||||
class Writer;
|
class Writer;
|
||||||
|
|
||||||
// prettywriter.h
|
// prettywriter.h
|
||||||
|
|
||||||
template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||||
class PrettyWriter;
|
class PrettyWriter;
|
||||||
|
|
||||||
// document.h
|
// document.h
|
||||||
@ -116,13 +107,13 @@ class GenericMember;
|
|||||||
template <bool Const, typename Encoding, typename Allocator>
|
template <bool Const, typename Encoding, typename Allocator>
|
||||||
class GenericMemberIterator;
|
class GenericMemberIterator;
|
||||||
|
|
||||||
template <typename CharType>
|
template<typename CharType>
|
||||||
struct GenericStringRef;
|
struct GenericStringRef;
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator>
|
template <typename Encoding, typename Allocator>
|
||||||
class GenericValue;
|
class GenericValue;
|
||||||
|
|
||||||
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator>> Value;
|
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator, typename StackAllocator>
|
template <typename Encoding, typename Allocator, typename StackAllocator>
|
||||||
class GenericDocument;
|
class GenericDocument;
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class BigInteger {
|
class BigInteger {
|
||||||
public:
|
public:
|
||||||
typedef uint64_t Type;
|
typedef uint64_t Type;
|
||||||
|
|
||||||
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
|
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
|
||||||
@ -52,7 +52,8 @@ namespace internal {
|
|||||||
AppendDecimal64(decimals + i, decimals + i + length);
|
AppendDecimal64(decimals + i, decimals + i + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator=(const BigInteger& rhs) {
|
BigInteger& operator=(const BigInteger &rhs)
|
||||||
|
{
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
count_ = rhs.count_;
|
count_ = rhs.count_;
|
||||||
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||||
@ -187,16 +188,8 @@ namespace internal {
|
|||||||
RAPIDJSON_ASSERT(cmp != 0);
|
RAPIDJSON_ASSERT(cmp != 0);
|
||||||
const BigInteger *a, *b; // Makes a > b
|
const BigInteger *a, *b; // Makes a > b
|
||||||
bool ret;
|
bool ret;
|
||||||
if (cmp < 0) {
|
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
||||||
a = &rhs;
|
else { a = this; b = &rhs; ret = false; }
|
||||||
b = this;
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
a = this;
|
|
||||||
b = &rhs;
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type borrow = 0;
|
Type borrow = 0;
|
||||||
for (size_t i = 0; i < a->count_; i++) {
|
for (size_t i = 0; i < a->count_; i++) {
|
||||||
@ -224,13 +217,10 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t GetCount() const { return count_; }
|
size_t GetCount() const { return count_; }
|
||||||
Type GetDigit(size_t index) const {
|
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
||||||
RAPIDJSON_ASSERT(index < count_);
|
|
||||||
return digits_[index];
|
|
||||||
}
|
|
||||||
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AppendDecimal64(const char* begin, const char* end) {
|
void AppendDecimal64(const char* begin, const char* end) {
|
||||||
uint64_t u = ParseUint64(begin, end);
|
uint64_t u = ParseUint64(begin, end);
|
||||||
if (IsZero())
|
if (IsZero())
|
||||||
@ -292,7 +282,7 @@ namespace internal {
|
|||||||
|
|
||||||
Type digits_[kCapacity];
|
Type digits_[kCapacity];
|
||||||
size_t count_;
|
size_t count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
inline uint32_t clzll(uint64_t x) {
|
inline uint32_t clzll(uint64_t x) {
|
||||||
// Passing 0 to __builtin_clzll is UB in GCC and results in an
|
// Passing 0 to __builtin_clzll is UB in GCC and results in an
|
||||||
// infinite loop in the software implementation.
|
// infinite loop in the software implementation.
|
||||||
RAPIDJSON_ASSERT(x != 0);
|
RAPIDJSON_ASSERT(x != 0);
|
||||||
@ -61,7 +61,7 @@ namespace internal {
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
|
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
|
||||||
|
|
||||||
|
@ -32,16 +32,16 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct DiyFp {
|
struct DiyFp {
|
||||||
DiyFp() : f(), e() {}
|
DiyFp() : f(), e() {}
|
||||||
|
|
||||||
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
||||||
@ -128,7 +128,7 @@ namespace internal {
|
|||||||
union {
|
union {
|
||||||
double d;
|
double d;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
} u;
|
}u;
|
||||||
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
||||||
if (e < kDpDenormalExponent) {
|
if (e < kDpDenormalExponent) {
|
||||||
// Underflow.
|
// Underflow.
|
||||||
@ -138,7 +138,8 @@ namespace internal {
|
|||||||
// Overflow.
|
// Overflow.
|
||||||
return std::numeric_limits<double>::infinity();
|
return std::numeric_limits<double>::infinity();
|
||||||
}
|
}
|
||||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : static_cast<uint64_t>(e + kDpExponentBias);
|
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||||
|
static_cast<uint64_t>(e + kDpExponentBias);
|
||||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||||
return u.d;
|
return u.d;
|
||||||
}
|
}
|
||||||
@ -155,9 +156,9 @@ namespace internal {
|
|||||||
|
|
||||||
uint64_t f;
|
uint64_t f;
|
||||||
int e;
|
int e;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||||
// 10^-348, 10^-340, ..., 10^340
|
// 10^-348, 10^-340, ..., 10^340
|
||||||
static const uint64_t kCachedPowers_F[] = {
|
static const uint64_t kCachedPowers_F[] = {
|
||||||
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||||
@ -218,9 +219,9 @@ namespace internal {
|
|||||||
};
|
};
|
||||||
RAPIDJSON_ASSERT(index < 87);
|
RAPIDJSON_ASSERT(index < 87);
|
||||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DiyFp GetCachedPower(int e, int* K) {
|
inline DiyFp GetCachedPower(int e, int* K) {
|
||||||
|
|
||||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
//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
|
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||||
@ -232,22 +233,22 @@ namespace internal {
|
|||||||
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||||
|
|
||||||
return GetCachedPowerByIndex(index);
|
return GetCachedPowerByIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DiyFp GetCachedPower10(int exp, int* outExp) {
|
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||||
RAPIDJSON_ASSERT(exp >= -348);
|
RAPIDJSON_ASSERT(exp >= -348);
|
||||||
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
||||||
*outExp = -348 + static_cast<int>(index) * 8;
|
*outExp = -348 + static_cast<int>(index) * 8;
|
||||||
return GetCachedPowerByIndex(index);
|
return GetCachedPowerByIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -27,21 +27,21 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
RAPIDJSON_DIAG_OFF(array - bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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
|
||||||
wp_w - rest > rest + ten_kappa - wp_w)) {
|
wp_w - rest > rest + ten_kappa - wp_w)) {
|
||||||
buffer[len - 1]--;
|
buffer[len - 1]--;
|
||||||
rest += ten_kappa;
|
rest += ten_kappa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int CountDecimalDigit32(uint32_t n) {
|
inline int CountDecimalDigit32(uint32_t n) {
|
||||||
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||||
if (n < 10) return 1;
|
if (n < 10) return 1;
|
||||||
if (n < 100) return 2;
|
if (n < 100) return 2;
|
||||||
@ -55,9 +55,9 @@ namespace internal {
|
|||||||
//if (n < 1000000000) return 9;
|
//if (n < 1000000000) return 9;
|
||||||
//return 10;
|
//return 10;
|
||||||
return 9;
|
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) {
|
||||||
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||||
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
||||||
const DiyFp wp_w = Mp - W;
|
const DiyFp wp_w = Mp - W;
|
||||||
@ -69,42 +69,15 @@ namespace internal {
|
|||||||
while (kappa > 0) {
|
while (kappa > 0) {
|
||||||
uint32_t d = 0;
|
uint32_t d = 0;
|
||||||
switch (kappa) {
|
switch (kappa) {
|
||||||
case 9:
|
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
||||||
d = p1 / 100000000;
|
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
||||||
p1 %= 100000000;
|
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
||||||
break;
|
case 6: d = p1 / 100000; p1 %= 100000; break;
|
||||||
case 8:
|
case 5: d = p1 / 10000; p1 %= 10000; break;
|
||||||
d = p1 / 10000000;
|
case 4: d = p1 / 1000; p1 %= 1000; break;
|
||||||
p1 %= 10000000;
|
case 3: d = p1 / 100; p1 %= 100; break;
|
||||||
break;
|
case 2: d = p1 / 10; p1 %= 10; break;
|
||||||
case 7:
|
case 1: d = p1; p1 = 0; break;
|
||||||
d = p1 / 1000000;
|
|
||||||
p1 %= 1000000;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
d = p1 / 100000;
|
|
||||||
p1 %= 100000;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
d = p1 / 10000;
|
|
||||||
p1 %= 10000;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
d = p1 / 1000;
|
|
||||||
p1 %= 1000;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
d = p1 / 100;
|
|
||||||
p1 %= 100;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
d = p1 / 10;
|
|
||||||
p1 %= 10;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
d = p1;
|
|
||||||
p1 = 0;
|
|
||||||
break;
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
if (d || *len)
|
if (d || *len)
|
||||||
@ -134,9 +107,9 @@ namespace internal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Grisu2(double value, char* buffer, int* length, int* K) {
|
inline void Grisu2(double value, char* buffer, int* length, int* K) {
|
||||||
const DiyFp v(value);
|
const DiyFp v(value);
|
||||||
DiyFp w_m, w_p;
|
DiyFp w_m, w_p;
|
||||||
v.NormalizedBoundaries(&w_m, &w_p);
|
v.NormalizedBoundaries(&w_m, &w_p);
|
||||||
@ -148,9 +121,9 @@ namespace internal {
|
|||||||
Wm.f++;
|
Wm.f++;
|
||||||
Wp.f--;
|
Wp.f--;
|
||||||
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* WriteExponent(int K, char* buffer) {
|
inline char* WriteExponent(int K, char* buffer) {
|
||||||
if (K < 0) {
|
if (K < 0) {
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
K = -K;
|
K = -K;
|
||||||
@ -172,9 +145,9 @@ namespace internal {
|
|||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||||
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||||
|
|
||||||
if (0 <= k && kk <= 21) {
|
if (0 <= k && kk <= 21) {
|
||||||
@ -238,9 +211,9 @@ namespace internal {
|
|||||||
buffer[length + 1] = 'e';
|
buffer[length + 1] = 'e';
|
||||||
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
||||||
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||||
Double d(value);
|
Double d(value);
|
||||||
if (d.IsZero()) {
|
if (d.IsZero()) {
|
||||||
@ -260,10 +233,10 @@ namespace internal {
|
|||||||
Grisu2(value, buffer, &length, &K);
|
Grisu2(value, buffer, &length, &K);
|
||||||
return Prettify(buffer, length, K, maxDecimalPlaces);
|
return Prettify(buffer, length, K, maxDecimalPlaces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_POP
|
RAPIDJSON_DIAG_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class Double {
|
class Double {
|
||||||
public:
|
public:
|
||||||
Double() {}
|
Double() {}
|
||||||
Double(double d) : d_(d) {}
|
Double(double d) : d_(d) {}
|
||||||
Double(uint64_t u) : u_(u) {}
|
Double(uint64_t u) : u_(u) {}
|
||||||
@ -57,7 +57,7 @@ namespace internal {
|
|||||||
return order + 1074;
|
return order + 1074;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kSignificandSize = 52;
|
static const int kSignificandSize = 52;
|
||||||
static const int kExponentBias = 0x3FF;
|
static const int kExponentBias = 0x3FF;
|
||||||
static const int kDenormalExponent = 1 - kExponentBias;
|
static const int kDenormalExponent = 1 - kExponentBias;
|
||||||
@ -70,7 +70,7 @@ namespace internal {
|
|||||||
double d_;
|
double d_;
|
||||||
uint64_t u_;
|
uint64_t u_;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -20,23 +20,23 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
inline const char* GetDigitsLut() {
|
inline const char* GetDigitsLut() {
|
||||||
static const char cDigitsLut[200] = {
|
static const char cDigitsLut[200] = {
|
||||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
|
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
|
||||||
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
|
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
|
||||||
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
|
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
|
||||||
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
|
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
|
||||||
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
|
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
|
||||||
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
|
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
|
||||||
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
|
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
|
||||||
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
|
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
|
||||||
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
|
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
|
||||||
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
|
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
|
||||||
};
|
};
|
||||||
return cDigitsLut;
|
return cDigitsLut;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* u32toa(uint32_t value, char* buffer) {
|
inline char* u32toa(uint32_t value, char* buffer) {
|
||||||
RAPIDJSON_ASSERT(buffer != 0);
|
RAPIDJSON_ASSERT(buffer != 0);
|
||||||
|
|
||||||
const char* cDigitsLut = GetDigitsLut();
|
const char* cDigitsLut = GetDigitsLut();
|
||||||
@ -110,9 +110,9 @@ namespace internal {
|
|||||||
*buffer++ = cDigitsLut[d4 + 1];
|
*buffer++ = cDigitsLut[d4 + 1];
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* i32toa(int32_t value, char* buffer) {
|
inline char* i32toa(int32_t value, char* buffer) {
|
||||||
RAPIDJSON_ASSERT(buffer != 0);
|
RAPIDJSON_ASSERT(buffer != 0);
|
||||||
uint32_t u = static_cast<uint32_t>(value);
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
@ -121,9 +121,9 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return u32toa(u, buffer);
|
return u32toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* u64toa(uint64_t value, char* buffer) {
|
inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
RAPIDJSON_ASSERT(buffer != 0);
|
RAPIDJSON_ASSERT(buffer != 0);
|
||||||
const char* cDigitsLut = GetDigitsLut();
|
const char* cDigitsLut = GetDigitsLut();
|
||||||
const uint64_t kTen8 = 100000000;
|
const uint64_t kTen8 = 100000000;
|
||||||
@ -289,9 +289,9 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* i64toa(int64_t value, char* buffer) {
|
inline char* i64toa(int64_t value, char* buffer) {
|
||||||
RAPIDJSON_ASSERT(buffer != 0);
|
RAPIDJSON_ASSERT(buffer != 0);
|
||||||
uint64_t u = static_cast<uint64_t>(value);
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
@ -300,7 +300,7 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return u64toa(u, buffer);
|
return u64toa(u, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -35,113 +35,81 @@ RAPIDJSON_DIAG_OFF(6334)
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
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
|
||||||
template <typename T>
|
template <typename T> struct Void { typedef void Type; };
|
||||||
struct Void { typedef void Type; };
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// BoolType, TrueType, FalseType
|
// BoolType, TrueType, FalseType
|
||||||
//
|
//
|
||||||
template <bool Cond>
|
template <bool Cond> struct BoolType {
|
||||||
struct BoolType {
|
|
||||||
static const bool Value = Cond;
|
static const bool Value = Cond;
|
||||||
typedef BoolType Type;
|
typedef BoolType Type;
|
||||||
};
|
};
|
||||||
typedef BoolType<true> TrueType;
|
typedef BoolType<true> TrueType;
|
||||||
typedef BoolType<false> FalseType;
|
typedef BoolType<false> FalseType;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
|
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
|
||||||
//
|
//
|
||||||
|
|
||||||
template <bool C>
|
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
|
||||||
struct SelectIfImpl {
|
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
|
||||||
template <typename T1, typename T2>
|
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
|
||||||
struct Apply { typedef T1 Type; };
|
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct SelectIfImpl<false> {
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
struct Apply { typedef T2 Type; };
|
|
||||||
};
|
|
||||||
template <bool C, typename T1, typename T2>
|
|
||||||
struct SelectIfCond : SelectIfImpl<C>::template Apply<T1, T2> {};
|
|
||||||
template <typename C, typename T1, typename T2>
|
|
||||||
struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
|
|
||||||
|
|
||||||
template <bool Cond1, bool Cond2>
|
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
|
||||||
struct AndExprCond : FalseType {};
|
template <> struct AndExprCond<true, true> : TrueType {};
|
||||||
template <>
|
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
|
||||||
struct AndExprCond<true, true> : TrueType {};
|
template <> struct OrExprCond<false, false> : FalseType {};
|
||||||
template <bool Cond1, bool Cond2>
|
|
||||||
struct OrExprCond : TrueType {};
|
|
||||||
template <>
|
|
||||||
struct OrExprCond<false, false> : FalseType {};
|
|
||||||
|
|
||||||
template <typename C>
|
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
|
||||||
struct BoolExpr : SelectIf<C, TrueType, FalseType>::Type {};
|
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
|
||||||
template <typename C>
|
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
|
||||||
struct NotExpr : SelectIf<C, FalseType, TrueType>::Type {};
|
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
|
||||||
template <typename C1, typename C2>
|
|
||||||
struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
|
|
||||||
template <typename C1, typename C2>
|
|
||||||
struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// AddConst, MaybeAddConst, RemoveConst
|
// AddConst, MaybeAddConst, RemoveConst
|
||||||
template <typename T>
|
template <typename T> struct AddConst { typedef const T Type; };
|
||||||
struct AddConst { typedef const T Type; };
|
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
|
||||||
template <bool Constify, typename T>
|
template <typename T> struct RemoveConst { typedef T Type; };
|
||||||
struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
|
template <typename T> struct RemoveConst<const T> { typedef T Type; };
|
||||||
template <typename T>
|
|
||||||
struct RemoveConst { typedef T Type; };
|
|
||||||
template <typename T>
|
|
||||||
struct RemoveConst<const T> { typedef T Type; };
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// IsSame, IsConst, IsMoreConst, IsPointer
|
// IsSame, IsConst, IsMoreConst, IsPointer
|
||||||
//
|
//
|
||||||
template <typename T, typename U>
|
template <typename T, typename U> struct IsSame : FalseType {};
|
||||||
struct IsSame : FalseType {};
|
template <typename T> struct IsSame<T, T> : TrueType {};
|
||||||
template <typename T>
|
|
||||||
struct IsSame<T, T> : TrueType {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct IsConst : FalseType {};
|
||||||
struct IsConst : FalseType {};
|
template <typename T> struct IsConst<const T> : TrueType {};
|
||||||
template <typename T>
|
|
||||||
struct IsConst<const T> : TrueType {};
|
|
||||||
|
|
||||||
template <typename CT, typename T>
|
template <typename CT, typename T>
|
||||||
struct IsMoreConst
|
struct IsMoreConst
|
||||||
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
|
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
|
||||||
BoolType<IsConst<CT>::Value >= IsConst<T>::Value>>::Type {};
|
BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct IsPointer : FalseType {};
|
||||||
struct IsPointer : FalseType {};
|
template <typename T> struct IsPointer<T*> : TrueType {};
|
||||||
template <typename T>
|
|
||||||
struct IsPointer<T*> : TrueType {};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// IsBaseOf
|
// IsBaseOf
|
||||||
//
|
//
|
||||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||||
|
|
||||||
template <typename B, typename D>
|
template <typename B, typename D> struct IsBaseOf
|
||||||
struct IsBaseOf
|
: BoolType< ::std::is_base_of<B,D>::value> {};
|
||||||
: BoolType<::std::is_base_of<B, D>::value> {};
|
|
||||||
|
|
||||||
#else // simplified version adopted from Boost
|
#else // simplified version adopted from Boost
|
||||||
|
|
||||||
template <typename B, typename D>
|
template<typename B, typename D> struct IsBaseOfImpl {
|
||||||
struct IsBaseOfImpl {
|
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||||
|
|
||||||
typedef char (&Yes)[1];
|
typedef char (&Yes)[1];
|
||||||
typedef char (&No)[2];
|
typedef char (&No) [2];
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static Yes Check(const D*, T);
|
static Yes Check(const D*, T);
|
||||||
@ -153,58 +121,54 @@ namespace internal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
|
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename B, typename D>
|
template <typename B, typename D> struct IsBaseOf
|
||||||
struct IsBaseOf
|
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
|
||||||
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D>>>::Type {};
|
|
||||||
|
|
||||||
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
|
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// EnableIf / DisableIf
|
// EnableIf / DisableIf
|
||||||
//
|
//
|
||||||
template <bool Condition, typename T = void>
|
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
|
||||||
struct EnableIfCond { typedef T Type; };
|
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
|
||||||
template <typename T>
|
|
||||||
struct EnableIfCond<false, T> { /* empty */
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool Condition, typename T = void>
|
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
|
||||||
struct DisableIfCond { typedef T Type; };
|
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
|
||||||
template <typename T>
|
|
||||||
struct DisableIfCond<true, T> { /* empty */
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Condition, typename T = void>
|
template <typename Condition, typename T = void>
|
||||||
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
||||||
|
|
||||||
template <typename Condition, typename T = void>
|
template <typename Condition, typename T = void>
|
||||||
struct DisableIf : DisableIfCond<Condition::Value, T> {};
|
struct DisableIf : DisableIfCond<Condition::Value, T> {};
|
||||||
|
|
||||||
// SFINAE helpers
|
// SFINAE helpers
|
||||||
struct SfinaeTag {};
|
struct SfinaeTag {};
|
||||||
template <typename T>
|
template <typename T> struct RemoveSfinaeTag;
|
||||||
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_NAMESPACE::internal::RemoveSfinaeTag<::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*)type>::Type
|
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||||
|
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
|
||||||
|
|
||||||
#define RAPIDJSON_ENABLEIF(cond) \
|
#define RAPIDJSON_ENABLEIF(cond) \
|
||||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL
|
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
#define RAPIDJSON_DISABLEIF(cond) \
|
#define RAPIDJSON_DISABLEIF(cond) \
|
||||||
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
#define RAPIDJSON_ENABLEIF_RETURN(cond, returntype) \
|
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond), \
|
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||||
|
<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_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond), \
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
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).
|
||||||
/*! This function uses lookup table for fast and accurate results.
|
/*! This function uses lookup table for fast and accurate results.
|
||||||
\param n non-negative exponent. Must <= 308.
|
\param n non-negative exponent. Must <= 308.
|
||||||
\return 10.0^n
|
\return 10.0^n
|
||||||
*/
|
*/
|
||||||
inline double Pow10(int n) {
|
inline double Pow10(int n) {
|
||||||
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
|
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
|
||||||
1e+0,
|
1e+0,
|
||||||
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
|
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
|
||||||
@ -33,21 +33,21 @@ namespace internal {
|
|||||||
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
|
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
|
||||||
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
|
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
|
||||||
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
|
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
|
||||||
1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119, 1e+120,
|
1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
|
||||||
1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140,
|
1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
|
||||||
1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160,
|
1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
|
||||||
1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179, 1e+180,
|
1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
|
||||||
1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199, 1e+200,
|
1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
|
||||||
1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219, 1e+220,
|
1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
|
||||||
1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240,
|
1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
|
||||||
1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,
|
1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
|
||||||
1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269, 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279, 1e+280,
|
1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
|
||||||
1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299, 1e+300,
|
1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
|
||||||
1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308
|
1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
|
||||||
};
|
};
|
||||||
RAPIDJSON_ASSERT(n >= 0 && n <= 308);
|
RAPIDJSON_ASSERT(n >= 0 && n <= 308);
|
||||||
return e[n];
|
return e[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
RAPIDJSON_DIAG_OFF(switch - enum)
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
@ -40,12 +40,12 @@ RAPIDJSON_DIAG_OFF(effc++)
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// DecodedStream
|
// DecodedStream
|
||||||
|
|
||||||
template <typename SourceStream, typename Encoding>
|
template <typename SourceStream, typename Encoding>
|
||||||
class DecodedStream {
|
class DecodedStream {
|
||||||
public:
|
public:
|
||||||
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
||||||
unsigned Peek() { return codepoint_; }
|
unsigned Peek() { return codepoint_; }
|
||||||
unsigned Take() {
|
unsigned Take() {
|
||||||
@ -55,7 +55,7 @@ namespace internal {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Decode() {
|
void Decode() {
|
||||||
if (!Encoding::Decode(ss_, &codepoint_))
|
if (!Encoding::Decode(ss_, &codepoint_))
|
||||||
codepoint_ = 0;
|
codepoint_ = 0;
|
||||||
@ -63,19 +63,19 @@ namespace internal {
|
|||||||
|
|
||||||
SourceStream& ss_;
|
SourceStream& ss_;
|
||||||
unsigned codepoint_;
|
unsigned codepoint_;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GenericRegex
|
// GenericRegex
|
||||||
|
|
||||||
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator>
|
template <typename Encoding, typename Allocator>
|
||||||
class GenericRegexSearch;
|
class GenericRegexSearch;
|
||||||
|
|
||||||
//! Regular expression engine with subset of ECMAscript grammar.
|
//! Regular expression engine with subset of ECMAscript grammar.
|
||||||
/*!
|
/*!
|
||||||
Supported regular expression syntax:
|
Supported regular expression syntax:
|
||||||
- \c ab Concatenation
|
- \c ab Concatenation
|
||||||
- \c a|b Alternation
|
- \c a|b Alternation
|
||||||
@ -106,23 +106,25 @@ namespace internal {
|
|||||||
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
|
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
|
||||||
https://swtch.com/~rsc/regexp/regexp1.html
|
https://swtch.com/~rsc/regexp/regexp1.html
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||||
class GenericRegex {
|
class GenericRegex {
|
||||||
public:
|
public:
|
||||||
typedef Encoding EncodingType;
|
typedef Encoding EncodingType;
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
template <typename, typename>
|
template <typename, typename> friend class GenericRegexSearch;
|
||||||
friend class GenericRegexSearch;
|
|
||||||
|
|
||||||
GenericRegex(const Ch* source, Allocator* allocator = 0) : ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
|
GenericRegex(const Ch* source, Allocator* allocator = 0) :
|
||||||
|
ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
|
||||||
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||||
anchorBegin_(), anchorEnd_() {
|
anchorBegin_(), anchorEnd_()
|
||||||
|
{
|
||||||
GenericStringStream<Encoding> ss(source);
|
GenericStringStream<Encoding> ss(source);
|
||||||
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
|
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
|
||||||
Parse(ds);
|
Parse(ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
~GenericRegex() {
|
~GenericRegex()
|
||||||
|
{
|
||||||
RAPIDJSON_DELETE(ownAllocator_);
|
RAPIDJSON_DELETE(ownAllocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +132,7 @@ namespace internal {
|
|||||||
return root_ != kRegexInvalidState;
|
return root_ != kRegexInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Operator {
|
enum Operator {
|
||||||
kZeroOrOne,
|
kZeroOrOne,
|
||||||
kZeroOrMore,
|
kZeroOrMore,
|
||||||
@ -242,7 +244,8 @@ namespace internal {
|
|||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{': {
|
case '{':
|
||||||
|
{
|
||||||
unsigned n, m;
|
unsigned n, m;
|
||||||
if (!ParseUnsigned(ds, &n))
|
if (!ParseUnsigned(ds, &n))
|
||||||
return;
|
return;
|
||||||
@ -260,14 +263,16 @@ namespace internal {
|
|||||||
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
||||||
return;
|
return;
|
||||||
ds.Take();
|
ds.Take();
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
PushOperand(operandStack, kAnyCharacterClass);
|
PushOperand(operandStack, kAnyCharacterClass);
|
||||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[': {
|
case '[':
|
||||||
|
{
|
||||||
SizeType range;
|
SizeType range;
|
||||||
if (!ParseRange(ds, &range))
|
if (!ParseRange(ds, &range))
|
||||||
return;
|
return;
|
||||||
@ -302,7 +307,7 @@ namespace internal {
|
|||||||
|
|
||||||
#if RAPIDJSON_REGEX_VERBOSE
|
#if RAPIDJSON_REGEX_VERBOSE
|
||||||
printf("root: %d\n", root_);
|
printf("root: %d\n", root_);
|
||||||
for (SizeType i = 0; i < stateCount_; i++) {
|
for (SizeType i = 0; i < stateCount_ ; i++) {
|
||||||
State& s = GetState(i);
|
State& s = GetState(i);
|
||||||
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
||||||
}
|
}
|
||||||
@ -524,7 +529,8 @@ namespace internal {
|
|||||||
// fall through to step 0 for other characters
|
// fall through to step 0 for other characters
|
||||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||||
|
|
||||||
case 0: {
|
case 0:
|
||||||
|
{
|
||||||
SizeType r = NewRange(codepoint);
|
SizeType r = NewRange(codepoint);
|
||||||
if (current != kRegexInvalidRange)
|
if (current != kRegexInvalidRange)
|
||||||
GetRange(current).next = r;
|
GetRange(current).next = r;
|
||||||
@ -570,23 +576,12 @@ namespace internal {
|
|||||||
case '{':
|
case '{':
|
||||||
case '}':
|
case '}':
|
||||||
case '\\':
|
case '\\':
|
||||||
*escapedCodepoint = codepoint;
|
*escapedCodepoint = codepoint; return true;
|
||||||
return true;
|
case 'f': *escapedCodepoint = 0x000C; return true;
|
||||||
case 'f':
|
case 'n': *escapedCodepoint = 0x000A; return true;
|
||||||
*escapedCodepoint = 0x000C;
|
case 'r': *escapedCodepoint = 0x000D; return true;
|
||||||
return true;
|
case 't': *escapedCodepoint = 0x0009; return true;
|
||||||
case 'n':
|
case 'v': *escapedCodepoint = 0x000B; return true;
|
||||||
*escapedCodepoint = 0x000A;
|
|
||||||
return true;
|
|
||||||
case 'r':
|
|
||||||
*escapedCodepoint = 0x000D;
|
|
||||||
return true;
|
|
||||||
case 't':
|
|
||||||
*escapedCodepoint = 0x0009;
|
|
||||||
return true;
|
|
||||||
case 'v':
|
|
||||||
*escapedCodepoint = 0x000B;
|
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
return false; // Unsupported escape character
|
return false; // Unsupported escape character
|
||||||
}
|
}
|
||||||
@ -605,16 +600,18 @@ namespace internal {
|
|||||||
// For SearchWithAnchoring()
|
// For SearchWithAnchoring()
|
||||||
bool anchorBegin_;
|
bool anchorBegin_;
|
||||||
bool anchorEnd_;
|
bool anchorEnd_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename RegexType, typename Allocator = CrtAllocator>
|
template <typename RegexType, typename Allocator = CrtAllocator>
|
||||||
class GenericRegexSearch {
|
class GenericRegexSearch {
|
||||||
public:
|
public:
|
||||||
typedef typename RegexType::EncodingType Encoding;
|
typedef typename RegexType::EncodingType Encoding;
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : regex_(regex), allocator_(allocator), ownAllocator_(0),
|
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
|
||||||
state0_(allocator, 0), state1_(allocator, 0), stateSet_() {
|
regex_(regex), allocator_(allocator), ownAllocator_(0),
|
||||||
|
state0_(allocator, 0), state1_(allocator, 0), stateSet_()
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(regex_.IsValid());
|
RAPIDJSON_ASSERT(regex_.IsValid());
|
||||||
if (!allocator_)
|
if (!allocator_)
|
||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||||
@ -648,7 +645,7 @@ namespace internal {
|
|||||||
return Search(is);
|
return Search(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef typename RegexType::State State;
|
typedef typename RegexType::State State;
|
||||||
typedef typename RegexType::Range Range;
|
typedef typename RegexType::Range Range;
|
||||||
|
|
||||||
@ -657,7 +654,7 @@ namespace internal {
|
|||||||
DecodedStream<InputStream, Encoding> ds(is);
|
DecodedStream<InputStream, Encoding> ds(is);
|
||||||
|
|
||||||
state0_.Clear();
|
state0_.Clear();
|
||||||
Stack<Allocator>*current = &state0_, *next = &state1_;
|
Stack<Allocator> *current = &state0_, *next = &state1_;
|
||||||
const size_t stateSetSize = GetStateSetSize();
|
const size_t stateSetSize = GetStateSetSize();
|
||||||
std::memset(stateSet_, 0, stateSetSize);
|
std::memset(stateSet_, 0, stateSetSize);
|
||||||
|
|
||||||
@ -671,7 +668,8 @@ namespace internal {
|
|||||||
const State& sr = regex_.GetState(*s);
|
const State& sr = regex_.GetState(*s);
|
||||||
if (sr.codepoint == codepoint ||
|
if (sr.codepoint == codepoint ||
|
||||||
sr.codepoint == RegexType::kAnyCharacterClass ||
|
sr.codepoint == RegexType::kAnyCharacterClass ||
|
||||||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) {
|
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
|
||||||
|
{
|
||||||
matched = AddState(*next, sr.out) || matched;
|
matched = AddState(*next, sr.out) || matched;
|
||||||
if (!anchorEnd && matched)
|
if (!anchorEnd && matched)
|
||||||
return true;
|
return true;
|
||||||
@ -722,10 +720,10 @@ namespace internal {
|
|||||||
Stack<Allocator> state0_;
|
Stack<Allocator> state0_;
|
||||||
Stack<Allocator> state1_;
|
Stack<Allocator> state1_;
|
||||||
uint32_t* stateSet_;
|
uint32_t* stateSet_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef GenericRegex<UTF8<>> Regex;
|
typedef GenericRegex<UTF8<> > Regex;
|
||||||
typedef GenericRegexSearch<Regex> RegexSearch;
|
typedef GenericRegexSearch<Regex> RegexSearch;
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -21,21 +21,21 @@
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Stack
|
// Stack
|
||||||
|
|
||||||
//! A type-unsafe stack for storing different types of data.
|
//! A type-unsafe stack for storing different types of data.
|
||||||
/*! \tparam Allocator Allocator for allocating stack memory.
|
/*! \tparam Allocator Allocator for allocating stack memory.
|
||||||
*/
|
*/
|
||||||
template <typename Allocator>
|
template <typename Allocator>
|
||||||
class Stack {
|
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) {
|
||||||
@ -48,7 +48,8 @@ namespace internal {
|
|||||||
stack_(rhs.stack_),
|
stack_(rhs.stack_),
|
||||||
stackTop_(rhs.stackTop_),
|
stackTop_(rhs.stackTop_),
|
||||||
stackEnd_(rhs.stackEnd_),
|
stackEnd_(rhs.stackEnd_),
|
||||||
initialCapacity_(rhs.initialCapacity_) {
|
initialCapacity_(rhs.initialCapacity_)
|
||||||
|
{
|
||||||
rhs.allocator_ = 0;
|
rhs.allocator_ = 0;
|
||||||
rhs.ownAllocator_ = 0;
|
rhs.ownAllocator_ = 0;
|
||||||
rhs.stack_ = 0;
|
rhs.stack_ = 0;
|
||||||
@ -64,7 +65,8 @@ namespace internal {
|
|||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
Stack& operator=(Stack&& rhs) {
|
Stack& operator=(Stack&& rhs) {
|
||||||
if (&rhs != this) {
|
if (&rhs != this)
|
||||||
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
allocator_ = rhs.allocator_;
|
allocator_ = rhs.allocator_;
|
||||||
@ -110,20 +112,20 @@ namespace internal {
|
|||||||
|
|
||||||
// Optimization note: try to minimize the size of this function for force inline.
|
// Optimization note: try to minimize the size of this function for force inline.
|
||||||
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
|
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
|
||||||
template <typename T>
|
template<typename T>
|
||||||
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||||
// Expand the stack if needed
|
// Expand the stack if needed
|
||||||
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
|
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
|
||||||
Expand<T>(count);
|
Expand<T>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
||||||
Reserve<T>(count);
|
Reserve<T>(count);
|
||||||
return PushUnsafe<T>(count);
|
return PushUnsafe<T>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||||
RAPIDJSON_ASSERT(stackTop_);
|
RAPIDJSON_ASSERT(stackTop_);
|
||||||
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
|
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
|
||||||
@ -132,35 +134,35 @@ namespace internal {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T* Pop(size_t count) {
|
T* Pop(size_t count) {
|
||||||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||||
stackTop_ -= count * sizeof(T);
|
stackTop_ -= count * sizeof(T);
|
||||||
return reinterpret_cast<T*>(stackTop_);
|
return reinterpret_cast<T*>(stackTop_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T* Top() {
|
T* Top() {
|
||||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
const T* Top() const {
|
const T* Top() const {
|
||||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
|
const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
|
||||||
|
|
||||||
bool HasAllocator() const {
|
bool HasAllocator() const {
|
||||||
@ -176,8 +178,8 @@ namespace internal {
|
|||||||
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_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template<typename T>
|
||||||
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;
|
||||||
@ -185,8 +187,7 @@ namespace internal {
|
|||||||
if (!allocator_)
|
if (!allocator_)
|
||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||||
newCapacity = initialCapacity_;
|
newCapacity = initialCapacity_;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
newCapacity = GetCapacity();
|
newCapacity = GetCapacity();
|
||||||
newCapacity += (newCapacity + 1) / 2;
|
newCapacity += (newCapacity + 1) / 2;
|
||||||
}
|
}
|
||||||
@ -215,11 +216,11 @@ namespace internal {
|
|||||||
|
|
||||||
Allocator* allocator_;
|
Allocator* allocator_;
|
||||||
Allocator* ownAllocator_;
|
Allocator* ownAllocator_;
|
||||||
char* stack_;
|
char *stack_;
|
||||||
char* stackTop_;
|
char *stackTop_;
|
||||||
char* stackEnd_;
|
char *stackEnd_;
|
||||||
size_t initialCapacity_;
|
size_t initialCapacity_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -21,33 +21,33 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
//! Custom strlen() which works on different character types.
|
//! Custom strlen() which works on different character types.
|
||||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
||||||
\param s Null-terminated input string.
|
\param s Null-terminated input string.
|
||||||
\return Number of characters in the string.
|
\return Number of characters in the string.
|
||||||
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
||||||
*/
|
*/
|
||||||
template <typename Ch>
|
template <typename Ch>
|
||||||
inline SizeType StrLen(const Ch* s) {
|
inline SizeType StrLen(const Ch* s) {
|
||||||
RAPIDJSON_ASSERT(s != 0);
|
RAPIDJSON_ASSERT(s != 0);
|
||||||
const Ch* p = s;
|
const Ch* p = s;
|
||||||
while (*p) ++p;
|
while (*p) ++p;
|
||||||
return SizeType(p - s);
|
return SizeType(p - s);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline SizeType StrLen(const char* s) {
|
inline SizeType StrLen(const char* s) {
|
||||||
return SizeType(std::strlen(s));
|
return SizeType(std::strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline SizeType StrLen(const wchar_t* s) {
|
inline SizeType StrLen(const wchar_t* s) {
|
||||||
return SizeType(std::wcslen(s));
|
return SizeType(std::wcslen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns number of code points in a encoded string.
|
//! Returns number of code points in a encoded string.
|
||||||
template <typename Encoding>
|
template<typename Encoding>
|
||||||
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
||||||
RAPIDJSON_ASSERT(s != 0);
|
RAPIDJSON_ASSERT(s != 0);
|
||||||
RAPIDJSON_ASSERT(outCount != 0);
|
RAPIDJSON_ASSERT(outCount != 0);
|
||||||
GenericStringStream<Encoding> is(s);
|
GenericStringStream<Encoding> is(s);
|
||||||
@ -61,7 +61,7 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
*outCount = count;
|
*outCount = count;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -25,16 +25,16 @@
|
|||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
inline double FastPath(double significand, int exp) {
|
inline double FastPath(double significand, int exp) {
|
||||||
if (exp < -308)
|
if (exp < -308)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
else if (exp >= 0)
|
else if (exp >= 0)
|
||||||
return significand * internal::Pow10(exp);
|
return significand * internal::Pow10(exp);
|
||||||
else
|
else
|
||||||
return significand / internal::Pow10(-exp);
|
return significand / internal::Pow10(-exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double StrtodNormalPrecision(double d, int p) {
|
inline double StrtodNormalPrecision(double d, int p) {
|
||||||
if (p < -308) {
|
if (p < -308) {
|
||||||
// Prevent expSum < -308, making Pow10(p) = 0
|
// Prevent expSum < -308, making Pow10(p) = 0
|
||||||
d = FastPath(d, -308);
|
d = FastPath(d, -308);
|
||||||
@ -43,17 +43,17 @@ namespace internal {
|
|||||||
else
|
else
|
||||||
d = FastPath(d, p);
|
d = FastPath(d, p);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T Min3(T a, T b, T c) {
|
inline T Min3(T a, T b, T c) {
|
||||||
T m = a;
|
T m = a;
|
||||||
if (m > b) m = b;
|
if (m > b) m = b;
|
||||||
if (m > c) m = c;
|
if (m > c) m = c;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||||
const Double db(b);
|
const Double db(b);
|
||||||
const uint64_t bInt = db.IntegerSignificand();
|
const uint64_t bInt = db.IntegerSignificand();
|
||||||
const int bExp = db.IntegerExponent();
|
const int bExp = db.IntegerExponent();
|
||||||
@ -108,9 +108,9 @@ namespace internal {
|
|||||||
dS.Difference(bS, &delta);
|
dS.Difference(bS, &delta);
|
||||||
|
|
||||||
return delta.Compare(hS);
|
return delta.Compare(hS);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool StrtodFast(double d, int p, double* result) {
|
inline bool StrtodFast(double d, int p, double* result) {
|
||||||
// Use fast path for string-to-double conversion if possible
|
// Use fast path for string-to-double conversion if possible
|
||||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||||
if (p > 22 && p < 22 + 16) {
|
if (p > 22 && p < 22 + 16) {
|
||||||
@ -125,10 +125,10 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute an approximation and see if it is within 1/2 ULP
|
// Compute an approximation and see if it is within 1/2 ULP
|
||||||
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
|
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
|
||||||
uint64_t significand = 0;
|
uint64_t significand = 0;
|
||||||
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||||
for (; i < dLen; i++) {
|
for (; i < dLen; i++) {
|
||||||
@ -203,9 +203,9 @@ namespace internal {
|
|||||||
*result = rounded.ToDouble();
|
*result = rounded.ToDouble();
|
||||||
|
|
||||||
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
|
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
|
||||||
RAPIDJSON_ASSERT(dLen >= 0);
|
RAPIDJSON_ASSERT(dLen >= 0);
|
||||||
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
||||||
Double a(approx);
|
Double a(approx);
|
||||||
@ -221,9 +221,9 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
else // adjustment
|
else // adjustment
|
||||||
return a.NextPositiveDouble();
|
return a.NextPositiveDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
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(d >= 0.0);
|
||||||
RAPIDJSON_ASSERT(length >= 1);
|
RAPIDJSON_ASSERT(length >= 1);
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ namespace internal {
|
|||||||
|
|
||||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||||
return StrtodBigInteger(result, decimals, dLen, dExp);
|
return StrtodBigInteger(result, decimals, dLen, dExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -19,22 +19,22 @@
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
//! Custom swap() to avoid dependency on C++ <algorithm> header
|
//! 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.
|
/*! \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().
|
\note This has the same semantics as std::swap().
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
||||||
T tmp = a;
|
T tmp = a;
|
||||||
a = b;
|
a = b;
|
||||||
b = tmp;
|
b = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
@ -54,7 +54,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\param stream stream opened for read.
|
\param stream stream opened for read.
|
||||||
*/
|
*/
|
||||||
BasicIStreamWrapper(StreamType& stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||||
Read();
|
Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,30 +64,20 @@ 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.
|
||||||
*/
|
*/
|
||||||
BasicIStreamWrapper(StreamType& stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||||
Read();
|
Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch Peek() const { return *current_; }
|
Ch Peek() const { return *current_; }
|
||||||
Ch Take() {
|
Ch Take() { Ch c = *current_; Read(); return c; }
|
||||||
Ch c = *current_;
|
|
||||||
Read();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(Ch*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For encoding detection only.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const {
|
||||||
@ -116,11 +106,11 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamType& stream_;
|
StreamType &stream_;
|
||||||
Ch peekBuffer_[4], *buffer_;
|
Ch peekBuffer_[4], *buffer_;
|
||||||
size_t bufferSize_;
|
size_t bufferSize_;
|
||||||
Ch* bufferLast_;
|
Ch *bufferLast_;
|
||||||
Ch* current_;
|
Ch *current_;
|
||||||
size_t readCount_;
|
size_t readCount_;
|
||||||
size_t count_; //!< Number of characters read
|
size_t count_; //!< Number of characters read
|
||||||
bool eof_;
|
bool eof_;
|
||||||
|
@ -60,7 +60,7 @@ struct GenericMemoryBuffer {
|
|||||||
typedef GenericMemoryBuffer<> MemoryBuffer;
|
typedef GenericMemoryBuffer<> MemoryBuffer;
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template <>
|
template<>
|
||||||
inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
|
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));
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(unreachable - code)
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
RAPIDJSON_DIAG_OFF(missing - noreturn)
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -40,22 +40,16 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
struct MemoryStream {
|
struct MemoryStream {
|
||||||
typedef char Ch; // byte
|
typedef char Ch; // byte
|
||||||
|
|
||||||
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 RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
||||||
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
Ch Take() { return RAPIDJSON_UNLIKELY(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_); }
|
||||||
|
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
size_t PutEnd(Ch*) {
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For encoding detection only.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const {
|
||||||
|
@ -194,11 +194,11 @@ typedef struct {
|
|||||||
#define SCNiMAX "I64i"
|
#define SCNiMAX "I64i"
|
||||||
|
|
||||||
#ifdef _WIN64 // [
|
#ifdef _WIN64 // [
|
||||||
#define SCNdPTR "I64d"
|
# define SCNdPTR "I64d"
|
||||||
#define SCNiPTR "I64i"
|
# define SCNiPTR "I64i"
|
||||||
#else // _WIN64 ][
|
#else // _WIN64 ][
|
||||||
#define SCNdPTR "ld"
|
# define SCNdPTR "ld"
|
||||||
#define SCNiPTR "li"
|
# define SCNiPTR "li"
|
||||||
#endif // _WIN64 ]
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
// The fscanf macros for unsigned integers are:
|
// The fscanf macros for unsigned integers are:
|
||||||
@ -260,15 +260,15 @@ typedef struct {
|
|||||||
#define SCNXMAX "I64X"
|
#define SCNXMAX "I64X"
|
||||||
|
|
||||||
#ifdef _WIN64 // [
|
#ifdef _WIN64 // [
|
||||||
#define SCNoPTR "I64o"
|
# define SCNoPTR "I64o"
|
||||||
#define SCNuPTR "I64u"
|
# define SCNuPTR "I64u"
|
||||||
#define SCNxPTR "I64x"
|
# define SCNxPTR "I64x"
|
||||||
#define SCNXPTR "I64X"
|
# define SCNXPTR "I64X"
|
||||||
#else // _WIN64 ][
|
#else // _WIN64 ][
|
||||||
#define SCNoPTR "lo"
|
# define SCNoPTR "lo"
|
||||||
#define SCNuPTR "lu"
|
# define SCNuPTR "lu"
|
||||||
#define SCNxPTR "lx"
|
# define SCNxPTR "lx"
|
||||||
#define SCNXPTR "lX"
|
# define SCNXPTR "lX"
|
||||||
#endif // _WIN64 ]
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
#endif // __STDC_FORMAT_MACROS ]
|
#endif // __STDC_FORMAT_MACROS ]
|
||||||
@ -287,7 +287,8 @@ static
|
|||||||
#else // STATIC_IMAXDIV ][
|
#else // STATIC_IMAXDIV ][
|
||||||
_inline
|
_inline
|
||||||
#endif // STATIC_IMAXDIV ]
|
#endif // STATIC_IMAXDIV ]
|
||||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) {
|
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||||
|
{
|
||||||
imaxdiv_t result;
|
imaxdiv_t result;
|
||||||
|
|
||||||
result.quot = numer / denom;
|
result.quot = numer / denom;
|
||||||
|
@ -76,10 +76,10 @@
|
|||||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||||
// Check out Issue 9 for the details.
|
// Check out Issue 9 for the details.
|
||||||
#ifndef INTMAX_C // [
|
#ifndef INTMAX_C // [
|
||||||
#define INTMAX_C INT64_C
|
# define INTMAX_C INT64_C
|
||||||
#endif // INTMAX_C ]
|
#endif // INTMAX_C ]
|
||||||
#ifndef UINTMAX_C // [
|
#ifndef UINTMAX_C // [
|
||||||
#define UINTMAX_C UINT64_C
|
# define UINTMAX_C UINT64_C
|
||||||
#endif // UINTMAX_C ]
|
#endif // UINTMAX_C ]
|
||||||
|
|
||||||
#endif // __STDC_CONSTANT_MACROS ]
|
#endif // __STDC_CONSTANT_MACROS ]
|
||||||
@ -95,18 +95,18 @@
|
|||||||
#if defined(__cplusplus) && !defined(_M_ARM)
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#include <wchar.h>
|
# include <wchar.h>
|
||||||
#if defined(__cplusplus) && !defined(_M_ARM)
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||||
#ifndef _W64
|
#ifndef _W64
|
||||||
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||||
#define _W64 __w64
|
# define _W64 __w64
|
||||||
#else
|
# else
|
||||||
#define _W64
|
# define _W64
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -118,19 +118,19 @@ extern "C" {
|
|||||||
// realize that, e.g. char has the same size as __int8
|
// realize that, e.g. char has the same size as __int8
|
||||||
// so we give up on __intX for them.
|
// so we give up on __intX for them.
|
||||||
#if (_MSC_VER < 1300)
|
#if (_MSC_VER < 1300)
|
||||||
typedef signed char int8_t;
|
typedef signed char int8_t;
|
||||||
typedef signed short int16_t;
|
typedef signed short int16_t;
|
||||||
typedef signed int int32_t;
|
typedef signed int int32_t;
|
||||||
typedef unsigned char uint8_t;
|
typedef unsigned char uint8_t;
|
||||||
typedef unsigned short uint16_t;
|
typedef unsigned short uint16_t;
|
||||||
typedef unsigned int uint32_t;
|
typedef unsigned int uint32_t;
|
||||||
#else
|
#else
|
||||||
typedef signed __int8 int8_t;
|
typedef signed __int8 int8_t;
|
||||||
typedef signed __int16 int16_t;
|
typedef signed __int16 int16_t;
|
||||||
typedef signed __int32 int32_t;
|
typedef signed __int32 int32_t;
|
||||||
typedef unsigned __int8 uint8_t;
|
typedef unsigned __int8 uint8_t;
|
||||||
typedef unsigned __int16 uint16_t;
|
typedef unsigned __int16 uint16_t;
|
||||||
typedef unsigned __int32 uint32_t;
|
typedef unsigned __int32 uint32_t;
|
||||||
#endif
|
#endif
|
||||||
typedef signed __int64 int64_t;
|
typedef signed __int64 int64_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
@ -158,11 +158,11 @@ typedef uint64_t uint_fast64_t;
|
|||||||
|
|
||||||
// 7.18.1.4 Integer types capable of holding object pointers
|
// 7.18.1.4 Integer types capable of holding object pointers
|
||||||
#ifdef _WIN64 // [
|
#ifdef _WIN64 // [
|
||||||
typedef signed __int64 intptr_t;
|
typedef signed __int64 intptr_t;
|
||||||
typedef unsigned __int64 uintptr_t;
|
typedef unsigned __int64 uintptr_t;
|
||||||
#else // _WIN64 ][
|
#else // _WIN64 ][
|
||||||
typedef _W64 signed int intptr_t;
|
typedef _W64 signed int intptr_t;
|
||||||
typedef _W64 unsigned int uintptr_t;
|
typedef _W64 unsigned int uintptr_t;
|
||||||
#endif // _WIN64 ]
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
// 7.18.1.5 Greatest-width integer types
|
// 7.18.1.5 Greatest-width integer types
|
||||||
@ -218,13 +218,13 @@ typedef uint64_t uintmax_t;
|
|||||||
|
|
||||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||||
#ifdef _WIN64 // [
|
#ifdef _WIN64 // [
|
||||||
#define INTPTR_MIN INT64_MIN
|
# define INTPTR_MIN INT64_MIN
|
||||||
#define INTPTR_MAX INT64_MAX
|
# define INTPTR_MAX INT64_MAX
|
||||||
#define UINTPTR_MAX UINT64_MAX
|
# define UINTPTR_MAX UINT64_MAX
|
||||||
#else // _WIN64 ][
|
#else // _WIN64 ][
|
||||||
#define INTPTR_MIN INT32_MIN
|
# define INTPTR_MIN INT32_MIN
|
||||||
#define INTPTR_MAX INT32_MAX
|
# define INTPTR_MAX INT32_MAX
|
||||||
#define UINTPTR_MAX UINT32_MAX
|
# define UINTPTR_MAX UINT32_MAX
|
||||||
#endif // _WIN64 ]
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
// 7.18.2.5 Limits of greatest-width integer types
|
// 7.18.2.5 Limits of greatest-width integer types
|
||||||
@ -235,30 +235,30 @@ typedef uint64_t uintmax_t;
|
|||||||
// 7.18.3 Limits of other integer types
|
// 7.18.3 Limits of other integer types
|
||||||
|
|
||||||
#ifdef _WIN64 // [
|
#ifdef _WIN64 // [
|
||||||
#define PTRDIFF_MIN _I64_MIN
|
# define PTRDIFF_MIN _I64_MIN
|
||||||
#define PTRDIFF_MAX _I64_MAX
|
# define PTRDIFF_MAX _I64_MAX
|
||||||
#else // _WIN64 ][
|
#else // _WIN64 ][
|
||||||
#define PTRDIFF_MIN _I32_MIN
|
# define PTRDIFF_MIN _I32_MIN
|
||||||
#define PTRDIFF_MAX _I32_MAX
|
# define PTRDIFF_MAX _I32_MAX
|
||||||
#endif // _WIN64 ]
|
#endif // _WIN64 ]
|
||||||
|
|
||||||
#define SIG_ATOMIC_MIN INT_MIN
|
#define SIG_ATOMIC_MIN INT_MIN
|
||||||
#define SIG_ATOMIC_MAX INT_MAX
|
#define SIG_ATOMIC_MAX INT_MAX
|
||||||
|
|
||||||
#ifndef SIZE_MAX // [
|
#ifndef SIZE_MAX // [
|
||||||
#ifdef _WIN64 // [
|
# ifdef _WIN64 // [
|
||||||
#define SIZE_MAX _UI64_MAX
|
# define SIZE_MAX _UI64_MAX
|
||||||
#else // _WIN64 ][
|
# else // _WIN64 ][
|
||||||
#define SIZE_MAX _UI32_MAX
|
# define SIZE_MAX _UI32_MAX
|
||||||
#endif // _WIN64 ]
|
# endif // _WIN64 ]
|
||||||
#endif // SIZE_MAX ]
|
#endif // SIZE_MAX ]
|
||||||
|
|
||||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||||
#ifndef WCHAR_MIN // [
|
#ifndef WCHAR_MIN // [
|
||||||
#define WCHAR_MIN 0
|
# define WCHAR_MIN 0
|
||||||
#endif // WCHAR_MIN ]
|
#endif // WCHAR_MIN ]
|
||||||
#ifndef WCHAR_MAX // [
|
#ifndef WCHAR_MAX // [
|
||||||
#define WCHAR_MAX _UI16_MAX
|
# define WCHAR_MAX _UI16_MAX
|
||||||
#endif // WCHAR_MAX ]
|
#endif // WCHAR_MAX ]
|
||||||
|
|
||||||
#define WINT_MIN 0
|
#define WINT_MIN 0
|
||||||
@ -287,10 +287,10 @@ typedef uint64_t uintmax_t;
|
|||||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||||
// Check out Issue 9 for the details.
|
// Check out Issue 9 for the details.
|
||||||
#ifndef INTMAX_C // [
|
#ifndef INTMAX_C // [
|
||||||
#define INTMAX_C INT64_C
|
# define INTMAX_C INT64_C
|
||||||
#endif // INTMAX_C ]
|
#endif // INTMAX_C ]
|
||||||
#ifndef UINTMAX_C // [
|
#ifndef UINTMAX_C // [
|
||||||
#define UINTMAX_C UINT64_C
|
# define UINTMAX_C UINT64_C
|
||||||
#endif // UINTMAX_C ]
|
#endif // UINTMAX_C ]
|
||||||
|
|
||||||
#endif // __STDC_CONSTANT_MACROS ]
|
#endif // __STDC_CONSTANT_MACROS ]
|
||||||
|
@ -56,26 +56,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
char Peek() const {
|
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
return 0;
|
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
}
|
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
char Take() {
|
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t Tell() const {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
char* PutBegin() {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t PutEnd(char*) {
|
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BasicOStreamWrapper(const BasicOStreamWrapper&);
|
BasicOStreamWrapper(const BasicOStreamWrapper&);
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(switch - enum)
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
@ -244,7 +244,7 @@ public:
|
|||||||
GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
|
GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
|
||||||
GenericPointer r;
|
GenericPointer r;
|
||||||
r.allocator_ = allocator;
|
r.allocator_ = allocator;
|
||||||
Ch* p = r.CopyFromRaw(*this, 1, token.length + 1);
|
Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
|
||||||
std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
|
std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
|
||||||
r.tokens_[tokenCount_].name = p;
|
r.tokens_[tokenCount_].name = p;
|
||||||
r.tokens_[tokenCount_].length = token.length;
|
r.tokens_[tokenCount_].length = token.length;
|
||||||
@ -271,7 +271,7 @@ public:
|
|||||||
\return A new Pointer with appended token.
|
\return A new Pointer with appended token.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (GenericPointer))
|
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
|
||||||
Append(T* name, Allocator* allocator = 0) const {
|
Append(T* name, Allocator* allocator = 0) const {
|
||||||
return Append(name, internal::StrLen(name), allocator);
|
return Append(name, internal::StrLen(name), allocator);
|
||||||
}
|
}
|
||||||
@ -371,7 +371,8 @@ public:
|
|||||||
for (size_t i = 0; i < tokenCount_; i++) {
|
for (size_t i = 0; i < tokenCount_; i++) {
|
||||||
if (tokens_[i].index != rhs.tokens_[i].index ||
|
if (tokens_[i].index != rhs.tokens_[i].index ||
|
||||||
tokens_[i].length != rhs.tokens_[i].length ||
|
tokens_[i].length != rhs.tokens_[i].length ||
|
||||||
(tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length) != 0)) {
|
(tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,7 +423,7 @@ public:
|
|||||||
\tparam OutputStream Type of output stream.
|
\tparam OutputStream Type of output stream.
|
||||||
\param os The output stream.
|
\param os The output stream.
|
||||||
*/
|
*/
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
bool Stringify(OutputStream& os) const {
|
bool Stringify(OutputStream& os) const {
|
||||||
return Stringify<false, OutputStream>(os);
|
return Stringify<false, OutputStream>(os);
|
||||||
}
|
}
|
||||||
@ -432,7 +433,7 @@ public:
|
|||||||
\tparam OutputStream Type of output stream.
|
\tparam OutputStream Type of output stream.
|
||||||
\param os The output stream.
|
\param os The output stream.
|
||||||
*/
|
*/
|
||||||
template <typename OutputStream>
|
template<typename OutputStream>
|
||||||
bool StringifyUriFragment(OutputStream& os) const {
|
bool StringifyUriFragment(OutputStream& os) const {
|
||||||
return Stringify<true, OutputStream>(os);
|
return Stringify<true, OutputStream>(os);
|
||||||
}
|
}
|
||||||
@ -461,7 +462,7 @@ public:
|
|||||||
RAPIDJSON_ASSERT(IsValid());
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
ValueType* v = &root;
|
ValueType* v = &root;
|
||||||
bool exist = true;
|
bool exist = true;
|
||||||
for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||||
if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
|
if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
|
||||||
v->PushBack(ValueType().Move(), allocator);
|
v->PushBack(ValueType().Move(), allocator);
|
||||||
v = &((*v)[v->Size() - 1]);
|
v = &((*v)[v->Size() - 1]);
|
||||||
@ -539,9 +540,10 @@ public:
|
|||||||
ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
|
ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
|
||||||
RAPIDJSON_ASSERT(IsValid());
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
ValueType* v = &root;
|
ValueType* v = &root;
|
||||||
for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||||
switch (v->GetType()) {
|
switch (v->GetType()) {
|
||||||
case kObjectType: {
|
case kObjectType:
|
||||||
|
{
|
||||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||||
if (m == v->MemberEnd())
|
if (m == v->MemberEnd())
|
||||||
break;
|
break;
|
||||||
@ -616,7 +618,7 @@ public:
|
|||||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||||
GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
|
GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||||
return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
|
return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
|
||||||
}
|
}
|
||||||
@ -646,7 +648,7 @@ public:
|
|||||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||||
*/
|
*/
|
||||||
template <typename T, typename stackAllocator>
|
template <typename T, typename stackAllocator>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||||
GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
|
GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
|
||||||
return GetWithDefault(document, defaultValue, document.GetAllocator());
|
return GetWithDefault(document, defaultValue, document.GetAllocator());
|
||||||
}
|
}
|
||||||
@ -692,7 +694,7 @@ public:
|
|||||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||||
Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
|
Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
|
||||||
return Create(root, allocator) = ValueType(value).Move();
|
return Create(root, allocator) = ValueType(value).Move();
|
||||||
}
|
}
|
||||||
@ -728,7 +730,7 @@ public:
|
|||||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||||
*/
|
*/
|
||||||
template <typename T, typename stackAllocator>
|
template <typename T, typename stackAllocator>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||||
Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
|
Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
|
||||||
return Create(document) = value;
|
return Create(document) = value;
|
||||||
}
|
}
|
||||||
@ -774,14 +776,16 @@ public:
|
|||||||
|
|
||||||
ValueType* v = &root;
|
ValueType* v = &root;
|
||||||
const Token* last = tokens_ + (tokenCount_ - 1);
|
const Token* last = tokens_ + (tokenCount_ - 1);
|
||||||
for (const Token* t = tokens_; t != last; ++t) {
|
for (const Token *t = tokens_; t != last; ++t) {
|
||||||
switch (v->GetType()) {
|
switch (v->GetType()) {
|
||||||
case kObjectType: {
|
case kObjectType:
|
||||||
|
{
|
||||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||||
if (m == v->MemberEnd())
|
if (m == v->MemberEnd())
|
||||||
return false;
|
return false;
|
||||||
v = &m->value;
|
v = &m->value;
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
case kArrayType:
|
case kArrayType:
|
||||||
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
|
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
|
||||||
return false;
|
return false;
|
||||||
@ -818,12 +822,12 @@ private:
|
|||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||||
|
|
||||||
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
|
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
|
||||||
for (Token* t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
||||||
nameBufferSize += t->length;
|
nameBufferSize += t->length;
|
||||||
|
|
||||||
tokenCount_ = rhs.tokenCount_ + extraToken;
|
tokenCount_ = rhs.tokenCount_ + extraToken;
|
||||||
tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
|
tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
|
||||||
nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_);
|
nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
|
||||||
if (rhs.tokenCount_ > 0) {
|
if (rhs.tokenCount_ > 0) {
|
||||||
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
|
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
|
||||||
}
|
}
|
||||||
@ -833,7 +837,7 @@ private:
|
|||||||
|
|
||||||
// Adjust pointers to name buffer
|
// Adjust pointers to name buffer
|
||||||
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
|
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
|
||||||
for (Token* t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
|
for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
|
||||||
t->name += diff;
|
t->name += diff;
|
||||||
|
|
||||||
return nameBuffer_ + nameBufferSize;
|
return nameBuffer_ + nameBufferSize;
|
||||||
@ -845,7 +849,7 @@ private:
|
|||||||
\param c The character (code unit) to be tested.
|
\param c The character (code unit) to be tested.
|
||||||
*/
|
*/
|
||||||
bool NeedPercentEncode(Ch c) const {
|
bool NeedPercentEncode(Ch c) const {
|
||||||
return !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c == '~');
|
return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Parse a JSON String or its URI fragment representation into tokens.
|
//! Parse a JSON String or its URI fragment representation into tokens.
|
||||||
@ -871,8 +875,8 @@ private:
|
|||||||
if (*s == '/')
|
if (*s == '/')
|
||||||
tokenCount_++;
|
tokenCount_++;
|
||||||
|
|
||||||
Token* token = tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
|
Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
|
||||||
Ch* name = nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_);
|
Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
// Detect if it is a URI fragment
|
// Detect if it is a URI fragment
|
||||||
@ -929,10 +933,8 @@ private:
|
|||||||
if (c == '~') {
|
if (c == '~') {
|
||||||
if (i < length) {
|
if (i < length) {
|
||||||
c = source[i];
|
c = source[i];
|
||||||
if (c == '0')
|
if (c == '0') c = '~';
|
||||||
c = '~';
|
else if (c == '1') c = '/';
|
||||||
else if (c == '1')
|
|
||||||
c = '/';
|
|
||||||
else {
|
else {
|
||||||
parseErrorCode_ = kPointerParseErrorInvalidEscape;
|
parseErrorCode_ = kPointerParseErrorInvalidEscape;
|
||||||
goto error;
|
goto error;
|
||||||
@ -996,14 +998,14 @@ private:
|
|||||||
\tparam OutputStream type of output stream.
|
\tparam OutputStream type of output stream.
|
||||||
\param os The output stream.
|
\param os The output stream.
|
||||||
*/
|
*/
|
||||||
template <bool uriFragment, typename OutputStream>
|
template<bool uriFragment, typename OutputStream>
|
||||||
bool Stringify(OutputStream& os) const {
|
bool Stringify(OutputStream& os) const {
|
||||||
RAPIDJSON_ASSERT(IsValid());
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
|
|
||||||
if (uriFragment)
|
if (uriFragment)
|
||||||
os.Put('#');
|
os.Put('#');
|
||||||
|
|
||||||
for (Token* t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||||
os.Put('/');
|
os.Put('/');
|
||||||
for (size_t j = 0; j < t->length; j++) {
|
for (size_t j = 0; j < t->length; j++) {
|
||||||
Ch c = t->name[j];
|
Ch c = t->name[j];
|
||||||
@ -1019,7 +1021,7 @@ private:
|
|||||||
// Transcode to UTF8 sequence
|
// Transcode to UTF8 sequence
|
||||||
GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
|
GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
|
||||||
PercentEncodeStream<OutputStream> target(os);
|
PercentEncodeStream<OutputStream> target(os);
|
||||||
if (!Transcoder<EncodingType, UTF8<>>().Validate(source, target))
|
if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
|
||||||
return false;
|
return false;
|
||||||
j += source.Tell() - 1;
|
j += source.Tell() - 1;
|
||||||
}
|
}
|
||||||
@ -1057,12 +1059,9 @@ private:
|
|||||||
for (int j = 0; j < 2; j++) {
|
for (int j = 0; j < 2; j++) {
|
||||||
c = static_cast<Ch>(c << 4);
|
c = static_cast<Ch>(c << 4);
|
||||||
Ch h = *src_;
|
Ch h = *src_;
|
||||||
if (h >= '0' && h <= '9')
|
if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
|
||||||
c = static_cast<Ch>(c + h - '0');
|
else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
|
||||||
else if (h >= 'A' && h <= 'F')
|
else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
|
||||||
c = static_cast<Ch>(c + h - 'A' + 10);
|
|
||||||
else if (h >= 'a' && h <= 'f')
|
|
||||||
c = static_cast<Ch>(c + h - 'a' + 10);
|
|
||||||
else {
|
else {
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1094,7 +1093,6 @@ private:
|
|||||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
|
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
|
||||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
|
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OutputStream& os_;
|
OutputStream& os_;
|
||||||
};
|
};
|
||||||
@ -1122,7 +1120,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typena
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& CreateValueByPointer(T& root, const CharType (&source)[N], typename T::AllocatorType& a) {
|
typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1134,7 +1132,7 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType (&source)[N]) {
|
typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,7 +1154,7 @@ typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], s
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
const typename T::ValueType* GetValueByPointer(const T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
|
const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,31 +1178,31 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename T2>
|
template <typename T, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||||
GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
|
GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
|
||||||
return pointer.GetWithDefault(root, defaultValue, a);
|
return pointer.GetWithDefault(root, defaultValue, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
|
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
|
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
|
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N, typename T2>
|
template <typename T, typename CharType, size_t N, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||||
GetValueByPointerWithDefault(T& root, const CharType (&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
|
GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,31 +1226,31 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename DocumentType, typename T2>
|
template <typename DocumentType, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||||
GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
|
GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
|
||||||
return pointer.GetWithDefault(document, defaultValue);
|
return pointer.GetWithDefault(document, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& defaultValue) {
|
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* defaultValue) {
|
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
|
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||||
GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], T2 defaultValue) {
|
GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,36 +1279,36 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename T2>
|
template <typename T, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||||
SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
|
SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
|
||||||
return pointer.Set(root, value, a);
|
return pointer.Set(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
|
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
|
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
|
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
|
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N, typename T2>
|
template <typename T, typename CharType, size_t N, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||||
SetValueByPointer(T& root, const CharType (&source)[N], T2 value, typename T::AllocatorType& a) {
|
SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,36 +1337,36 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename DocumentType, typename T2>
|
template <typename DocumentType, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||||
SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
|
SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
|
||||||
return pointer.Set(document, value);
|
return pointer.Set(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) {
|
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& value) {
|
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* value) {
|
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
|
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||||
SetValueByPointer(DocumentType& document, const CharType (&source)[N], T2 value) {
|
SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1380,7 +1378,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType& SwapValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
|
typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1390,7 +1388,7 @@ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename DocumentType, typename CharType, size_t N>
|
template <typename DocumentType, typename CharType, size_t N>
|
||||||
typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) {
|
typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
|
||||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
|
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1402,7 +1400,7 @@ bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& p
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
bool EraseValueByPointer(T& root, const CharType (&source)[N]) {
|
bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ RAPIDJSON_DIAG_OFF(effc++)
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -44,7 +44,7 @@ enum PrettyFormatOptions {
|
|||||||
\tparam TargetEncoding Encoding of output stream.
|
\tparam TargetEncoding Encoding of output stream.
|
||||||
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
||||||
*/
|
*/
|
||||||
template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||||
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
|
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
|
||||||
public:
|
public:
|
||||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
|
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
|
||||||
@ -55,13 +55,16 @@ public:
|
|||||||
\param allocator User supplied allocator. If it is null, it will create a private one.
|
\param allocator 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 PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||||
|
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||||
|
|
||||||
|
|
||||||
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||||
|
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
PrettyWriter(PrettyWriter&& rhs) : Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
|
PrettyWriter(PrettyWriter&& rhs) :
|
||||||
|
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Set custom indentation.
|
//! Set custom indentation.
|
||||||
@ -89,34 +92,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
bool Null() {
|
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); }
|
||||||
PrettyPrefix(kNullType);
|
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
|
||||||
return Base::EndValue(Base::WriteNull());
|
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
|
||||||
}
|
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
|
||||||
bool Bool(bool b) {
|
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
|
||||||
PrettyPrefix(b ? kTrueType : kFalseType);
|
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); }
|
||||||
return Base::EndValue(Base::WriteBool(b));
|
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
|
||||||
}
|
|
||||||
bool Int(int i) {
|
|
||||||
PrettyPrefix(kNumberType);
|
|
||||||
return Base::EndValue(Base::WriteInt(i));
|
|
||||||
}
|
|
||||||
bool Uint(unsigned u) {
|
|
||||||
PrettyPrefix(kNumberType);
|
|
||||||
return Base::EndValue(Base::WriteUint(u));
|
|
||||||
}
|
|
||||||
bool Int64(int64_t i64) {
|
|
||||||
PrettyPrefix(kNumberType);
|
|
||||||
return Base::EndValue(Base::WriteInt64(i64));
|
|
||||||
}
|
|
||||||
bool Uint64(uint64_t u64) {
|
|
||||||
PrettyPrefix(kNumberType);
|
|
||||||
return Base::EndValue(Base::WriteUint64(u64));
|
|
||||||
}
|
|
||||||
bool Double(double d) {
|
|
||||||
PrettyPrefix(kNumberType);
|
|
||||||
return Base::EndValue(Base::WriteDouble(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||||
RAPIDJSON_ASSERT(str != 0);
|
RAPIDJSON_ASSERT(str != 0);
|
||||||
|
@ -244,41 +244,41 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef RAPIDJSON_ENDIAN
|
#ifndef RAPIDJSON_ENDIAN
|
||||||
// Detect with GCC 4.6's macro
|
// Detect with GCC 4.6's macro
|
||||||
#ifdef __BYTE_ORDER__
|
# ifdef __BYTE_ORDER__
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||||
#else
|
# else
|
||||||
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||||
#endif // __BYTE_ORDER__
|
# endif // __BYTE_ORDER__
|
||||||
// Detect with GLIBC's endian.h
|
// Detect with GLIBC's endian.h
|
||||||
#elif defined(__GLIBC__)
|
# elif defined(__GLIBC__)
|
||||||
#include <endian.h>
|
# include <endian.h>
|
||||||
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
#elif (__BYTE_ORDER == __BIG_ENDIAN)
|
# elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||||
#else
|
# else
|
||||||
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||||
#endif // __GLIBC__
|
# endif // __GLIBC__
|
||||||
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
|
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
|
||||||
#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
|
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
|
# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||||
// Detect with architecture macros
|
// Detect with architecture macros
|
||||||
#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
|
# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
|
||||||
#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) || defined(_M_ARM64))
|
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
#elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||||
#define RAPIDJSON_ENDIAN
|
# define RAPIDJSON_ENDIAN
|
||||||
#else
|
# else
|
||||||
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||||
#endif
|
# endif
|
||||||
#endif // RAPIDJSON_ENDIAN
|
#endif // RAPIDJSON_ENDIAN
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -343,8 +343,8 @@
|
|||||||
#if RAPIDJSON_64BIT != 1
|
#if RAPIDJSON_64BIT != 1
|
||||||
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
|
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
|
||||||
#endif
|
#endif
|
||||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type*>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
|
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
|
||||||
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
|
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
||||||
#define RAPIDJSON_GETPOINTER(type, p) (p)
|
#define RAPIDJSON_GETPOINTER(type, p) (p)
|
||||||
@ -379,7 +379,8 @@
|
|||||||
If any of these symbols is defined, RapidJSON defines the macro
|
If any of these symbols is defined, RapidJSON defines the macro
|
||||||
\c RAPIDJSON_SIMD to indicate the availability of the optimized code.
|
\c RAPIDJSON_SIMD to indicate the availability of the optimized code.
|
||||||
*/
|
*/
|
||||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
|
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
|
||||||
|
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||||
#define RAPIDJSON_SIMD
|
#define RAPIDJSON_SIMD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -441,7 +442,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
|
|
||||||
// Prefer C++11 static_assert, if available
|
// Prefer C++11 static_assert, if available
|
||||||
#ifndef RAPIDJSON_STATIC_ASSERT
|
#ifndef RAPIDJSON_STATIC_ASSERT
|
||||||
#if RAPIDJSON_CPLUSPLUS >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
|
||||||
#define RAPIDJSON_STATIC_ASSERT(x) \
|
#define RAPIDJSON_STATIC_ASSERT(x) \
|
||||||
static_assert(x, RAPIDJSON_STRINGIFY(x))
|
static_assert(x, RAPIDJSON_STRINGIFY(x))
|
||||||
#endif // C++11
|
#endif // C++11
|
||||||
@ -453,14 +454,9 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#endif
|
#endif
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
template <bool x>
|
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||||
struct STATIC_ASSERTION_FAILURE;
|
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||||
template <>
|
template <size_t x> struct StaticAssertTest {};
|
||||||
struct STATIC_ASSERTION_FAILURE<true> {
|
|
||||||
enum { value = 1 };
|
|
||||||
};
|
|
||||||
template <size_t x>
|
|
||||||
struct StaticAssertTest {};
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
@ -479,7 +475,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
*/
|
*/
|
||||||
#define RAPIDJSON_STATIC_ASSERT(x) \
|
#define RAPIDJSON_STATIC_ASSERT(x) \
|
||||||
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
||||||
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x)>)> \
|
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 // RAPIDJSON_STATIC_ASSERT
|
#endif // RAPIDJSON_STATIC_ASSERT
|
||||||
|
|
||||||
@ -519,11 +515,10 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
|
|
||||||
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
|
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
|
||||||
#define RAPIDJSON_MULTILINEMACRO_END \
|
#define RAPIDJSON_MULTILINEMACRO_END \
|
||||||
} \
|
} while((void)0, 0)
|
||||||
while ((void)0, 0)
|
|
||||||
|
|
||||||
// adopted from Boost
|
// adopted from Boost
|
||||||
#define RAPIDJSON_VERSION_CODE(x, y, z) \
|
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||||
(((x)*100000) + ((y)*100) + (z))
|
(((x)*100000) + ((y)*100) + (z))
|
||||||
|
|
||||||
#if defined(__has_builtin)
|
#if defined(__has_builtin)
|
||||||
@ -537,18 +532,18 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define RAPIDJSON_GNUC \
|
#define RAPIDJSON_GNUC \
|
||||||
RAPIDJSON_VERSION_CODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 2, 0))
|
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
|
||||||
|
|
||||||
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
|
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
|
||||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
|
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
|
||||||
#define RAPIDJSON_DIAG_OFF(x) \
|
#define RAPIDJSON_DIAG_OFF(x) \
|
||||||
RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W, x)))
|
RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
|
||||||
|
|
||||||
// push/pop support in Clang and GCC>=4.6
|
// push/pop support in Clang and GCC>=4.6
|
||||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0))
|
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
|
||||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
||||||
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
||||||
#else // GCC >= 4.2, < 4.6
|
#else // GCC >= 4.2, < 4.6
|
||||||
@ -562,8 +557,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#define RAPIDJSON_PRAGMA(x) __pragma(x)
|
#define RAPIDJSON_PRAGMA(x) __pragma(x)
|
||||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
|
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
|
||||||
|
|
||||||
#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable \
|
#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
|
||||||
: x)
|
|
||||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
||||||
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
||||||
|
|
||||||
@ -592,7 +586,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#else
|
#else
|
||||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||||
#endif
|
#endif
|
||||||
#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) || \
|
||||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||||
|
|
||||||
@ -611,7 +605,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
|
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
|
||||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||||
(defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
(defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||||
@ -639,7 +633,7 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||||
(defined(_MSC_VER) && _MSC_VER >= 1700) || \
|
(defined(_MSC_VER) && _MSC_VER >= 1700) || \
|
||||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||||
@ -656,23 +650,23 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX17
|
#if RAPIDJSON_HAS_CXX17
|
||||||
#define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
|
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
|
||||||
#elif defined(__has_cpp_attribute)
|
#elif defined(__has_cpp_attribute)
|
||||||
#if __has_cpp_attribute(clang::fallthrough)
|
# if __has_cpp_attribute(clang::fallthrough)
|
||||||
#define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
|
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
|
||||||
#elif __has_cpp_attribute(fallthrough)
|
# elif __has_cpp_attribute(fallthrough)
|
||||||
#define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
|
# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
|
||||||
|
# else
|
||||||
|
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
//! Assertion (in non-throwing contexts).
|
//! Assertion (in non-throwing contexts).
|
||||||
/*! \ingroup RAPIDJSON_CONFIG
|
/*! \ingroup RAPIDJSON_CONFIG
|
||||||
Some functions provide a \c noexcept guarantee, if the compiler supports it.
|
Some functions provide a \c noexcept guarantee, if the compiler supports it.
|
||||||
In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
|
In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
|
||||||
throw an exception. This macro adds a separate customization point for
|
throw an exception. This macro adds a separate customization point for
|
||||||
|
@ -40,9 +40,9 @@
|
|||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(old - style - cast)
|
RAPIDJSON_DIAG_OFF(old-style-cast)
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
RAPIDJSON_DIAG_OFF(switch - enum)
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||||
@ -194,7 +194,7 @@ concept Handler {
|
|||||||
/*! This can be used as base class of any reader handler.
|
/*! This can be used as base class of any reader handler.
|
||||||
\note implements Handler concept
|
\note implements Handler concept
|
||||||
*/
|
*/
|
||||||
template <typename Encoding = UTF8<>, typename Derived = void>
|
template<typename Encoding = UTF8<>, typename Derived = void>
|
||||||
struct BaseReaderHandler {
|
struct BaseReaderHandler {
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
@ -223,35 +223,35 @@ struct BaseReaderHandler {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename Stream, int = StreamTraits<Stream>::copyOptimization>
|
template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
|
||||||
class StreamLocalCopy;
|
class StreamLocalCopy;
|
||||||
|
|
||||||
//! Do copy optimization.
|
//! Do copy optimization.
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
class StreamLocalCopy<Stream, 1> {
|
class StreamLocalCopy<Stream, 1> {
|
||||||
public:
|
public:
|
||||||
StreamLocalCopy(Stream& original) : s(original), original_(original) {}
|
StreamLocalCopy(Stream& original) : s(original), original_(original) {}
|
||||||
~StreamLocalCopy() { original_ = s; }
|
~StreamLocalCopy() { original_ = s; }
|
||||||
|
|
||||||
Stream s;
|
Stream s;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
|
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
|
||||||
|
|
||||||
Stream& original_;
|
Stream& original_;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Keep reference.
|
//! Keep reference.
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
class StreamLocalCopy<Stream, 0> {
|
class StreamLocalCopy<Stream, 0> {
|
||||||
public:
|
public:
|
||||||
StreamLocalCopy(Stream& original) : s(original) {}
|
StreamLocalCopy(Stream& original) : s(original) {}
|
||||||
|
|
||||||
Stream& s;
|
Stream& s;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
|
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ namespace internal {
|
|||||||
/*! \param is A input stream for skipping white spaces.
|
/*! \param is A input stream for skipping white spaces.
|
||||||
\note This function has SSE2/SSE4.2 specialization.
|
\note This function has SSE2/SSE4.2 specialization.
|
||||||
*/
|
*/
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
void SkipWhitespace(InputStream& is) {
|
void SkipWhitespace(InputStream& is) {
|
||||||
internal::StreamLocalCopy<InputStream> copy(is);
|
internal::StreamLocalCopy<InputStream> copy(is);
|
||||||
InputStream& s(copy.s);
|
InputStream& s(copy.s);
|
||||||
@ -280,7 +280,7 @@ inline const char* SkipWhitespace(const char* p, const char* end) {
|
|||||||
|
|
||||||
#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;
|
||||||
@ -297,17 +297,17 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
|
|||||||
|
|
||||||
// The rest of string using SIMD
|
// The rest of string using SIMD
|
||||||
static const char whitespace[16] = " \n\r\t";
|
static const char whitespace[16] = " \n\r\t";
|
||||||
const __m128i w = _mm_loadu_si128(reinterpret_cast<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(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
||||||
if (r != 16) // some of characters is non-whitespace
|
if (r != 16) // some of characters is non-whitespace
|
||||||
return p + r;
|
return p + r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||||
++p;
|
++p;
|
||||||
@ -316,10 +316,10 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
|
|
||||||
// The middle of string using SIMD
|
// The middle 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(reinterpret_cast<const __m128i*>(&whitespace[0]));
|
const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
|
||||||
|
|
||||||
for (; p <= end - 16; p += 16) {
|
for (; p <= end - 16; p += 16) {
|
||||||
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
||||||
if (r != 16) // some of characters is non-whitespace
|
if (r != 16) // some of characters is non-whitespace
|
||||||
return p + r;
|
return p + r;
|
||||||
@ -331,7 +331,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
#elif defined(RAPIDJSON_SSE2)
|
#elif defined(RAPIDJSON_SSE2)
|
||||||
|
|
||||||
//! 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;
|
||||||
@ -346,19 +346,18 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
|
|||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// The rest of string
|
// The rest of string
|
||||||
#define C16(c) \
|
#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
|
||||||
{ c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
|
|
||||||
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
|
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
|
||||||
#undef C16
|
#undef C16
|
||||||
|
|
||||||
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0]));
|
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
|
||||||
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0]));
|
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
|
||||||
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0]));
|
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
|
||||||
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<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(reinterpret_cast<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));
|
||||||
@ -376,26 +375,25 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||||
++p;
|
++p;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
// The rest of string
|
// The rest of string
|
||||||
#define C16(c) \
|
#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
|
||||||
{ c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
|
|
||||||
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
|
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
|
||||||
#undef C16
|
#undef C16
|
||||||
|
|
||||||
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0]));
|
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
|
||||||
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0]));
|
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
|
||||||
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0]));
|
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
|
||||||
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[3][0]));
|
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
|
||||||
|
|
||||||
for (; p <= end - 16; p += 16) {
|
for (; p <= end - 16; p += 16) {
|
||||||
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_loadu_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));
|
||||||
@ -418,7 +416,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
#elif defined(RAPIDJSON_NEON)
|
#elif defined(RAPIDJSON_NEON)
|
||||||
|
|
||||||
//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.
|
//! Skip whitespace with ARM Neon 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;
|
||||||
@ -439,7 +437,7 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
|
|||||||
const uint8x16_t w3 = vmovq_n_u8('\t');
|
const uint8x16_t w3 = vmovq_n_u8('\t');
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, w0);
|
uint8x16_t x = vceqq_u8(s, w0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, w1));
|
x = vorrq_u8(x, vceqq_u8(s, w1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, w2));
|
x = vorrq_u8(x, vceqq_u8(s, w2));
|
||||||
@ -455,15 +453,14 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
|
|||||||
uint32_t lz = internal::clzll(high);
|
uint32_t lz = internal::clzll(high);
|
||||||
return p + 8 + (lz >> 3);
|
return p + 8 + (lz >> 3);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
return p + (lz >> 3);
|
return p + (lz >> 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||||
// Fast return for single non-whitespace
|
// Fast return for single non-whitespace
|
||||||
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||||
++p;
|
++p;
|
||||||
@ -476,7 +473,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
const uint8x16_t w3 = vmovq_n_u8('\t');
|
const uint8x16_t w3 = vmovq_n_u8('\t');
|
||||||
|
|
||||||
for (; p <= end - 16; p += 16) {
|
for (; p <= end - 16; p += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, w0);
|
uint8x16_t x = vceqq_u8(s, w0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, w1));
|
x = vorrq_u8(x, vceqq_u8(s, w1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, w2));
|
x = vorrq_u8(x, vceqq_u8(s, w2));
|
||||||
@ -492,8 +489,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
uint32_t lz = internal::clzll(high);
|
uint32_t lz = internal::clzll(high);
|
||||||
return p + 8 + (lz >> 3);
|
return p + 8 + (lz >> 3);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
return p + (lz >> 3);
|
return p + (lz >> 3);
|
||||||
}
|
}
|
||||||
@ -506,19 +502,16 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
|
|
||||||
#ifdef RAPIDJSON_SIMD
|
#ifdef RAPIDJSON_SIMD
|
||||||
//! Template function specialization for InsituStringStream
|
//! Template function specialization for InsituStringStream
|
||||||
template <>
|
template<> inline void SkipWhitespace(InsituStringStream& is) {
|
||||||
inline void SkipWhitespace(InsituStringStream& is) {
|
|
||||||
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
|
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Template function specialization for StringStream
|
//! Template function specialization for StringStream
|
||||||
template <>
|
template<> inline void SkipWhitespace(StringStream& is) {
|
||||||
inline void SkipWhitespace(StringStream& is) {
|
|
||||||
is.src_ = SkipWhitespace_SIMD(is.src_);
|
is.src_ = SkipWhitespace_SIMD(is.src_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
|
||||||
inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
|
|
||||||
is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
|
is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
|
||||||
}
|
}
|
||||||
#endif // RAPIDJSON_SIMD
|
#endif // RAPIDJSON_SIMD
|
||||||
@ -551,7 +544,8 @@ public:
|
|||||||
/*! \param stackAllocator 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_(), state_(IterativeParsingStartState) {}
|
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :
|
||||||
|
stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
|
||||||
|
|
||||||
//! Parse JSON text.
|
//! Parse JSON text.
|
||||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||||
@ -707,14 +701,13 @@ private:
|
|||||||
struct ClearStackOnExit {
|
struct ClearStackOnExit {
|
||||||
explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
|
explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
|
||||||
~ClearStackOnExit() { r_.ClearStack(); }
|
~ClearStackOnExit() { r_.ClearStack(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GenericReader& r_;
|
GenericReader& r_;
|
||||||
ClearStackOnExit(const ClearStackOnExit&);
|
ClearStackOnExit(const ClearStackOnExit&);
|
||||||
ClearStackOnExit& operator=(const ClearStackOnExit&);
|
ClearStackOnExit& operator=(const ClearStackOnExit&);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <unsigned parseFlags, typename InputStream>
|
template<unsigned parseFlags, typename InputStream>
|
||||||
void SkipWhitespaceAndComments(InputStream& is) {
|
void SkipWhitespaceAndComments(InputStream& is) {
|
||||||
SkipWhitespace(is);
|
SkipWhitespace(is);
|
||||||
|
|
||||||
@ -743,7 +736,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == '{');
|
RAPIDJSON_ASSERT(is.Peek() == '{');
|
||||||
is.Take(); // Skip '{'
|
is.Take(); // Skip '{'
|
||||||
@ -796,8 +789,7 @@ private:
|
|||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
|
||||||
break; // This useless break is only for making warning and coverage happy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseFlags & kParseTrailingCommasFlag) {
|
if (parseFlags & kParseTrailingCommasFlag) {
|
||||||
@ -812,7 +804,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse array: [ value, ... ]
|
// Parse array: [ value, ... ]
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseArray(InputStream& is, Handler& handler) {
|
void ParseArray(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == '[');
|
RAPIDJSON_ASSERT(is.Peek() == '[');
|
||||||
is.Take(); // Skip '['
|
is.Take(); // Skip '['
|
||||||
@ -860,7 +852,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseNull(InputStream& is, Handler& handler) {
|
void ParseNull(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == 'n');
|
RAPIDJSON_ASSERT(is.Peek() == 'n');
|
||||||
is.Take();
|
is.Take();
|
||||||
@ -873,7 +865,7 @@ private:
|
|||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseTrue(InputStream& is, Handler& handler) {
|
void ParseTrue(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == 't');
|
RAPIDJSON_ASSERT(is.Peek() == 't');
|
||||||
is.Take();
|
is.Take();
|
||||||
@ -886,7 +878,7 @@ private:
|
|||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseFalse(InputStream& is, Handler& handler) {
|
void ParseFalse(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == 'f');
|
RAPIDJSON_ASSERT(is.Peek() == 'f');
|
||||||
is.Take();
|
is.Take();
|
||||||
@ -899,7 +891,7 @@ private:
|
|||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
|
RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
|
||||||
if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
|
if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
|
||||||
is.Take();
|
is.Take();
|
||||||
@ -910,7 +902,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
|
// Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
|
unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
|
||||||
unsigned codepoint = 0;
|
unsigned codepoint = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
@ -963,7 +955,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parse string and generate String event. Different code paths for kParseInsituFlag.
|
// Parse string and generate String event. Different code paths for kParseInsituFlag.
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
|
void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
|
||||||
internal::StreamLocalCopy<InputStream> copy(is);
|
internal::StreamLocalCopy<InputStream> copy(is);
|
||||||
InputStream& s(copy.s);
|
InputStream& s(copy.s);
|
||||||
@ -973,7 +965,7 @@ private:
|
|||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (parseFlags & kParseInsituFlag) {
|
if (parseFlags & kParseInsituFlag) {
|
||||||
typename InputStream::Ch* head = s.PutBegin();
|
typename InputStream::Ch *head = s.PutBegin();
|
||||||
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
|
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
|
||||||
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;
|
||||||
@ -995,19 +987,19 @@ private:
|
|||||||
|
|
||||||
// Parse string to an output is
|
// Parse string to an output is
|
||||||
// This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
|
// This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
|
||||||
template <unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
|
template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
|
||||||
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
|
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#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
|
||||||
static const char escape[256] = {
|
static const char escape[256] = {
|
||||||
Z16, Z16, 0, 0, '\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
|
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
|
||||||
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
|
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
|
||||||
0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0, 0, 0, '\n', 0,
|
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
|
||||||
0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
|
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
|
||||||
};
|
};
|
||||||
#undef Z16
|
#undef Z16
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
|
// Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
|
||||||
@ -1044,7 +1036,8 @@ private:
|
|||||||
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
||||||
}
|
}
|
||||||
// single low surrogate
|
// single low surrogate
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1066,13 +1059,15 @@ private:
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t offset = is.Tell();
|
size_t offset = is.Tell();
|
||||||
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? !Transcoder<SEncoding, TEncoding>::Validate(is, os) : !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
|
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
|
||||||
|
!Transcoder<SEncoding, TEncoding>::Validate(is, os) :
|
||||||
|
!Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template<typename InputStream, typename OutputStream>
|
||||||
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
|
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
|
||||||
// Do nothing for generic version
|
// Do nothing for generic version
|
||||||
}
|
}
|
||||||
@ -1096,12 +1091,12 @@ private:
|
|||||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||||
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
|
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
|
||||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
|
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
|
||||||
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
|
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||||
@ -1109,13 +1104,13 @@ private:
|
|||||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||||
if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||||
SizeType length;
|
SizeType length;
|
||||||
#ifdef _MSC_VER // Find the index of first escaped
|
#ifdef _MSC_VER // Find the index of first escaped
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
_BitScanForward(&offset, r);
|
_BitScanForward(&offset, r);
|
||||||
length = offset;
|
length = offset;
|
||||||
#else
|
#else
|
||||||
length = static_cast<SizeType>(__builtin_ffs(r) - 1);
|
length = static_cast<SizeType>(__builtin_ffs(r) - 1);
|
||||||
#endif
|
#endif
|
||||||
if (length != 0) {
|
if (length != 0) {
|
||||||
char* q = reinterpret_cast<char*>(os.Push(length));
|
char* q = reinterpret_cast<char*>(os.Push(length));
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
@ -1125,7 +1120,7 @@ private:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(os.Push(16)), s);
|
_mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
@ -1142,7 +1137,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* p = is.src_;
|
char* p = is.src_;
|
||||||
char* q = is.dst_;
|
char *q = is.dst_;
|
||||||
|
|
||||||
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
|
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
||||||
@ -1159,12 +1154,12 @@ private:
|
|||||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||||
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
|
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
|
||||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
|
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
|
||||||
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
|
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||||
|
|
||||||
for (;; p += 16, q += 16) {
|
for (;; p += 16, q += 16) {
|
||||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||||
@ -1179,11 +1174,11 @@ private:
|
|||||||
#else
|
#else
|
||||||
length = static_cast<size_t>(__builtin_ffs(r) - 1);
|
length = static_cast<size_t>(__builtin_ffs(r) - 1);
|
||||||
#endif
|
#endif
|
||||||
for (const char* pend = p + length; p != pend;)
|
for (const char* pend = p + length; p != pend; )
|
||||||
*q++ = *p++;
|
*q++ = *p++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(q), s);
|
_mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
@ -1207,12 +1202,12 @@ private:
|
|||||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||||
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
|
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
|
||||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
|
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
|
||||||
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
|
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||||
@ -1256,7 +1251,7 @@ private:
|
|||||||
const uint8x16_t s3 = vmovq_n_u8(32);
|
const uint8x16_t s3 = vmovq_n_u8(32);
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, s0);
|
uint8x16_t x = vceqq_u8(s, s0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s1));
|
x = vorrq_u8(x, vceqq_u8(s, s1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s2));
|
x = vorrq_u8(x, vceqq_u8(s, s2));
|
||||||
@ -1274,8 +1269,7 @@ private:
|
|||||||
length = 8 + (lz >> 3);
|
length = 8 + (lz >> 3);
|
||||||
escaped = true;
|
escaped = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
length = lz >> 3;
|
length = lz >> 3;
|
||||||
escaped = true;
|
escaped = true;
|
||||||
@ -1290,7 +1284,7 @@ private:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vst1q_u8(reinterpret_cast<uint8_t*>(os.Push(16)), s);
|
vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
@ -1307,7 +1301,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* p = is.src_;
|
char* p = is.src_;
|
||||||
char* q = is.dst_;
|
char *q = is.dst_;
|
||||||
|
|
||||||
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
|
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
|
||||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
||||||
@ -1327,7 +1321,7 @@ private:
|
|||||||
const uint8x16_t s3 = vmovq_n_u8(32);
|
const uint8x16_t s3 = vmovq_n_u8(32);
|
||||||
|
|
||||||
for (;; p += 16, q += 16) {
|
for (;; p += 16, q += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, s0);
|
uint8x16_t x = vceqq_u8(s, s0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s1));
|
x = vorrq_u8(x, vceqq_u8(s, s1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s2));
|
x = vorrq_u8(x, vceqq_u8(s, s2));
|
||||||
@ -1345,19 +1339,18 @@ private:
|
|||||||
length = 8 + (lz >> 3);
|
length = 8 + (lz >> 3);
|
||||||
escaped = true;
|
escaped = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
length = lz >> 3;
|
length = lz >> 3;
|
||||||
escaped = true;
|
escaped = true;
|
||||||
}
|
}
|
||||||
if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
|
if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
|
||||||
for (const char* pend = p + length; p != pend;) {
|
for (const char* pend = p + length; p != pend; ) {
|
||||||
*q++ = *p++;
|
*q++ = *p++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vst1q_u8(reinterpret_cast<uint8_t*>(q), s);
|
vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
@ -1384,7 +1377,7 @@ private:
|
|||||||
const uint8x16_t s3 = vmovq_n_u8(32);
|
const uint8x16_t s3 = vmovq_n_u8(32);
|
||||||
|
|
||||||
for (;; p += 16) {
|
for (;; p += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, s0);
|
uint8x16_t x = vceqq_u8(s, s0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s1));
|
x = vorrq_u8(x, vceqq_u8(s, s1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s2));
|
x = vorrq_u8(x, vceqq_u8(s, s2));
|
||||||
@ -1400,8 +1393,7 @@ private:
|
|||||||
p += 8 + (lz >> 3);
|
p += 8 + (lz >> 3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
p += lz >> 3;
|
p += lz >> 3;
|
||||||
break;
|
break;
|
||||||
@ -1412,10 +1404,10 @@ private:
|
|||||||
}
|
}
|
||||||
#endif // RAPIDJSON_NEON
|
#endif // RAPIDJSON_NEON
|
||||||
|
|
||||||
template <typename InputStream, bool backup, bool pushOnTake>
|
template<typename InputStream, bool backup, bool pushOnTake>
|
||||||
class NumberStream;
|
class NumberStream;
|
||||||
|
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
class NumberStream<InputStream, false, false> {
|
class NumberStream<InputStream, false, false> {
|
||||||
public:
|
public:
|
||||||
typedef typename InputStream::Ch Ch;
|
typedef typename InputStream::Ch Ch;
|
||||||
@ -1437,10 +1429,9 @@ private:
|
|||||||
InputStream& is;
|
InputStream& is;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
|
class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
|
||||||
typedef NumberStream<InputStream, false, false> Base;
|
typedef NumberStream<InputStream, false, false> Base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
|
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
|
||||||
|
|
||||||
@ -1464,24 +1455,24 @@ private:
|
|||||||
StackStream<char> stackStream;
|
StackStream<char> stackStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename InputStream>
|
template<typename InputStream>
|
||||||
class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
|
class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
|
||||||
typedef NumberStream<InputStream, true, false> Base;
|
typedef NumberStream<InputStream, true, false> Base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
|
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
|
||||||
|
|
||||||
RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
|
RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
NumberStream<InputStream,
|
NumberStream<InputStream,
|
||||||
((parseFlags & kParseNumbersAsStringsFlag) != 0) ? ((parseFlags & kParseInsituFlag) == 0) : ((parseFlags & kParseFullPrecisionFlag) != 0),
|
((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
|
||||||
|
((parseFlags & kParseInsituFlag) == 0) :
|
||||||
|
((parseFlags & kParseFullPrecisionFlag) != 0),
|
||||||
(parseFlags & kParseNumbersAsStringsFlag) != 0 &&
|
(parseFlags & kParseNumbersAsStringsFlag) != 0 &&
|
||||||
(parseFlags & kParseInsituFlag) == 0>
|
(parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
|
||||||
s(*this, copy.s);
|
|
||||||
|
|
||||||
size_t startOffset = s.Tell();
|
size_t startOffset = s.Tell();
|
||||||
double d = 0.0;
|
double d = 0.0;
|
||||||
@ -1540,7 +1531,8 @@ private:
|
|||||||
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
|
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
|
||||||
useNanOrInf = true;
|
useNanOrInf = true;
|
||||||
|
|
||||||
if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
|
if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
|
||||||
|
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1754,30 +1746,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse any JSON value
|
// Parse any JSON value
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseValue(InputStream& is, Handler& handler) {
|
void ParseValue(InputStream& is, Handler& handler) {
|
||||||
switch (is.Peek()) {
|
switch (is.Peek()) {
|
||||||
case 'n':
|
case 'n': ParseNull <parseFlags>(is, handler); break;
|
||||||
ParseNull<parseFlags>(is, handler);
|
case 't': ParseTrue <parseFlags>(is, handler); break;
|
||||||
break;
|
case 'f': ParseFalse <parseFlags>(is, handler); break;
|
||||||
case 't':
|
case '"': ParseString<parseFlags>(is, handler); break;
|
||||||
ParseTrue<parseFlags>(is, handler);
|
case '{': ParseObject<parseFlags>(is, handler); break;
|
||||||
break;
|
case '[': ParseArray <parseFlags>(is, handler); break;
|
||||||
case 'f':
|
default :
|
||||||
ParseFalse<parseFlags>(is, handler);
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
ParseString<parseFlags>(is, handler);
|
|
||||||
break;
|
|
||||||
case '{':
|
|
||||||
ParseObject<parseFlags>(is, handler);
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
ParseArray<parseFlags>(is, handler);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ParseNumber<parseFlags>(is, handler);
|
ParseNumber<parseFlags>(is, handler);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,7 +1816,7 @@ private:
|
|||||||
|
|
||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#define N NumberToken
|
#define N NumberToken
|
||||||
#define N16 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
|
#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
|
||||||
// Maps from ASCII to Token
|
// Maps from ASCII to Token
|
||||||
static const unsigned char tokenMap[256] = {
|
static const unsigned char tokenMap[256] = {
|
||||||
N16, // 00~0F
|
N16, // 00~0F
|
||||||
@ -1850,7 +1831,7 @@ private:
|
|||||||
};
|
};
|
||||||
#undef N
|
#undef N
|
||||||
#undef N16
|
#undef N16
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
|
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
|
||||||
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
|
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
|
||||||
@ -1865,12 +1846,14 @@ private:
|
|||||||
{
|
{
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState },
|
IterativeParsingErrorState
|
||||||
|
},
|
||||||
// Error(sink state)
|
// Error(sink state)
|
||||||
{
|
{
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState },
|
IterativeParsingErrorState
|
||||||
|
},
|
||||||
// Start
|
// Start
|
||||||
{
|
{
|
||||||
IterativeParsingArrayInitialState, // Left bracket
|
IterativeParsingArrayInitialState, // Left bracket
|
||||||
@ -1931,7 +1914,8 @@ private:
|
|||||||
{
|
{
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState },
|
IterativeParsingErrorState
|
||||||
|
},
|
||||||
// ArrayInitial
|
// ArrayInitial
|
||||||
{
|
{
|
||||||
IterativeParsingArrayInitialState, // Left bracket(push Element state)
|
IterativeParsingArrayInitialState, // Left bracket(push Element state)
|
||||||
@ -1964,12 +1948,14 @@ private:
|
|||||||
{
|
{
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState },
|
IterativeParsingErrorState
|
||||||
|
},
|
||||||
// Single Value (sink state)
|
// Single Value (sink state)
|
||||||
{
|
{
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||||
IterativeParsingErrorState },
|
IterativeParsingErrorState
|
||||||
|
},
|
||||||
// ElementDelimiter
|
// ElementDelimiter
|
||||||
{
|
{
|
||||||
IterativeParsingArrayInitialState, // Left bracket(push Element state)
|
IterativeParsingArrayInitialState, // Left bracket(push Element state)
|
||||||
@ -2028,7 +2014,8 @@ private:
|
|||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
case IterativeParsingObjectInitialState:
|
case IterativeParsingObjectInitialState:
|
||||||
case IterativeParsingArrayInitialState: {
|
case IterativeParsingArrayInitialState:
|
||||||
|
{
|
||||||
// Push the state(Element or MemeberValue) if we are nested in another array or value of member.
|
// Push the state(Element or MemeberValue) if we are nested in another array or value of member.
|
||||||
// In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
|
// In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
|
||||||
IterativeParsingState n = src;
|
IterativeParsingState n = src;
|
||||||
@ -2088,7 +2075,8 @@ private:
|
|||||||
*stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
|
*stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
case IterativeParsingObjectFinishState: {
|
case IterativeParsingObjectFinishState:
|
||||||
|
{
|
||||||
// Transit from delimiter is only allowed when trailing commas are enabled
|
// Transit from delimiter is only allowed when trailing commas are enabled
|
||||||
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
|
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
|
||||||
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
|
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
|
||||||
@ -2117,7 +2105,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case IterativeParsingArrayFinishState: {
|
case IterativeParsingArrayFinishState:
|
||||||
|
{
|
||||||
// Transit from delimiter is only allowed when trailing commas are enabled
|
// Transit from delimiter is only allowed when trailing commas are enabled
|
||||||
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
|
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
|
||||||
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
|
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
|
||||||
@ -2176,31 +2165,16 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (src) {
|
switch (src) {
|
||||||
case IterativeParsingStartState:
|
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
|
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
|
||||||
return;
|
|
||||||
case IterativeParsingFinishState:
|
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
|
|
||||||
return;
|
|
||||||
case IterativeParsingObjectInitialState:
|
case IterativeParsingObjectInitialState:
|
||||||
case IterativeParsingMemberDelimiterState:
|
case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
|
case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
|
||||||
return;
|
case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
|
||||||
case IterativeParsingMemberKeyState:
|
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
|
|
||||||
return;
|
|
||||||
case IterativeParsingMemberValueState:
|
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
|
||||||
return;
|
|
||||||
case IterativeParsingKeyValueDelimiterState:
|
case IterativeParsingKeyValueDelimiterState:
|
||||||
case IterativeParsingArrayInitialState:
|
case IterativeParsingArrayInitialState:
|
||||||
case IterativeParsingElementDelimiterState:
|
case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
|
default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
|
||||||
return;
|
|
||||||
default:
|
|
||||||
RAPIDJSON_ASSERT(src == IterativeParsingElementState);
|
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2254,7 +2228,7 @@ private:
|
|||||||
}; // class GenericReader
|
}; // class GenericReader
|
||||||
|
|
||||||
//! Reader with UTF8 encoding and default allocator.
|
//! Reader with UTF8 encoding and default allocator.
|
||||||
typedef GenericReader<UTF8<>, UTF8<>> Reader;
|
typedef GenericReader<UTF8<>, UTF8<> > Reader;
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
|
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
|
#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
|
||||||
#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
|
#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
|
#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
|
||||||
@ -60,10 +60,10 @@ RAPIDJSON_DIAG_OFF(effc++)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_OFF(weak - vtables)
|
RAPIDJSON_DIAG_OFF(weak-vtables)
|
||||||
RAPIDJSON_DIAG_OFF(exit - time - destructors)
|
RAPIDJSON_DIAG_OFF(exit-time-destructors)
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat - pedantic)
|
RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
|
||||||
RAPIDJSON_DIAG_OFF(variadic - macros)
|
RAPIDJSON_DIAG_OFF(variadic-macros)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
#endif
|
#endif
|
||||||
@ -77,29 +77,29 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
inline void PrintInvalidKeyword(const char* keyword) {
|
inline void PrintInvalidKeyword(const char* keyword) {
|
||||||
printf("Fail keyword: %s\n", keyword);
|
printf("Fail keyword: %s\n", keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PrintInvalidKeyword(const wchar_t* keyword) {
|
inline void PrintInvalidKeyword(const wchar_t* keyword) {
|
||||||
wprintf(L"Fail keyword: %ls\n", keyword);
|
wprintf(L"Fail keyword: %ls\n", keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PrintInvalidDocument(const char* document) {
|
inline void PrintInvalidDocument(const char* document) {
|
||||||
printf("Fail document: %s\n\n", document);
|
printf("Fail document: %s\n\n", document);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PrintInvalidDocument(const wchar_t* document) {
|
inline void PrintInvalidDocument(const wchar_t* document) {
|
||||||
wprintf(L"Fail document: %ls\n\n", document);
|
wprintf(L"Fail document: %ls\n\n", document);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
|
inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
|
||||||
printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
|
printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
|
inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
|
||||||
wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
|
wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@ -114,13 +114,13 @@ namespace internal {
|
|||||||
#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
|
#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RAPIDJSON_INVALID_KEYWORD_RETURN(code) \
|
#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\
|
||||||
RAPIDJSON_MULTILINEMACRO_BEGIN \
|
RAPIDJSON_MULTILINEMACRO_BEGIN\
|
||||||
context.invalidCode = code; \
|
context.invalidCode = code;\
|
||||||
context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString(); \
|
context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\
|
||||||
RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword); \
|
RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\
|
||||||
return false; \
|
return false;\
|
||||||
RAPIDJSON_MULTILINEMACRO_END
|
RAPIDJSON_MULTILINEMACRO_END
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ValidateFlag
|
// ValidateFlag
|
||||||
@ -152,26 +152,26 @@ class GenericSchemaDocument;
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename SchemaDocumentType>
|
template <typename SchemaDocumentType>
|
||||||
class Schema;
|
class Schema;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ISchemaValidator
|
// ISchemaValidator
|
||||||
|
|
||||||
class ISchemaValidator {
|
class ISchemaValidator {
|
||||||
public:
|
public:
|
||||||
virtual ~ISchemaValidator() {}
|
virtual ~ISchemaValidator() {}
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsValid() const = 0;
|
||||||
virtual void SetValidateFlags(unsigned flags) = 0;
|
virtual void SetValidateFlags(unsigned flags) = 0;
|
||||||
virtual unsigned GetValidateFlags() const = 0;
|
virtual unsigned GetValidateFlags() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ISchemaStateFactory
|
// ISchemaStateFactory
|
||||||
|
|
||||||
template <typename SchemaType>
|
template <typename SchemaType>
|
||||||
class ISchemaStateFactory {
|
class ISchemaStateFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~ISchemaStateFactory() {}
|
virtual ~ISchemaStateFactory() {}
|
||||||
virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0;
|
virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0;
|
||||||
virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
|
virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
|
||||||
@ -180,14 +180,14 @@ namespace internal {
|
|||||||
virtual void DestroryHasher(void* hasher) = 0;
|
virtual void DestroryHasher(void* hasher) = 0;
|
||||||
virtual void* MallocState(size_t size) = 0;
|
virtual void* MallocState(size_t size) = 0;
|
||||||
virtual void FreeState(void* p) = 0;
|
virtual void FreeState(void* p) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// IValidationErrorHandler
|
// IValidationErrorHandler
|
||||||
|
|
||||||
template <typename SchemaType>
|
template <typename SchemaType>
|
||||||
class IValidationErrorHandler {
|
class IValidationErrorHandler {
|
||||||
public:
|
public:
|
||||||
typedef typename SchemaType::Ch Ch;
|
typedef typename SchemaType::Ch Ch;
|
||||||
typedef typename SchemaType::SValue SValue;
|
typedef typename SchemaType::SValue SValue;
|
||||||
|
|
||||||
@ -235,52 +235,30 @@ namespace internal {
|
|||||||
virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
|
virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
|
||||||
virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0;
|
virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0;
|
||||||
virtual void Disallowed() = 0;
|
virtual void Disallowed() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Hasher
|
// Hasher
|
||||||
|
|
||||||
// For comparison of compound value
|
// For comparison of compound value
|
||||||
template <typename Encoding, typename Allocator>
|
template<typename Encoding, typename Allocator>
|
||||||
class Hasher {
|
class Hasher {
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
|
Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
|
||||||
|
|
||||||
bool Null() { return WriteType(kNullType); }
|
bool Null() { return WriteType(kNullType); }
|
||||||
bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
|
bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
|
||||||
bool Int(int i) {
|
bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
|
||||||
Number n;
|
bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
|
||||||
n.u.i = i;
|
bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
|
||||||
n.d = static_cast<double>(i);
|
bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
|
||||||
return WriteNumber(n);
|
|
||||||
}
|
|
||||||
bool Uint(unsigned u) {
|
|
||||||
Number n;
|
|
||||||
n.u.u = u;
|
|
||||||
n.d = static_cast<double>(u);
|
|
||||||
return WriteNumber(n);
|
|
||||||
}
|
|
||||||
bool Int64(int64_t i) {
|
|
||||||
Number n;
|
|
||||||
n.u.i = i;
|
|
||||||
n.d = static_cast<double>(i);
|
|
||||||
return WriteNumber(n);
|
|
||||||
}
|
|
||||||
bool Uint64(uint64_t u) {
|
|
||||||
Number n;
|
|
||||||
n.u.u = u;
|
|
||||||
n.d = static_cast<double>(u);
|
|
||||||
return WriteNumber(n);
|
|
||||||
}
|
|
||||||
bool Double(double d) {
|
bool Double(double d) {
|
||||||
Number n;
|
Number n;
|
||||||
if (d < 0)
|
if (d < 0) n.u.i = static_cast<int64_t>(d);
|
||||||
n.u.i = static_cast<int64_t>(d);
|
else n.u.u = static_cast<uint64_t>(d);
|
||||||
else
|
|
||||||
n.u.u = static_cast<uint64_t>(d);
|
|
||||||
n.d = d;
|
n.d = d;
|
||||||
return WriteNumber(n);
|
return WriteNumber(n);
|
||||||
}
|
}
|
||||||
@ -323,13 +301,13 @@ namespace internal {
|
|||||||
return *stack_.template Top<uint64_t>();
|
return *stack_.template Top<uint64_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const size_t kDefaultSize = 256;
|
static const size_t kDefaultSize = 256;
|
||||||
struct Number {
|
struct Number {
|
||||||
union U {
|
union U {
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
int64_t i;
|
int64_t i;
|
||||||
} u;
|
}u;
|
||||||
double d;
|
double d;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -355,13 +333,13 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stack<Allocator> stack_;
|
Stack<Allocator> stack_;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// SchemaValidationContext
|
// SchemaValidationContext
|
||||||
|
|
||||||
template <typename SchemaDocumentType>
|
template <typename SchemaDocumentType>
|
||||||
struct SchemaValidationContext {
|
struct SchemaValidationContext {
|
||||||
typedef Schema<SchemaDocumentType> SchemaType;
|
typedef Schema<SchemaDocumentType> SchemaType;
|
||||||
typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
|
typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
|
||||||
typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
|
typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
|
||||||
@ -374,7 +352,8 @@ namespace internal {
|
|||||||
kPatternValidatorWithAdditionalProperty
|
kPatternValidatorWithAdditionalProperty
|
||||||
};
|
};
|
||||||
|
|
||||||
SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : factory(f),
|
SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) :
|
||||||
|
factory(f),
|
||||||
error_handler(eh),
|
error_handler(eh),
|
||||||
schema(s),
|
schema(s),
|
||||||
valueSchema(),
|
valueSchema(),
|
||||||
@ -392,7 +371,8 @@ namespace internal {
|
|||||||
propertyExist(),
|
propertyExist(),
|
||||||
inArray(false),
|
inArray(false),
|
||||||
valueUniqueness(false),
|
valueUniqueness(false),
|
||||||
arrayUniqueness(false) {
|
arrayUniqueness(false)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~SchemaValidationContext() {
|
~SchemaValidationContext() {
|
||||||
@ -435,14 +415,14 @@ namespace internal {
|
|||||||
bool inArray;
|
bool inArray;
|
||||||
bool valueUniqueness;
|
bool valueUniqueness;
|
||||||
bool arrayUniqueness;
|
bool arrayUniqueness;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Schema
|
// Schema
|
||||||
|
|
||||||
template <typename SchemaDocumentType>
|
template <typename SchemaDocumentType>
|
||||||
class Schema {
|
class Schema {
|
||||||
public:
|
public:
|
||||||
typedef typename SchemaDocumentType::ValueType ValueType;
|
typedef typename SchemaDocumentType::ValueType ValueType;
|
||||||
typedef typename SchemaDocumentType::AllocatorType AllocatorType;
|
typedef typename SchemaDocumentType::AllocatorType AllocatorType;
|
||||||
typedef typename SchemaDocumentType::PointerType PointerType;
|
typedef typename SchemaDocumentType::PointerType PointerType;
|
||||||
@ -454,7 +434,8 @@ namespace internal {
|
|||||||
typedef IValidationErrorHandler<Schema> ErrorHandler;
|
typedef IValidationErrorHandler<Schema> ErrorHandler;
|
||||||
friend class GenericSchemaDocument<ValueType, AllocatorType>;
|
friend class GenericSchemaDocument<ValueType, AllocatorType>;
|
||||||
|
|
||||||
Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : allocator_(allocator),
|
Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
|
||||||
|
allocator_(allocator),
|
||||||
uri_(schemaDocument->GetURI(), *allocator),
|
uri_(schemaDocument->GetURI(), *allocator),
|
||||||
pointer_(p, allocator),
|
pointer_(p, allocator),
|
||||||
typeless_(schemaDocument->GetTypeless()),
|
typeless_(schemaDocument->GetTypeless()),
|
||||||
@ -488,7 +469,8 @@ namespace internal {
|
|||||||
maxLength_(~SizeType(0)),
|
maxLength_(~SizeType(0)),
|
||||||
exclusiveMinimum_(false),
|
exclusiveMinimum_(false),
|
||||||
exclusiveMaximum_(false),
|
exclusiveMaximum_(false),
|
||||||
defaultValueLength_(0) {
|
defaultValueLength_(0)
|
||||||
|
{
|
||||||
typedef typename ValueType::ConstValueIterator ConstValueIterator;
|
typedef typename ValueType::ConstValueIterator ConstValueIterator;
|
||||||
typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
|
typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
|
||||||
|
|
||||||
@ -508,7 +490,7 @@ namespace internal {
|
|||||||
if (v->IsArray() && v->Size() > 0) {
|
if (v->IsArray() && v->Size() > 0) {
|
||||||
enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
|
enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
|
||||||
for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
|
for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
|
||||||
typedef Hasher<EncodingType, MemoryPoolAllocator<>> EnumHasherType;
|
typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
|
||||||
char buffer[256u + 24];
|
char buffer[256u + 24];
|
||||||
MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
|
MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
|
||||||
EnumHasherType h(&hasherAllocator, 256);
|
EnumHasherType h(&hasherAllocator, 256);
|
||||||
@ -608,7 +590,7 @@ namespace internal {
|
|||||||
if (FindPropertyIndex(itr->name, &sourceIndex)) {
|
if (FindPropertyIndex(itr->name, &sourceIndex)) {
|
||||||
if (itr->value.IsArray()) {
|
if (itr->value.IsArray()) {
|
||||||
properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
|
properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
|
||||||
std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool) * propertyCount_);
|
std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
|
||||||
for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
|
for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
|
||||||
SizeType targetIndex;
|
SizeType targetIndex;
|
||||||
if (FindPropertyIndex(*targetItr, &targetIndex))
|
if (FindPropertyIndex(*targetItr, &targetIndex))
|
||||||
@ -687,6 +669,7 @@ namespace internal {
|
|||||||
if (const ValueType* v = GetMember(value, GetDefaultValueString()))
|
if (const ValueType* v = GetMember(value, GetDefaultValueString()))
|
||||||
if (v->IsString())
|
if (v->IsString())
|
||||||
defaultValueLength_ = v->GetStringLength();
|
defaultValueLength_ = v->GetStringLength();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Schema() {
|
~Schema() {
|
||||||
@ -818,8 +801,7 @@ namespace internal {
|
|||||||
if (oneValid) {
|
if (oneValid) {
|
||||||
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
|
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
|
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
oneValid = true;
|
oneValid = true;
|
||||||
}
|
}
|
||||||
if (!oneValid) {
|
if (!oneValid) {
|
||||||
@ -1000,7 +982,7 @@ namespace internal {
|
|||||||
context.error_handler.StartMissingProperties();
|
context.error_handler.StartMissingProperties();
|
||||||
for (SizeType index = 0; index < propertyCount_; index++)
|
for (SizeType index = 0; index < propertyCount_; index++)
|
||||||
if (properties_[index].required && !context.propertyExist[index])
|
if (properties_[index].required && !context.propertyExist[index])
|
||||||
if (properties_[index].schema->defaultValueLength_ == 0)
|
if (properties_[index].schema->defaultValueLength_ == 0 )
|
||||||
context.error_handler.AddMissingProperty(properties_[index].name);
|
context.error_handler.AddMissingProperty(properties_[index].name);
|
||||||
if (context.error_handler.EndMissingProperties())
|
if (context.error_handler.EndMissingProperties())
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired);
|
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired);
|
||||||
@ -1072,74 +1054,48 @@ namespace internal {
|
|||||||
|
|
||||||
static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
|
static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
|
||||||
switch (validateErrorCode) {
|
switch (validateErrorCode) {
|
||||||
case kValidateErrorMultipleOf:
|
case kValidateErrorMultipleOf: return GetMultipleOfString();
|
||||||
return GetMultipleOfString();
|
case kValidateErrorMaximum: return GetMaximumString();
|
||||||
case kValidateErrorMaximum:
|
case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same
|
||||||
return GetMaximumString();
|
case kValidateErrorMinimum: return GetMinimumString();
|
||||||
case kValidateErrorExclusiveMaximum:
|
case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same
|
||||||
return GetMaximumString(); // Same
|
|
||||||
case kValidateErrorMinimum:
|
|
||||||
return GetMinimumString();
|
|
||||||
case kValidateErrorExclusiveMinimum:
|
|
||||||
return GetMinimumString(); // Same
|
|
||||||
|
|
||||||
case kValidateErrorMaxLength:
|
case kValidateErrorMaxLength: return GetMaxLengthString();
|
||||||
return GetMaxLengthString();
|
case kValidateErrorMinLength: return GetMinLengthString();
|
||||||
case kValidateErrorMinLength:
|
case kValidateErrorPattern: return GetPatternString();
|
||||||
return GetMinLengthString();
|
|
||||||
case kValidateErrorPattern:
|
|
||||||
return GetPatternString();
|
|
||||||
|
|
||||||
case kValidateErrorMaxItems:
|
case kValidateErrorMaxItems: return GetMaxItemsString();
|
||||||
return GetMaxItemsString();
|
case kValidateErrorMinItems: return GetMinItemsString();
|
||||||
case kValidateErrorMinItems:
|
case kValidateErrorUniqueItems: return GetUniqueItemsString();
|
||||||
return GetMinItemsString();
|
case kValidateErrorAdditionalItems: return GetAdditionalItemsString();
|
||||||
case kValidateErrorUniqueItems:
|
|
||||||
return GetUniqueItemsString();
|
|
||||||
case kValidateErrorAdditionalItems:
|
|
||||||
return GetAdditionalItemsString();
|
|
||||||
|
|
||||||
case kValidateErrorMaxProperties:
|
case kValidateErrorMaxProperties: return GetMaxPropertiesString();
|
||||||
return GetMaxPropertiesString();
|
case kValidateErrorMinProperties: return GetMinPropertiesString();
|
||||||
case kValidateErrorMinProperties:
|
case kValidateErrorRequired: return GetRequiredString();
|
||||||
return GetMinPropertiesString();
|
case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString();
|
||||||
case kValidateErrorRequired:
|
case kValidateErrorPatternProperties: return GetPatternPropertiesString();
|
||||||
return GetRequiredString();
|
case kValidateErrorDependencies: return GetDependenciesString();
|
||||||
case kValidateErrorAdditionalProperties:
|
|
||||||
return GetAdditionalPropertiesString();
|
|
||||||
case kValidateErrorPatternProperties:
|
|
||||||
return GetPatternPropertiesString();
|
|
||||||
case kValidateErrorDependencies:
|
|
||||||
return GetDependenciesString();
|
|
||||||
|
|
||||||
case kValidateErrorEnum:
|
case kValidateErrorEnum: return GetEnumString();
|
||||||
return GetEnumString();
|
case kValidateErrorType: return GetTypeString();
|
||||||
case kValidateErrorType:
|
|
||||||
return GetTypeString();
|
|
||||||
|
|
||||||
case kValidateErrorOneOf:
|
case kValidateErrorOneOf: return GetOneOfString();
|
||||||
return GetOneOfString();
|
case kValidateErrorOneOfMatch: return GetOneOfString(); // Same
|
||||||
case kValidateErrorOneOfMatch:
|
case kValidateErrorAllOf: return GetAllOfString();
|
||||||
return GetOneOfString(); // Same
|
case kValidateErrorAnyOf: return GetAnyOfString();
|
||||||
case kValidateErrorAllOf:
|
case kValidateErrorNot: return GetNotString();
|
||||||
return GetAllOfString();
|
|
||||||
case kValidateErrorAnyOf:
|
|
||||||
return GetAnyOfString();
|
|
||||||
case kValidateErrorNot:
|
|
||||||
return GetNotString();
|
|
||||||
|
|
||||||
default:
|
default: return GetNullString();
|
||||||
return GetNullString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate functions for string literal according to Ch
|
// Generate functions for string literal according to Ch
|
||||||
#define RAPIDJSON_STRING_(name, ...) \
|
#define RAPIDJSON_STRING_(name, ...) \
|
||||||
static const ValueType& Get##name##String() { \
|
static const ValueType& Get##name##String() {\
|
||||||
static const Ch s[] = { __VA_ARGS__, '\0' }; \
|
static const Ch s[] = { __VA_ARGS__, '\0' };\
|
||||||
static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
|
static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
|
||||||
return v; \
|
return v;\
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
|
RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
|
||||||
@ -1179,7 +1135,7 @@ namespace internal {
|
|||||||
|
|
||||||
#undef RAPIDJSON_STRING_
|
#undef RAPIDJSON_STRING_
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum SchemaValueType {
|
enum SchemaValueType {
|
||||||
kNullSchemaType,
|
kNullSchemaType,
|
||||||
kBooleanSchemaType,
|
kBooleanSchemaType,
|
||||||
@ -1239,7 +1195,7 @@ namespace internal {
|
|||||||
PointerType q = p.Append(name, allocator_);
|
PointerType q = p.Append(name, allocator_);
|
||||||
out.count = v->Size();
|
out.count = v->Size();
|
||||||
out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
|
out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
|
||||||
memset(out.schemas, 0, sizeof(Schema*) * out.count);
|
memset(out.schemas, 0, sizeof(Schema*)* out.count);
|
||||||
for (SizeType i = 0; i < out.count; i++)
|
for (SizeType i = 0; i < out.count; i++)
|
||||||
schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
|
schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
|
||||||
out.begin = validatorCount_;
|
out.begin = validatorCount_;
|
||||||
@ -1263,7 +1219,7 @@ namespace internal {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType) {
|
static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
|
||||||
GenericRegexSearch<RegexType> rs(*pattern);
|
GenericRegexSearch<RegexType> rs(*pattern);
|
||||||
return rs.Search(str);
|
return rs.Search(str);
|
||||||
}
|
}
|
||||||
@ -1271,7 +1227,7 @@ namespace internal {
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
RegexType* CreatePattern(const ValueType& value) {
|
RegexType* CreatePattern(const ValueType& value) {
|
||||||
if (value.IsString()) {
|
if (value.IsString()) {
|
||||||
RegexType* r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
|
RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
|
||||||
try {
|
try {
|
||||||
return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
|
return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
|
||||||
}
|
}
|
||||||
@ -1282,7 +1238,7 @@ namespace internal {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType length) {
|
static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
|
||||||
std::match_results<const Ch*> r;
|
std::match_results<const Ch*> r;
|
||||||
return std::regex_search(str, str + length, r, *pattern);
|
return std::regex_search(str, str + length, r, *pattern);
|
||||||
}
|
}
|
||||||
@ -1290,24 +1246,17 @@ namespace internal {
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
RegexType* CreatePattern(const ValueType&) { return 0; }
|
RegexType* CreatePattern(const ValueType&) { return 0; }
|
||||||
|
|
||||||
static bool IsPatternMatch(const RegexType*, const Ch*, SizeType) { return true; }
|
static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
|
||||||
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
|
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
|
||||||
|
|
||||||
void AddType(const ValueType& type) {
|
void AddType(const ValueType& type) {
|
||||||
if (type == GetNullString())
|
if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
|
||||||
type_ |= 1 << kNullSchemaType;
|
else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
|
||||||
else if (type == GetBooleanString())
|
else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
|
||||||
type_ |= 1 << kBooleanSchemaType;
|
else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
|
||||||
else if (type == GetObjectString())
|
else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
|
||||||
type_ |= 1 << kObjectSchemaType;
|
else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
|
||||||
else if (type == GetArrayString())
|
else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
|
||||||
type_ |= 1 << kArraySchemaType;
|
|
||||||
else if (type == GetStringString())
|
|
||||||
type_ |= 1 << kStringSchemaType;
|
|
||||||
else if (type == GetIntegerString())
|
|
||||||
type_ |= 1 << kIntegerSchemaType;
|
|
||||||
else if (type == GetNumberString())
|
|
||||||
type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateParallelValidator(Context& context) const {
|
bool CreateParallelValidator(Context& context) const {
|
||||||
@ -1353,7 +1302,8 @@ namespace internal {
|
|||||||
const Ch* str = name.GetString();
|
const Ch* str = name.GetString();
|
||||||
for (SizeType index = 0; index < propertyCount_; index++)
|
for (SizeType index = 0; index < propertyCount_; index++)
|
||||||
if (properties_[index].name.GetStringLength() == len &&
|
if (properties_[index].name.GetStringLength() == len &&
|
||||||
(std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) {
|
(std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
|
||||||
|
{
|
||||||
*outIndex = index;
|
*outIndex = index;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1388,8 +1338,7 @@ namespace internal {
|
|||||||
RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
|
RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (maximum_.IsUint64()) {
|
else if (maximum_.IsUint64()) { }
|
||||||
}
|
|
||||||
/* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
|
/* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
|
||||||
else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
|
else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
|
||||||
return false;
|
return false;
|
||||||
@ -1494,10 +1443,8 @@ namespace internal {
|
|||||||
if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
|
if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
|
||||||
if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
|
if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
|
||||||
|
|
||||||
if (type_ & (1 << kNumberSchemaType))
|
if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
|
||||||
eh.AddExpectedType(GetNumberString());
|
else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
|
||||||
else if (type_ & (1 << kIntegerSchemaType))
|
|
||||||
eh.AddExpectedType(GetIntegerString());
|
|
||||||
|
|
||||||
eh.EndDisallowedType(actualType);
|
eh.EndDisallowedType(actualType);
|
||||||
}
|
}
|
||||||
@ -1571,10 +1518,10 @@ namespace internal {
|
|||||||
bool exclusiveMaximum_;
|
bool exclusiveMaximum_;
|
||||||
|
|
||||||
SizeType defaultValueLength_;
|
SizeType defaultValueLength_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Stack, typename Ch>
|
template<typename Stack, typename Ch>
|
||||||
struct TokenHelper {
|
struct TokenHelper {
|
||||||
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
|
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
|
||||||
*documentStack.template Push<Ch>() = '/';
|
*documentStack.template Push<Ch>() = '/';
|
||||||
char buffer[21];
|
char buffer[21];
|
||||||
@ -1582,26 +1529,26 @@ namespace internal {
|
|||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
*documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
|
*documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Partial specialized version for char to prevent buffer copying.
|
// Partial specialized version for char to prevent buffer copying.
|
||||||
template <typename Stack>
|
template <typename Stack>
|
||||||
struct TokenHelper<Stack, char> {
|
struct TokenHelper<Stack, char> {
|
||||||
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
|
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
|
||||||
if (sizeof(SizeType) == 4) {
|
if (sizeof(SizeType) == 4) {
|
||||||
char* buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
|
char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
|
||||||
*buffer++ = '/';
|
*buffer++ = '/';
|
||||||
const char* end = internal::u32toa(index, buffer);
|
const char* end = internal::u32toa(index, buffer);
|
||||||
documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
|
documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char* buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
|
char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
|
||||||
*buffer++ = '/';
|
*buffer++ = '/';
|
||||||
const char* end = internal::u64toa(index, buffer);
|
const char* end = internal::u64toa(index, buffer);
|
||||||
documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
|
documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@ -1655,17 +1602,19 @@ public:
|
|||||||
\param allocator An optional allocator instance for allocating memory. Can be null.
|
\param allocator An optional allocator instance for allocating memory. Can be null.
|
||||||
*/
|
*/
|
||||||
explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
|
explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
|
||||||
IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : remoteProvider_(remoteProvider),
|
IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
|
||||||
|
remoteProvider_(remoteProvider),
|
||||||
allocator_(allocator),
|
allocator_(allocator),
|
||||||
ownAllocator_(),
|
ownAllocator_(),
|
||||||
root_(),
|
root_(),
|
||||||
typeless_(),
|
typeless_(),
|
||||||
schemaMap_(allocator, kInitialSchemaMapSize),
|
schemaMap_(allocator, kInitialSchemaMapSize),
|
||||||
schemaRef_(allocator, kInitialSchemaRefSize) {
|
schemaRef_(allocator, kInitialSchemaRefSize)
|
||||||
|
{
|
||||||
if (!allocator_)
|
if (!allocator_)
|
||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||||
|
|
||||||
Ch noUri[1] = { 0 };
|
Ch noUri[1] = {0};
|
||||||
uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
|
uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
|
||||||
|
|
||||||
typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
|
typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
|
||||||
@ -1700,14 +1649,16 @@ public:
|
|||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
//! Move constructor in C++11
|
//! Move constructor in C++11
|
||||||
GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : remoteProvider_(rhs.remoteProvider_),
|
GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
|
||||||
|
remoteProvider_(rhs.remoteProvider_),
|
||||||
allocator_(rhs.allocator_),
|
allocator_(rhs.allocator_),
|
||||||
ownAllocator_(rhs.ownAllocator_),
|
ownAllocator_(rhs.ownAllocator_),
|
||||||
root_(rhs.root_),
|
root_(rhs.root_),
|
||||||
typeless_(rhs.typeless_),
|
typeless_(rhs.typeless_),
|
||||||
schemaMap_(std::move(rhs.schemaMap_)),
|
schemaMap_(std::move(rhs.schemaMap_)),
|
||||||
schemaRef_(std::move(rhs.schemaRef_)),
|
schemaRef_(std::move(rhs.schemaRef_)),
|
||||||
uri_(std::move(rhs.uri_)) {
|
uri_(std::move(rhs.uri_))
|
||||||
|
{
|
||||||
rhs.remoteProvider_ = 0;
|
rhs.remoteProvider_ = 0;
|
||||||
rhs.allocator_ = 0;
|
rhs.allocator_ = 0;
|
||||||
rhs.ownAllocator_ = 0;
|
rhs.ownAllocator_ = 0;
|
||||||
@ -1740,7 +1691,7 @@ private:
|
|||||||
GenericSchemaDocument& operator=(const GenericSchemaDocument&);
|
GenericSchemaDocument& operator=(const GenericSchemaDocument&);
|
||||||
|
|
||||||
struct SchemaRefEntry {
|
struct SchemaRefEntry {
|
||||||
SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator* allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
|
SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
|
||||||
PointerType source;
|
PointerType source;
|
||||||
PointerType target;
|
PointerType target;
|
||||||
const SchemaType** schema;
|
const SchemaType** schema;
|
||||||
@ -1855,8 +1806,8 @@ private:
|
|||||||
static const size_t kInitialSchemaRefSize = 64;
|
static const size_t kInitialSchemaRefSize = 64;
|
||||||
|
|
||||||
IRemoteSchemaDocumentProviderType* remoteProvider_;
|
IRemoteSchemaDocumentProviderType* remoteProvider_;
|
||||||
Allocator* allocator_;
|
Allocator *allocator_;
|
||||||
Allocator* ownAllocator_;
|
Allocator *ownAllocator_;
|
||||||
const SchemaType* root_; //!< Root schema.
|
const SchemaType* root_; //!< Root schema.
|
||||||
SchemaType* typeless_;
|
SchemaType* typeless_;
|
||||||
internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
|
internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
|
||||||
@ -1888,7 +1839,8 @@ template <
|
|||||||
typename SchemaDocumentType,
|
typename SchemaDocumentType,
|
||||||
typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
|
typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
|
||||||
typename StateAllocator = CrtAllocator>
|
typename StateAllocator = CrtAllocator>
|
||||||
class GenericSchemaValidator : public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
|
class GenericSchemaValidator :
|
||||||
|
public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
|
||||||
public internal::ISchemaValidator,
|
public internal::ISchemaValidator,
|
||||||
public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
|
public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
|
||||||
public:
|
public:
|
||||||
@ -1912,7 +1864,8 @@ public:
|
|||||||
StateAllocator* allocator = 0,
|
StateAllocator* allocator = 0,
|
||||||
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
||||||
: schemaDocument_(&schemaDocument),
|
:
|
||||||
|
schemaDocument_(&schemaDocument),
|
||||||
root_(schemaDocument.GetRoot()),
|
root_(schemaDocument.GetRoot()),
|
||||||
stateAllocator_(allocator),
|
stateAllocator_(allocator),
|
||||||
ownStateAllocator_(0),
|
ownStateAllocator_(0),
|
||||||
@ -1925,8 +1878,7 @@ public:
|
|||||||
valid_(true),
|
valid_(true),
|
||||||
flags_(kValidateDefaultFlags)
|
flags_(kValidateDefaultFlags)
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
,
|
, depth_(0)
|
||||||
depth_(0)
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1944,7 +1896,8 @@ public:
|
|||||||
StateAllocator* allocator = 0,
|
StateAllocator* allocator = 0,
|
||||||
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
||||||
: schemaDocument_(&schemaDocument),
|
:
|
||||||
|
schemaDocument_(&schemaDocument),
|
||||||
root_(schemaDocument.GetRoot()),
|
root_(schemaDocument.GetRoot()),
|
||||||
stateAllocator_(allocator),
|
stateAllocator_(allocator),
|
||||||
ownStateAllocator_(0),
|
ownStateAllocator_(0),
|
||||||
@ -1957,8 +1910,7 @@ public:
|
|||||||
valid_(true),
|
valid_(true),
|
||||||
flags_(kValidateDefaultFlags)
|
flags_(kValidateDefaultFlags)
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
,
|
, depth_(0)
|
||||||
depth_(0)
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -2216,10 +2168,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define RAPIDJSON_STRING_(name, ...) \
|
#define RAPIDJSON_STRING_(name, ...) \
|
||||||
static const StringRefType& Get##name##String() { \
|
static const StringRefType& Get##name##String() {\
|
||||||
static const Ch s[] = { __VA_ARGS__, '\0' }; \
|
static const Ch s[] = { __VA_ARGS__, '\0' };\
|
||||||
static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
|
static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
|
||||||
return v; \
|
return v;\
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
|
RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
|
||||||
@ -2237,52 +2189,54 @@ public:
|
|||||||
|
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
|
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
|
||||||
RAPIDJSON_MULTILINEMACRO_BEGIN \
|
RAPIDJSON_MULTILINEMACRO_BEGIN\
|
||||||
*documentStack_.template Push<Ch>() = '\0'; \
|
*documentStack_.template Push<Ch>() = '\0';\
|
||||||
documentStack_.template Pop<Ch>(1); \
|
documentStack_.template Pop<Ch>(1);\
|
||||||
internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>()); \
|
internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
|
||||||
RAPIDJSON_MULTILINEMACRO_END
|
RAPIDJSON_MULTILINEMACRO_END
|
||||||
#else
|
#else
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
|
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1) \
|
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
|
||||||
if (!valid_) return false; \
|
if (!valid_) return false; \
|
||||||
if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) { \
|
if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\
|
||||||
RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_(); \
|
RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
|
||||||
return valid_ = false; \
|
return valid_ = false;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2) \
|
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
|
||||||
for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) { \
|
for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
|
||||||
if (context->hasher) \
|
if (context->hasher)\
|
||||||
static_cast<HasherType*>(context->hasher)->method arg2; \
|
static_cast<HasherType*>(context->hasher)->method arg2;\
|
||||||
if (context->validators) \
|
if (context->validators)\
|
||||||
for (SizeType i_ = 0; i_ < context->validatorCount; i_++) \
|
for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
|
||||||
static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2; \
|
static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
|
||||||
if (context->patternPropertiesValidators) \
|
if (context->patternPropertiesValidators)\
|
||||||
for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++) \
|
for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
|
||||||
static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2; \
|
static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2) \
|
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
|
||||||
valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2); \
|
valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\
|
||||||
return valid_;
|
return valid_;
|
||||||
|
|
||||||
#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
|
#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
|
||||||
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1); \
|
RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
|
||||||
RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2); \
|
RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
|
||||||
RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)
|
RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
|
||||||
|
|
||||||
bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ()); }
|
bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
|
||||||
bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
|
bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
|
||||||
bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
|
bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
|
||||||
bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
|
bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
|
||||||
bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
|
bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
|
||||||
bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
|
bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
|
||||||
bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
|
bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
|
||||||
bool RawNumber(const Ch* str, SizeType length, bool copy) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
bool RawNumber(const Ch* str, SizeType length, bool copy)
|
||||||
bool String(const Ch* str, SizeType length, bool copy) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
{ RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
||||||
|
bool String(const Ch* str, SizeType length, bool copy)
|
||||||
|
{ RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
||||||
|
|
||||||
bool StartObject() {
|
bool StartObject() {
|
||||||
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
|
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
|
||||||
@ -2377,7 +2331,8 @@ private:
|
|||||||
StateAllocator* allocator = 0,
|
StateAllocator* allocator = 0,
|
||||||
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
||||||
: schemaDocument_(&schemaDocument),
|
:
|
||||||
|
schemaDocument_(&schemaDocument),
|
||||||
root_(root),
|
root_(root),
|
||||||
stateAllocator_(allocator),
|
stateAllocator_(allocator),
|
||||||
ownStateAllocator_(0),
|
ownStateAllocator_(0),
|
||||||
@ -2390,8 +2345,7 @@ private:
|
|||||||
valid_(true),
|
valid_(true),
|
||||||
flags_(kValidateDefaultFlags)
|
flags_(kValidateDefaultFlags)
|
||||||
#if RAPIDJSON_SCHEMA_VERBOSE
|
#if RAPIDJSON_SCHEMA_VERBOSE
|
||||||
,
|
, depth_(depth)
|
||||||
depth_(depth)
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (basePath && basePathSize)
|
if (basePath && basePathSize)
|
||||||
@ -2469,8 +2423,7 @@ private:
|
|||||||
// Cleanup before returning if continuing
|
// Cleanup before returning if continuing
|
||||||
if (GetContinueOnErrors()) {
|
if (GetContinueOnErrors()) {
|
||||||
a->PushBack(h, GetStateAllocator());
|
a->PushBack(h, GetStateAllocator());
|
||||||
while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
|
while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/');
|
||||||
;
|
|
||||||
}
|
}
|
||||||
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems);
|
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems);
|
||||||
}
|
}
|
||||||
@ -2518,8 +2471,7 @@ private:
|
|||||||
PointerType instancePointer = GetInvalidDocumentPointer();
|
PointerType instancePointer = GetInvalidDocumentPointer();
|
||||||
((parent && instancePointer.GetTokenCount() > 0)
|
((parent && instancePointer.GetTokenCount() > 0)
|
||||||
? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
|
? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
|
||||||
: instancePointer)
|
: instancePointer).StringifyUriFragment(sb);
|
||||||
.StringifyUriFragment(sb);
|
|
||||||
ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
|
ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
|
||||||
GetStateAllocator());
|
GetStateAllocator());
|
||||||
result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
|
result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
|
||||||
@ -2529,10 +2481,8 @@ private:
|
|||||||
GenericStringBuffer<EncodingType> sb;
|
GenericStringBuffer<EncodingType> sb;
|
||||||
SizeType len = CurrentSchema().GetURI().GetStringLength();
|
SizeType len = CurrentSchema().GetURI().GetStringLength();
|
||||||
if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch));
|
if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch));
|
||||||
if (schema.GetTokenCount())
|
if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
|
||||||
schema.StringifyUriFragment(sb);
|
else GetInvalidSchemaPointer().StringifyUriFragment(sb);
|
||||||
else
|
|
||||||
GetInvalidSchemaPointer().StringifyUriFragment(sb);
|
|
||||||
ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
|
ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
|
||||||
GetStateAllocator());
|
GetStateAllocator());
|
||||||
result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
|
result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
|
||||||
|
@ -69,7 +69,7 @@ concept Stream {
|
|||||||
For custom stream, this type can be specialized for other configuration.
|
For custom stream, this type can be specialized for other configuration.
|
||||||
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
|
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
|
||||||
*/
|
*/
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
struct StreamTraits {
|
struct StreamTraits {
|
||||||
//! Whether to make local copy of stream for optimization during parsing.
|
//! Whether to make local copy of stream for optimization during parsing.
|
||||||
/*!
|
/*!
|
||||||
@ -80,20 +80,20 @@ struct StreamTraits {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! Reserve n characters for writing to a stream.
|
//! Reserve n characters for writing to a stream.
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
inline void PutReserve(Stream& stream, size_t count) {
|
inline void PutReserve(Stream& stream, size_t count) {
|
||||||
(void)stream;
|
(void)stream;
|
||||||
(void)count;
|
(void)count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Write character to a stream, presuming buffer is reserved.
|
//! Write character to a stream, presuming buffer is reserved.
|
||||||
template <typename Stream>
|
template<typename Stream>
|
||||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
|
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
|
||||||
stream.Put(c);
|
stream.Put(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Put N copies of a character to a stream.
|
//! Put N copies of a character to a stream.
|
||||||
template <typename Stream, typename Ch>
|
template<typename Stream, typename Ch>
|
||||||
inline void PutN(Stream& stream, Ch c, size_t n) {
|
inline void PutN(Stream& stream, Ch c, size_t n) {
|
||||||
PutReserve(stream, n);
|
PutReserve(stream, n);
|
||||||
for (size_t i = 0; i < n; i++)
|
for (size_t i = 0; i < n; i++)
|
||||||
@ -115,11 +115,11 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
|||||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename InputStream, typename Encoding = UTF8<>>
|
template <typename InputStream, typename Encoding = UTF8<> >
|
||||||
class GenericStreamWrapper {
|
class GenericStreamWrapper {
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
GenericStreamWrapper(InputStream& is) : is_(is) {}
|
GenericStreamWrapper(InputStream& is): is_(is) {}
|
||||||
|
|
||||||
Ch Peek() const { return is_.Peek(); }
|
Ch Peek() const { return is_.Peek(); }
|
||||||
Ch Take() { return is_.Take(); }
|
Ch Take() { return is_.Take(); }
|
||||||
@ -154,34 +154,28 @@ template <typename Encoding>
|
|||||||
struct GenericStringStream {
|
struct GenericStringStream {
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
GenericStringStream(const Ch* src) : src_(src), head_(src) {}
|
GenericStringStream(const Ch *src) : src_(src), head_(src) {}
|
||||||
|
|
||||||
Ch Peek() const { return *src_; }
|
Ch Peek() const { return *src_; }
|
||||||
Ch Take() { return *src_++; }
|
Ch Take() { return *src_++; }
|
||||||
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
|
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
|
||||||
|
|
||||||
Ch* PutBegin() {
|
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||||
size_t PutEnd(Ch*) {
|
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||||
RAPIDJSON_ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Ch* src_; //!< Current read position.
|
const Ch* src_; //!< Current read position.
|
||||||
const Ch* head_; //!< Original head of the string.
|
const Ch* head_; //!< Original head of the string.
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct StreamTraits<GenericStringStream<Encoding>> {
|
struct StreamTraits<GenericStringStream<Encoding> > {
|
||||||
enum { copyOptimization = 1 };
|
enum { copyOptimization = 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
//! String stream with UTF8 encoding.
|
//! String stream with UTF8 encoding.
|
||||||
typedef GenericStringStream<UTF8<>> StringStream;
|
typedef GenericStringStream<UTF8<> > StringStream;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// InsituStringStream
|
// InsituStringStream
|
||||||
@ -194,7 +188,7 @@ template <typename Encoding>
|
|||||||
struct GenericInsituStringStream {
|
struct GenericInsituStringStream {
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {}
|
GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
Ch Peek() { return *src_; }
|
Ch Peek() { return *src_; }
|
||||||
@ -202,20 +196,13 @@ struct GenericInsituStringStream {
|
|||||||
size_t Tell() { return static_cast<size_t>(src_ - head_); }
|
size_t Tell() { return static_cast<size_t>(src_ - head_); }
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
void Put(Ch c) {
|
void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
|
||||||
RAPIDJSON_ASSERT(dst_ != 0);
|
|
||||||
*dst_++ = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ch* PutBegin() { return dst_ = src_; }
|
Ch* PutBegin() { return dst_ = src_; }
|
||||||
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
|
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
|
||||||
void Flush() {}
|
void Flush() {}
|
||||||
|
|
||||||
Ch* Push(size_t count) {
|
Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
|
||||||
Ch* begin = dst_;
|
|
||||||
dst_ += count;
|
|
||||||
return begin;
|
|
||||||
}
|
|
||||||
void Pop(size_t count) { dst_ -= count; }
|
void Pop(size_t count) { dst_ -= count; }
|
||||||
|
|
||||||
Ch* src_;
|
Ch* src_;
|
||||||
@ -224,12 +211,12 @@ struct GenericInsituStringStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct StreamTraits<GenericInsituStringStream<Encoding>> {
|
struct StreamTraits<GenericInsituStringStream<Encoding> > {
|
||||||
enum { copyOptimization = 1 };
|
enum { copyOptimization = 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Insitu string stream with UTF8 encoding.
|
//! Insitu string stream with UTF8 encoding.
|
||||||
typedef GenericInsituStringStream<UTF8<>> InsituStringStream;
|
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
@ -94,21 +94,21 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! String buffer with UTF8 encoding
|
//! String buffer with UTF8 encoding
|
||||||
typedef GenericStringBuffer<UTF8<>> StringBuffer;
|
typedef GenericStringBuffer<UTF8<> > StringBuffer;
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator>
|
template<typename Encoding, typename Allocator>
|
||||||
inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
|
inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
|
||||||
stream.Reserve(count);
|
stream.Reserve(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator>
|
template<typename Encoding, typename Allocator>
|
||||||
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
|
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
|
||||||
stream.PutUnsafe(c);
|
stream.PutUnsafe(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template <>
|
template<>
|
||||||
inline void PutN(GenericStringBuffer<UTF8<>>& stream, char c, size_t n) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
RAPIDJSON_DIAG_OFF(unreachable - code)
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||||
@ -86,7 +86,7 @@ enum WriteFlag {
|
|||||||
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
||||||
\note implements Handler concept
|
\note implements Handler concept
|
||||||
*/
|
*/
|
||||||
template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||||
class Writer {
|
class Writer {
|
||||||
public:
|
public:
|
||||||
typedef typename SourceEncoding::Ch Ch;
|
typedef typename SourceEncoding::Ch Ch;
|
||||||
@ -98,12 +98,17 @@ public:
|
|||||||
\param stackAllocator 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) : os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
explicit
|
||||||
|
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||||
|
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
||||||
|
|
||||||
explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
explicit
|
||||||
|
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||||
|
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
Writer(Writer&& rhs) : os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
|
Writer(Writer&& rhs) :
|
||||||
|
os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
|
||||||
rhs.os_ = 0;
|
rhs.os_ = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -174,40 +179,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
bool Null() {
|
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
|
||||||
Prefix(kNullType);
|
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
|
||||||
return EndValue(WriteNull());
|
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
|
||||||
}
|
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
|
||||||
bool Bool(bool b) {
|
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
|
||||||
Prefix(b ? kTrueType : kFalseType);
|
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
|
||||||
return EndValue(WriteBool(b));
|
|
||||||
}
|
|
||||||
bool Int(int i) {
|
|
||||||
Prefix(kNumberType);
|
|
||||||
return EndValue(WriteInt(i));
|
|
||||||
}
|
|
||||||
bool Uint(unsigned u) {
|
|
||||||
Prefix(kNumberType);
|
|
||||||
return EndValue(WriteUint(u));
|
|
||||||
}
|
|
||||||
bool Int64(int64_t i64) {
|
|
||||||
Prefix(kNumberType);
|
|
||||||
return EndValue(WriteInt64(i64));
|
|
||||||
}
|
|
||||||
bool Uint64(uint64_t u64) {
|
|
||||||
Prefix(kNumberType);
|
|
||||||
return EndValue(WriteUint64(u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Writes the given \c double value to the stream
|
//! Writes the given \c double value to the stream
|
||||||
/*!
|
/*!
|
||||||
\param d The value to be written.
|
\param d The value to be written.
|
||||||
\return Whether it is succeed.
|
\return Whether it is succeed.
|
||||||
*/
|
*/
|
||||||
bool Double(double d) {
|
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
|
||||||
Prefix(kNumberType);
|
|
||||||
return EndValue(WriteDouble(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||||
RAPIDJSON_ASSERT(str != 0);
|
RAPIDJSON_ASSERT(str != 0);
|
||||||
@ -238,7 +222,8 @@ public:
|
|||||||
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
|
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
bool Key(const std::basic_string<Ch>& str) {
|
bool Key(const std::basic_string<Ch>& str)
|
||||||
|
{
|
||||||
return Key(str.data(), SizeType(str.size()));
|
return Key(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -310,28 +295,17 @@ protected:
|
|||||||
|
|
||||||
bool WriteNull() {
|
bool WriteNull() {
|
||||||
PutReserve(*os_, 4);
|
PutReserve(*os_, 4);
|
||||||
PutUnsafe(*os_, 'n');
|
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
|
||||||
PutUnsafe(*os_, 'u');
|
|
||||||
PutUnsafe(*os_, 'l');
|
|
||||||
PutUnsafe(*os_, 'l');
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteBool(bool b) {
|
bool WriteBool(bool b) {
|
||||||
if (b) {
|
if (b) {
|
||||||
PutReserve(*os_, 4);
|
PutReserve(*os_, 4);
|
||||||
PutUnsafe(*os_, 't');
|
PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
|
||||||
PutUnsafe(*os_, 'r');
|
|
||||||
PutUnsafe(*os_, 'u');
|
|
||||||
PutUnsafe(*os_, 'e');
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PutReserve(*os_, 5);
|
PutReserve(*os_, 5);
|
||||||
PutUnsafe(*os_, 'f');
|
PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
|
||||||
PutUnsafe(*os_, 'a');
|
|
||||||
PutUnsafe(*os_, 'l');
|
|
||||||
PutUnsafe(*os_, 's');
|
|
||||||
PutUnsafe(*os_, 'e');
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -378,9 +352,7 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
if (internal::Double(d).IsNan()) {
|
if (internal::Double(d).IsNan()) {
|
||||||
PutReserve(*os_, 3);
|
PutReserve(*os_, 3);
|
||||||
PutUnsafe(*os_, 'N');
|
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
|
||||||
PutUnsafe(*os_, 'a');
|
|
||||||
PutUnsafe(*os_, 'N');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (internal::Double(d).Sign()) {
|
if (internal::Double(d).Sign()) {
|
||||||
@ -389,14 +361,8 @@ protected:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
PutReserve(*os_, 8);
|
PutReserve(*os_, 8);
|
||||||
PutUnsafe(*os_, 'I');
|
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
|
||||||
PutUnsafe(*os_, 'n');
|
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
|
||||||
PutUnsafe(*os_, 'f');
|
|
||||||
PutUnsafe(*os_, 'i');
|
|
||||||
PutUnsafe(*os_, 'n');
|
|
||||||
PutUnsafe(*os_, 'i');
|
|
||||||
PutUnsafe(*os_, 't');
|
|
||||||
PutUnsafe(*os_, 'y');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,13 +377,13 @@ protected:
|
|||||||
bool WriteString(const Ch* str, SizeType length) {
|
bool WriteString(const Ch* str, SizeType length) {
|
||||||
static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
static const typename OutputStream::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
|
||||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
|
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
|
||||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
|
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
|
||||||
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
|
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
|
||||||
Z16, Z16, // 30~4F
|
Z16, Z16, // 30~4F
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
|
||||||
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
|
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
|
||||||
#undef Z16
|
#undef Z16
|
||||||
};
|
};
|
||||||
@ -442,7 +408,7 @@ protected:
|
|||||||
PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
|
PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
|
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
|
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(codepoint)&15]);
|
PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||||
@ -453,13 +419,13 @@ protected:
|
|||||||
PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
|
PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
|
PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
|
PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(lead)&15]);
|
PutUnsafe(*os_, hexDigits[(lead ) & 15]);
|
||||||
PutUnsafe(*os_, '\\');
|
PutUnsafe(*os_, '\\');
|
||||||
PutUnsafe(*os_, 'u');
|
PutUnsafe(*os_, 'u');
|
||||||
PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
|
PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
|
PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
|
PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(trail)&15]);
|
PutUnsafe(*os_, hexDigits[(trail ) & 15]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
|
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
|
||||||
@ -473,7 +439,9 @@ protected:
|
|||||||
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
|
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||||
|
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||||
|
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PutUnsafe(*os_, '\"');
|
PutUnsafe(*os_, '\"');
|
||||||
@ -484,29 +452,19 @@ protected:
|
|||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteStartObject() {
|
bool WriteStartObject() { os_->Put('{'); return true; }
|
||||||
os_->Put('{');
|
bool WriteEndObject() { os_->Put('}'); return true; }
|
||||||
return true;
|
bool WriteStartArray() { os_->Put('['); return true; }
|
||||||
}
|
bool WriteEndArray() { os_->Put(']'); return true; }
|
||||||
bool WriteEndObject() {
|
|
||||||
os_->Put('}');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool WriteStartArray() {
|
|
||||||
os_->Put('[');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool WriteEndArray() {
|
|
||||||
os_->Put(']');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteRawValue(const Ch* json, size_t length) {
|
bool WriteRawValue(const Ch* json, size_t length) {
|
||||||
PutReserve(*os_, length);
|
PutReserve(*os_, length);
|
||||||
GenericStringStream<SourceEncoding> is(json);
|
GenericStringStream<SourceEncoding> is(json);
|
||||||
while (RAPIDJSON_LIKELY(is.Tell() < length)) {
|
while (RAPIDJSON_LIKELY(is.Tell() < length)) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() != '\0');
|
RAPIDJSON_ASSERT(is.Peek() != '\0');
|
||||||
if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||||
|
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||||
|
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -552,39 +510,39 @@ private:
|
|||||||
|
|
||||||
// Full specialization for StringStream to prevent memory copying
|
// Full specialization for StringStream to prevent memory copying
|
||||||
|
|
||||||
template <>
|
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(static_cast<size_t>(11 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(11 - (end - buffer)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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(static_cast<size_t>(10 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(10 - (end - buffer)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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(static_cast<size_t>(21 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(21 - (end - buffer)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
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(static_cast<size_t>(20 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(20 - (end - buffer)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
||||||
if (internal::Double(d).IsNanOrInf()) {
|
if (internal::Double(d).IsNanOrInf()) {
|
||||||
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
||||||
@ -592,9 +550,7 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
|||||||
return false;
|
return false;
|
||||||
if (internal::Double(d).IsNan()) {
|
if (internal::Double(d).IsNan()) {
|
||||||
PutReserve(*os_, 3);
|
PutReserve(*os_, 3);
|
||||||
PutUnsafe(*os_, 'N');
|
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
|
||||||
PutUnsafe(*os_, 'a');
|
|
||||||
PutUnsafe(*os_, 'N');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (internal::Double(d).Sign()) {
|
if (internal::Double(d).Sign()) {
|
||||||
@ -603,25 +559,19 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
PutReserve(*os_, 8);
|
PutReserve(*os_, 8);
|
||||||
PutUnsafe(*os_, 'I');
|
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
|
||||||
PutUnsafe(*os_, 'n');
|
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
|
||||||
PutUnsafe(*os_, 'f');
|
|
||||||
PutUnsafe(*os_, 'i');
|
|
||||||
PutUnsafe(*os_, 'n');
|
|
||||||
PutUnsafe(*os_, 'i');
|
|
||||||
PutUnsafe(*os_, 't');
|
|
||||||
PutUnsafe(*os_, 'y');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* buffer = os_->Push(25);
|
char *buffer = os_->Push(25);
|
||||||
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
||||||
os_->Pop(static_cast<size_t>(25 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(25 - (end - buffer)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
||||||
template <>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
||||||
if (length < 16)
|
if (length < 16)
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
@ -648,12 +598,12 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
|||||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||||
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
|
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
|
||||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
|
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
|
||||||
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
|
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||||
|
|
||||||
for (; p != endAligned; p += 16) {
|
for (; p != endAligned; p += 16) {
|
||||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||||
@ -675,14 +625,14 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
|||||||
p += len;
|
p += len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s);
|
_mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
}
|
}
|
||||||
#elif defined(RAPIDJSON_NEON)
|
#elif defined(RAPIDJSON_NEON)
|
||||||
template <>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
||||||
if (length < 16)
|
if (length < 16)
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
@ -712,7 +662,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
|||||||
const uint8x16_t s3 = vmovq_n_u8(32);
|
const uint8x16_t s3 = vmovq_n_u8(32);
|
||||||
|
|
||||||
for (; p != endAligned; p += 16) {
|
for (; p != endAligned; p += 16) {
|
||||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p));
|
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
|
||||||
uint8x16_t x = vceqq_u8(s, s0);
|
uint8x16_t x = vceqq_u8(s, s0);
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s1));
|
x = vorrq_u8(x, vceqq_u8(s, s1));
|
||||||
x = vorrq_u8(x, vceqq_u8(s, s2));
|
x = vorrq_u8(x, vceqq_u8(s, s2));
|
||||||
@ -730,8 +680,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
|||||||
len = 8 + (lz >> 3);
|
len = 8 + (lz >> 3);
|
||||||
escaped = true;
|
escaped = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lz = internal::clzll(low);
|
uint32_t lz = internal::clzll(low);
|
||||||
len = lz >> 3;
|
len = lz >> 3;
|
||||||
escaped = true;
|
escaped = true;
|
||||||
@ -744,7 +693,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
|||||||
p += len;
|
p += len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vst1q_u8(reinterpret_cast<uint8_t*>(os_->PushUnsafe(16)), s);
|
vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
|
@ -16,15 +16,22 @@ struct Backoff {
|
|||||||
double rand01() { return randDistribution(randGenerator); }
|
double rand01() { return randDistribution(randGenerator); }
|
||||||
|
|
||||||
Backoff(int64_t min, int64_t max)
|
Backoff(int64_t min, int64_t max)
|
||||||
: minAmount(min), maxAmount(max), current(min), fails(0), randGenerator((uint64_t)time(0)) {
|
: minAmount(min)
|
||||||
|
, maxAmount(max)
|
||||||
|
, current(min)
|
||||||
|
, fails(0)
|
||||||
|
, randGenerator((uint64_t)time(0))
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset()
|
||||||
|
{
|
||||||
fails = 0;
|
fails = 0;
|
||||||
current = minAmount;
|
current = minAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t nextDelay() {
|
int64_t nextDelay()
|
||||||
|
{
|
||||||
++fails;
|
++fails;
|
||||||
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
||||||
current = std::min(current + delay, maxAmount);
|
current = std::min(current + delay, maxAmount);
|
||||||
|
@ -11,7 +11,7 @@ int GetProcessId();
|
|||||||
struct BaseConnection {
|
struct BaseConnection {
|
||||||
static BaseConnection* Create();
|
static BaseConnection* Create();
|
||||||
static void Destroy(BaseConnection*&);
|
static void Destroy(BaseConnection*&);
|
||||||
bool isOpen{ false };
|
bool isOpen{false};
|
||||||
bool Open();
|
bool Open();
|
||||||
bool Close();
|
bool Close();
|
||||||
bool Write(const void* data, size_t length);
|
bool Write(const void* data, size_t length);
|
||||||
|
@ -9,12 +9,13 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int GetProcessId() {
|
int GetProcessId()
|
||||||
|
{
|
||||||
return ::getpid();
|
return ::getpid();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BaseConnectionUnix : public BaseConnection {
|
struct BaseConnectionUnix : public BaseConnection {
|
||||||
int sock{ -1 };
|
int sock{-1};
|
||||||
};
|
};
|
||||||
|
|
||||||
static BaseConnectionUnix Connection;
|
static BaseConnectionUnix Connection;
|
||||||
@ -25,7 +26,8 @@ static int MsgFlags = MSG_NOSIGNAL;
|
|||||||
static int MsgFlags = 0;
|
static int MsgFlags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* GetTempPath() {
|
static const char* GetTempPath()
|
||||||
|
{
|
||||||
const char* temp = getenv("XDG_RUNTIME_DIR");
|
const char* temp = getenv("XDG_RUNTIME_DIR");
|
||||||
temp = temp ? temp : getenv("TMPDIR");
|
temp = temp ? temp : getenv("TMPDIR");
|
||||||
temp = temp ? temp : getenv("TMP");
|
temp = temp ? temp : getenv("TMP");
|
||||||
@ -34,18 +36,21 @@ static const char* GetTempPath() {
|
|||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ BaseConnection* BaseConnection::Create() {
|
/*static*/ BaseConnection* BaseConnection::Create()
|
||||||
|
{
|
||||||
PipeAddr.sun_family = AF_UNIX;
|
PipeAddr.sun_family = AF_UNIX;
|
||||||
return &Connection;
|
return &Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void BaseConnection::Destroy(BaseConnection*& c) {
|
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionUnix*>(c);
|
auto self = reinterpret_cast<BaseConnectionUnix*>(c);
|
||||||
self->Close();
|
self->Close();
|
||||||
c = nullptr;
|
c = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Open() {
|
bool BaseConnection::Open()
|
||||||
|
{
|
||||||
const char* tempPath = GetTempPath();
|
const char* tempPath = GetTempPath();
|
||||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
@ -71,7 +76,8 @@ bool BaseConnection::Open() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Close() {
|
bool BaseConnection::Close()
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
if (self->sock == -1) {
|
if (self->sock == -1) {
|
||||||
return false;
|
return false;
|
||||||
@ -82,7 +88,8 @@ bool BaseConnection::Close() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Write(const void* data, size_t length) {
|
bool BaseConnection::Write(const void* data, size_t length)
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
|
||||||
if (self->sock == -1) {
|
if (self->sock == -1) {
|
||||||
@ -96,7 +103,8 @@ bool BaseConnection::Write(const void* data, size_t length) {
|
|||||||
return sentBytes == (ssize_t)length;
|
return sentBytes == (ssize_t)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Read(void* data, size_t length) {
|
bool BaseConnection::Read(void* data, size_t length)
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
|
||||||
if (self->sock == -1) {
|
if (self->sock == -1) {
|
||||||
|
@ -7,28 +7,32 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
int GetProcessId() {
|
int GetProcessId()
|
||||||
|
{
|
||||||
return (int)::GetCurrentProcessId();
|
return (int)::GetCurrentProcessId();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BaseConnectionWin : public BaseConnection {
|
struct BaseConnectionWin : public BaseConnection {
|
||||||
HANDLE pipe{ INVALID_HANDLE_VALUE };
|
HANDLE pipe{INVALID_HANDLE_VALUE};
|
||||||
};
|
};
|
||||||
|
|
||||||
static BaseConnectionWin Connection;
|
static BaseConnectionWin Connection;
|
||||||
|
|
||||||
/*static*/ BaseConnection* BaseConnection::Create() {
|
/*static*/ BaseConnection* BaseConnection::Create()
|
||||||
|
{
|
||||||
return &Connection;
|
return &Connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void BaseConnection::Destroy(BaseConnection*& c) {
|
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionWin*>(c);
|
auto self = reinterpret_cast<BaseConnectionWin*>(c);
|
||||||
self->Close();
|
self->Close();
|
||||||
c = nullptr;
|
c = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Open() {
|
bool BaseConnection::Open()
|
||||||
wchar_t pipeName[]{ L"\\\\?\\pipe\\discord-ipc-0" };
|
{
|
||||||
|
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
|
||||||
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
|
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
|
||||||
pipeName[pipeDigit] = L'0';
|
pipeName[pipeDigit] = L'0';
|
||||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
@ -57,7 +61,8 @@ bool BaseConnection::Open() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Close() {
|
bool BaseConnection::Close()
|
||||||
|
{
|
||||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
::CloseHandle(self->pipe);
|
::CloseHandle(self->pipe);
|
||||||
self->pipe = INVALID_HANDLE_VALUE;
|
self->pipe = INVALID_HANDLE_VALUE;
|
||||||
@ -65,7 +70,8 @@ bool BaseConnection::Close() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Write(const void* data, size_t length) {
|
bool BaseConnection::Write(const void* data, size_t length)
|
||||||
|
{
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -87,7 +93,8 @@ bool BaseConnection::Write(const void* data, size_t length) {
|
|||||||
bytesWritten == bytesLength;
|
bytesWritten == bytesLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnection::Read(void* data, size_t length) {
|
bool BaseConnection::Read(void* data, size_t length)
|
||||||
|
{
|
||||||
assert(data);
|
assert(data);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static bool Mkdir(const char* path) {
|
static bool Mkdir(const char* path)
|
||||||
|
{
|
||||||
int result = mkdir(path, 0755);
|
int result = mkdir(path, 0755);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
return true;
|
return true;
|
||||||
@ -21,7 +22,8 @@ static bool Mkdir(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we want to register games so we can run them from Discord client as discord-<appid>://
|
// we want to register games so we can run them from Discord client as discord-<appid>://
|
||||||
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) {
|
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||||
|
{
|
||||||
// Add a desktop file and update some mime handlers so that xdg-open does the right thing.
|
// Add a desktop file and update some mime handlers so that xdg-open does the right thing.
|
||||||
|
|
||||||
const char* home = getenv("HOME");
|
const char* home = getenv("HOME");
|
||||||
@ -92,7 +94,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||||
const char* steamId) {
|
const char* steamId)
|
||||||
|
{
|
||||||
char command[256];
|
char command[256];
|
||||||
sprintf(command, "xdg-open steam://rungameid/%s", steamId);
|
sprintf(command, "xdg-open steam://rungameid/%s", steamId);
|
||||||
Discord_Register(applicationId, command);
|
Discord_Register(applicationId, command);
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
/// strsafe.h fixes
|
/// strsafe.h fixes
|
||||||
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) {
|
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
|
||||||
|
{
|
||||||
HRESULT ret;
|
HRESULT ret;
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, pszFormat);
|
va_start(va, pszFormat);
|
||||||
@ -50,7 +51,8 @@ static LSTATUS regset(HKEY hkey,
|
|||||||
LPCWSTR name,
|
LPCWSTR name,
|
||||||
DWORD type,
|
DWORD type,
|
||||||
const void* data,
|
const void* data,
|
||||||
DWORD len) {
|
DWORD len)
|
||||||
|
{
|
||||||
HKEY htkey = hkey, hsubkey = nullptr;
|
HKEY htkey = hkey, hsubkey = nullptr;
|
||||||
LSTATUS ret;
|
LSTATUS ret;
|
||||||
if (subkey && subkey[0]) {
|
if (subkey && subkey[0]) {
|
||||||
@ -65,7 +67,8 @@ static LSTATUS regset(HKEY hkey,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) {
|
static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
||||||
|
{
|
||||||
// https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
// https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
||||||
// we want to register games so we can run them as discord-<appid>://
|
// we want to register games so we can run them as discord-<appid>://
|
||||||
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
||||||
@ -128,7 +131,8 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma
|
|||||||
RegCloseKey(key);
|
RegCloseKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) {
|
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||||
|
{
|
||||||
wchar_t appId[32];
|
wchar_t appId[32];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||||
|
|
||||||
@ -144,7 +148,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||||
const char* steamId) {
|
const char* steamId)
|
||||||
|
{
|
||||||
wchar_t appId[32];
|
wchar_t appId[32];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||||
|
|
||||||
|
@ -15,15 +15,16 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr size_t MaxMessageSize{ 16 * 1024 };
|
constexpr size_t MaxMessageSize{16 * 1024};
|
||||||
constexpr size_t MessageQueueSize{ 8 };
|
constexpr size_t MessageQueueSize{8};
|
||||||
constexpr size_t JoinQueueSize{ 8 };
|
constexpr size_t JoinQueueSize{8};
|
||||||
|
|
||||||
struct QueuedMessage {
|
struct QueuedMessage {
|
||||||
size_t length;
|
size_t length;
|
||||||
char buffer[MaxMessageSize];
|
char buffer[MaxMessageSize];
|
||||||
|
|
||||||
void Copy(const QueuedMessage& other) {
|
void Copy(const QueuedMessage& other)
|
||||||
|
{
|
||||||
length = other.length;
|
length = other.length;
|
||||||
if (length) {
|
if (length) {
|
||||||
memcpy(buffer, other.buffer, length);
|
memcpy(buffer, other.buffer, length);
|
||||||
@ -45,20 +46,20 @@ struct User {
|
|||||||
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
|
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
|
||||||
};
|
};
|
||||||
|
|
||||||
static RpcConnection* Connection{ nullptr };
|
static RpcConnection* Connection{nullptr};
|
||||||
static DiscordEventHandlers QueuedHandlers{};
|
static DiscordEventHandlers QueuedHandlers{};
|
||||||
static DiscordEventHandlers Handlers{};
|
static DiscordEventHandlers Handlers{};
|
||||||
static std::atomic_bool WasJustConnected{ false };
|
static std::atomic_bool WasJustConnected{false};
|
||||||
static std::atomic_bool WasJustDisconnected{ false };
|
static std::atomic_bool WasJustDisconnected{false};
|
||||||
static std::atomic_bool GotErrorMessage{ false };
|
static std::atomic_bool GotErrorMessage{false};
|
||||||
static std::atomic_bool WasJoinGame{ false };
|
static std::atomic_bool WasJoinGame{false};
|
||||||
static std::atomic_bool WasSpectateGame{ false };
|
static std::atomic_bool WasSpectateGame{false};
|
||||||
static std::atomic_bool UpdatePresence{ false };
|
static std::atomic_bool UpdatePresence{false};
|
||||||
static char JoinGameSecret[256];
|
static char JoinGameSecret[256];
|
||||||
static char SpectateGameSecret[256];
|
static char SpectateGameSecret[256];
|
||||||
static int LastErrorCode{ 0 };
|
static int LastErrorCode{0};
|
||||||
static char LastErrorMessage[256];
|
static char LastErrorMessage[256];
|
||||||
static int LastDisconnectErrorCode{ 0 };
|
static int LastDisconnectErrorCode{0};
|
||||||
static char LastDisconnectErrorMessage[256];
|
static char LastDisconnectErrorMessage[256];
|
||||||
static std::mutex PresenceMutex;
|
static std::mutex PresenceMutex;
|
||||||
static std::mutex HandlerMutex;
|
static std::mutex HandlerMutex;
|
||||||
@ -71,23 +72,24 @@ static User connectedUser;
|
|||||||
// backoff from 0.5 seconds to 1 minute
|
// backoff from 0.5 seconds to 1 minute
|
||||||
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||||
static auto NextConnect = std::chrono::system_clock::now();
|
static auto NextConnect = std::chrono::system_clock::now();
|
||||||
static int Pid{ 0 };
|
static int Pid{0};
|
||||||
static int Nonce{ 1 };
|
static int Nonce{1};
|
||||||
|
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||||
static void Discord_UpdateConnection(void);
|
static void Discord_UpdateConnection(void);
|
||||||
class IoThreadHolder {
|
class IoThreadHolder {
|
||||||
private:
|
private:
|
||||||
std::atomic_bool keepRunning{ true };
|
std::atomic_bool keepRunning{true};
|
||||||
std::mutex waitForIOMutex;
|
std::mutex waitForIOMutex;
|
||||||
std::condition_variable waitForIOActivity;
|
std::condition_variable waitForIOActivity;
|
||||||
std::thread ioThread;
|
std::thread ioThread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Start() {
|
void Start()
|
||||||
|
{
|
||||||
keepRunning.store(true);
|
keepRunning.store(true);
|
||||||
ioThread = std::thread([&]() {
|
ioThread = std::thread([&]() {
|
||||||
const std::chrono::duration<int64_t, std::milli> maxWait{ 500LL };
|
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||||
Discord_UpdateConnection();
|
Discord_UpdateConnection();
|
||||||
while (keepRunning.load()) {
|
while (keepRunning.load()) {
|
||||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||||
@ -99,7 +101,8 @@ public:
|
|||||||
|
|
||||||
void Notify() { waitForIOActivity.notify_all(); }
|
void Notify() { waitForIOActivity.notify_all(); }
|
||||||
|
|
||||||
void Stop() {
|
void Stop()
|
||||||
|
{
|
||||||
keepRunning.exchange(false);
|
keepRunning.exchange(false);
|
||||||
Notify();
|
Notify();
|
||||||
if (ioThread.joinable()) {
|
if (ioThread.joinable()) {
|
||||||
@ -117,11 +120,12 @@ public:
|
|||||||
void Notify() {}
|
void Notify() {}
|
||||||
};
|
};
|
||||||
#endif // DISCORD_DISABLE_IO_THREAD
|
#endif // DISCORD_DISABLE_IO_THREAD
|
||||||
static IoThreadHolder* IoThread{ nullptr };
|
static IoThreadHolder* IoThread{nullptr};
|
||||||
|
|
||||||
static void UpdateReconnectTime() {
|
static void UpdateReconnectTime()
|
||||||
|
{
|
||||||
NextConnect = std::chrono::system_clock::now() +
|
NextConnect = std::chrono::system_clock::now() +
|
||||||
std::chrono::duration<int64_t, std::milli>{ ReconnectTimeMs.nextDelay() };
|
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||||
@ -233,13 +237,15 @@ static void Discord_UpdateConnection(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SignalIOActivity() {
|
static void SignalIOActivity()
|
||||||
|
{
|
||||||
if (IoThread != nullptr) {
|
if (IoThread != nullptr) {
|
||||||
IoThread->Notify();
|
IoThread->Notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool RegisterForEvent(const char* evtName) {
|
static bool RegisterForEvent(const char* evtName)
|
||||||
|
{
|
||||||
auto qmessage = SendQueue.GetNextAddMessage();
|
auto qmessage = SendQueue.GetNextAddMessage();
|
||||||
if (qmessage) {
|
if (qmessage) {
|
||||||
qmessage->length =
|
qmessage->length =
|
||||||
@ -251,7 +257,8 @@ static bool RegisterForEvent(const char* evtName) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DeregisterForEvent(const char* evtName) {
|
static bool DeregisterForEvent(const char* evtName)
|
||||||
|
{
|
||||||
auto qmessage = SendQueue.GetNextAddMessage();
|
auto qmessage = SendQueue.GetNextAddMessage();
|
||||||
if (qmessage) {
|
if (qmessage) {
|
||||||
qmessage->length =
|
qmessage->length =
|
||||||
@ -266,7 +273,8 @@ static bool DeregisterForEvent(const char* evtName) {
|
|||||||
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||||
DiscordEventHandlers* handlers,
|
DiscordEventHandlers* handlers,
|
||||||
int autoRegister,
|
int autoRegister,
|
||||||
const char* optionalSteamId) {
|
const char* optionalSteamId)
|
||||||
|
{
|
||||||
IoThread = new (std::nothrow) IoThreadHolder();
|
IoThread = new (std::nothrow) IoThreadHolder();
|
||||||
if (IoThread == nullptr) {
|
if (IoThread == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -339,7 +347,8 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
|||||||
IoThread->Start();
|
IoThread->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_Shutdown(void) {
|
extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
|
||||||
|
{
|
||||||
if (!Connection) {
|
if (!Connection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -357,7 +366,8 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown(void) {
|
|||||||
RpcConnection::Destroy(Connection);
|
RpcConnection::Destroy(Connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) {
|
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||||
QueuedPresence.length = JsonWriteRichPresenceObj(
|
QueuedPresence.length = JsonWriteRichPresenceObj(
|
||||||
@ -367,11 +377,13 @@ extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence*
|
|||||||
SignalIOActivity();
|
SignalIOActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) {
|
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void)
|
||||||
|
{
|
||||||
Discord_UpdatePresence(nullptr);
|
Discord_UpdatePresence(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) {
|
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||||
|
{
|
||||||
// if we are not connected, let's not batch up stale messages for later
|
// if we are not connected, let's not batch up stale messages for later
|
||||||
if (!Connection || !Connection->IsOpen()) {
|
if (!Connection || !Connection->IsOpen()) {
|
||||||
return;
|
return;
|
||||||
@ -385,7 +397,8 @@ extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_RE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
|
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
|
||||||
|
{
|
||||||
// Note on some weirdness: internally we might connect, get other signals, disconnect any number
|
// Note on some weirdness: internally we might connect, get other signals, disconnect any number
|
||||||
// of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
|
// of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
|
||||||
// signals are book-ended by calls to ready and disconnect.
|
// signals are book-ended by calls to ready and disconnect.
|
||||||
@ -408,10 +421,10 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
|
|||||||
if (WasJustConnected.exchange(false)) {
|
if (WasJustConnected.exchange(false)) {
|
||||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
if (Handlers.ready) {
|
if (Handlers.ready) {
|
||||||
DiscordUser du{ connectedUser.userId,
|
DiscordUser du{connectedUser.userId,
|
||||||
connectedUser.username,
|
connectedUser.username,
|
||||||
connectedUser.discriminator,
|
connectedUser.discriminator,
|
||||||
connectedUser.avatar };
|
connectedUser.avatar};
|
||||||
Handlers.ready(&du);
|
Handlers.ready(&du);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +460,7 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
if (Handlers.joinRequest) {
|
if (Handlers.joinRequest) {
|
||||||
DiscordUser du{ req->userId, req->username, req->discriminator, req->avatar };
|
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
|
||||||
Handlers.joinRequest(&du);
|
Handlers.joinRequest(&du);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -463,7 +476,8 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) {
|
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
|
||||||
|
{
|
||||||
if (newHandlers) {
|
if (newHandlers) {
|
||||||
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
|
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
|
||||||
if (!Handlers.handler_name && newHandlers->handler_name) { \
|
if (!Handlers.handler_name && newHandlers->handler_name) { \
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
// outsmart GCC's missing-declarations warning
|
// outsmart GCC's missing-declarations warning
|
||||||
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID);
|
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID);
|
||||||
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) {
|
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID)
|
||||||
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,15 @@
|
|||||||
template <typename ElementType, size_t QueueSize>
|
template <typename ElementType, size_t QueueSize>
|
||||||
class MsgQueue {
|
class MsgQueue {
|
||||||
ElementType queue_[QueueSize];
|
ElementType queue_[QueueSize];
|
||||||
std::atomic_uint nextAdd_{ 0 };
|
std::atomic_uint nextAdd_{0};
|
||||||
std::atomic_uint nextSend_{ 0 };
|
std::atomic_uint nextSend_{0};
|
||||||
std::atomic_uint pendingSends_{ 0 };
|
std::atomic_uint pendingSends_{0};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MsgQueue() {}
|
MsgQueue() {}
|
||||||
|
|
||||||
ElementType* GetNextAddMessage() {
|
ElementType* GetNextAddMessage()
|
||||||
|
{
|
||||||
// if we are falling behind, bail
|
// if we are falling behind, bail
|
||||||
if (pendingSends_.load() >= QueueSize) {
|
if (pendingSends_.load() >= QueueSize) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -26,7 +27,8 @@ public:
|
|||||||
void CommitAdd() { ++pendingSends_; }
|
void CommitAdd() { ++pendingSends_; }
|
||||||
|
|
||||||
bool HavePendingSends() const { return pendingSends_.load() != 0; }
|
bool HavePendingSends() const { return pendingSends_.load() != 0; }
|
||||||
ElementType* GetNextSendMessage() {
|
ElementType* GetNextSendMessage()
|
||||||
|
{
|
||||||
auto index = (nextSend_++) % QueueSize;
|
auto index = (nextSend_++) % QueueSize;
|
||||||
return &queue_[index];
|
return &queue_[index];
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,22 @@
|
|||||||
static const int RpcVersion = 1;
|
static const int RpcVersion = 1;
|
||||||
static RpcConnection Instance;
|
static RpcConnection Instance;
|
||||||
|
|
||||||
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) {
|
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
|
||||||
|
{
|
||||||
Instance.connection = BaseConnection::Create();
|
Instance.connection = BaseConnection::Create();
|
||||||
StringCopy(Instance.appId, applicationId);
|
StringCopy(Instance.appId, applicationId);
|
||||||
return &Instance;
|
return &Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void RpcConnection::Destroy(RpcConnection*& c) {
|
/*static*/ void RpcConnection::Destroy(RpcConnection*& c)
|
||||||
|
{
|
||||||
c->Close();
|
c->Close();
|
||||||
BaseConnection::Destroy(c->connection);
|
BaseConnection::Destroy(c->connection);
|
||||||
c = nullptr;
|
c = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcConnection::Open() {
|
void RpcConnection::Open()
|
||||||
|
{
|
||||||
if (state == State::Connected) {
|
if (state == State::Connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -54,7 +57,8 @@ void RpcConnection::Open() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcConnection::Close() {
|
void RpcConnection::Close()
|
||||||
|
{
|
||||||
if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) {
|
if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) {
|
||||||
onDisconnect(lastErrorCode, lastErrorMessage);
|
onDisconnect(lastErrorCode, lastErrorMessage);
|
||||||
}
|
}
|
||||||
@ -62,7 +66,8 @@ void RpcConnection::Close() {
|
|||||||
state = State::Disconnected;
|
state = State::Disconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RpcConnection::Write(const void* data, size_t length) {
|
bool RpcConnection::Write(const void* data, size_t length)
|
||||||
|
{
|
||||||
sendFrame.opcode = Opcode::Frame;
|
sendFrame.opcode = Opcode::Frame;
|
||||||
memcpy(sendFrame.message, data, length);
|
memcpy(sendFrame.message, data, length);
|
||||||
sendFrame.length = (uint32_t)length;
|
sendFrame.length = (uint32_t)length;
|
||||||
@ -73,7 +78,8 @@ bool RpcConnection::Write(const void* data, size_t length) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RpcConnection::Read(JsonDocument& message) {
|
bool RpcConnection::Read(JsonDocument& message)
|
||||||
|
{
|
||||||
if (state != State::Connected && state != State::SentHandshake) {
|
if (state != State::Connected && state != State::SentHandshake) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@ struct RpcConnection {
|
|||||||
Connected,
|
Connected,
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseConnection* connection{ nullptr };
|
BaseConnection* connection{nullptr};
|
||||||
State state{ State::Disconnected };
|
State state{State::Disconnected};
|
||||||
void (*onConnect)(JsonDocument& message){ nullptr };
|
void (*onConnect)(JsonDocument& message){nullptr};
|
||||||
void (*onDisconnect)(int errorCode, const char* message){ nullptr };
|
void (*onDisconnect)(int errorCode, const char* message){nullptr};
|
||||||
char appId[64]{};
|
char appId[64]{};
|
||||||
int lastErrorCode{ 0 };
|
int lastErrorCode{0};
|
||||||
char lastErrorMessage[256]{};
|
char lastErrorMessage[256]{};
|
||||||
RpcConnection::MessageFrame sendFrame;
|
RpcConnection::MessageFrame sendFrame;
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
#include "discord_rpc.h"
|
#include "discord_rpc.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void NumberToString(char* dest, T number) {
|
void NumberToString(char* dest, T number)
|
||||||
|
{
|
||||||
if (!number) {
|
if (!number) {
|
||||||
*dest++ = '0';
|
*dest++ = '0';
|
||||||
*dest++ = 0;
|
*dest++ = 0;
|
||||||
@ -28,19 +29,22 @@ void NumberToString(char* dest, T number) {
|
|||||||
|
|
||||||
// it's ever so slightly faster to not have to strlen the key
|
// it's ever so slightly faster to not have to strlen the key
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteKey(JsonWriter& w, T& k) {
|
void WriteKey(JsonWriter& w, T& k)
|
||||||
|
{
|
||||||
w.Key(k, sizeof(T) - 1);
|
w.Key(k, sizeof(T) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WriteObject {
|
struct WriteObject {
|
||||||
JsonWriter& writer;
|
JsonWriter& writer;
|
||||||
WriteObject(JsonWriter& w)
|
WriteObject(JsonWriter& w)
|
||||||
: writer(w) {
|
: writer(w)
|
||||||
|
{
|
||||||
writer.StartObject();
|
writer.StartObject();
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
WriteObject(JsonWriter& w, T& name)
|
WriteObject(JsonWriter& w, T& name)
|
||||||
: writer(w) {
|
: writer(w)
|
||||||
|
{
|
||||||
WriteKey(writer, name);
|
WriteKey(writer, name);
|
||||||
writer.StartObject();
|
writer.StartObject();
|
||||||
}
|
}
|
||||||
@ -51,7 +55,8 @@ struct WriteArray {
|
|||||||
JsonWriter& writer;
|
JsonWriter& writer;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
WriteArray(JsonWriter& w, T& name)
|
WriteArray(JsonWriter& w, T& name)
|
||||||
: writer(w) {
|
: writer(w)
|
||||||
|
{
|
||||||
WriteKey(writer, name);
|
WriteKey(writer, name);
|
||||||
writer.StartArray();
|
writer.StartArray();
|
||||||
}
|
}
|
||||||
@ -59,14 +64,16 @@ struct WriteArray {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteOptionalString(JsonWriter& w, T& k, const char* value) {
|
void WriteOptionalString(JsonWriter& w, T& k, const char* value)
|
||||||
|
{
|
||||||
if (value && value[0]) {
|
if (value && value[0]) {
|
||||||
w.Key(k, sizeof(T) - 1);
|
w.Key(k, sizeof(T) - 1);
|
||||||
w.String(value);
|
w.String(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void JsonWriteNonce(JsonWriter& writer, int nonce) {
|
static void JsonWriteNonce(JsonWriter& writer, int nonce)
|
||||||
|
{
|
||||||
WriteKey(writer, "nonce");
|
WriteKey(writer, "nonce");
|
||||||
char nonceBuffer[32];
|
char nonceBuffer[32];
|
||||||
NumberToString(nonceBuffer, nonce);
|
NumberToString(nonceBuffer, nonce);
|
||||||
@ -77,7 +84,8 @@ size_t JsonWriteRichPresenceObj(char* dest,
|
|||||||
size_t maxLen,
|
size_t maxLen,
|
||||||
int nonce,
|
int nonce,
|
||||||
int pid,
|
int pid,
|
||||||
const DiscordRichPresence* presence) {
|
const DiscordRichPresence* presence)
|
||||||
|
{
|
||||||
JsonWriter writer(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -159,7 +167,8 @@ size_t JsonWriteRichPresenceObj(char* dest,
|
|||||||
return writer.Size();
|
return writer.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) {
|
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
|
||||||
|
{
|
||||||
JsonWriter writer(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -173,7 +182,8 @@ size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char*
|
|||||||
return writer.Size();
|
return writer.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) {
|
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||||
|
{
|
||||||
JsonWriter writer(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -191,7 +201,8 @@ size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const cha
|
|||||||
return writer.Size();
|
return writer.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) {
|
size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
|
||||||
|
{
|
||||||
JsonWriter writer(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -209,7 +220,8 @@ size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const c
|
|||||||
return writer.Size();
|
return writer.Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) {
|
size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
|
||||||
|
{
|
||||||
JsonWriter writer(dest, maxLen);
|
JsonWriter writer(dest, maxLen);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
// if only there was a standard library function for this
|
// if only there was a standard library function for this
|
||||||
template <size_t Len>
|
template <size_t Len>
|
||||||
inline size_t StringCopy(char (&dest)[Len], const char* src) {
|
inline size_t StringCopy(char (&dest)[Len], const char* src)
|
||||||
|
{
|
||||||
if (!src || !Len) {
|
if (!src || !Len) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -57,14 +58,18 @@ class LinearAllocator {
|
|||||||
public:
|
public:
|
||||||
char* buffer_;
|
char* buffer_;
|
||||||
char* end_;
|
char* end_;
|
||||||
LinearAllocator() {
|
LinearAllocator()
|
||||||
|
{
|
||||||
assert(0); // needed for some default case in rapidjson, should not use
|
assert(0); // needed for some default case in rapidjson, should not use
|
||||||
}
|
}
|
||||||
LinearAllocator(char* buffer, size_t size)
|
LinearAllocator(char* buffer, size_t size)
|
||||||
: buffer_(buffer), end_(buffer + size) {
|
: buffer_(buffer)
|
||||||
|
, end_(buffer + size)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
static const bool kNeedFree = false;
|
static const bool kNeedFree = false;
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size)
|
||||||
|
{
|
||||||
char* res = buffer_;
|
char* res = buffer_;
|
||||||
buffer_ += size;
|
buffer_ += size;
|
||||||
if (buffer_ > end_) {
|
if (buffer_ > end_) {
|
||||||
@ -73,7 +78,8 @@ public:
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
|
||||||
|
{
|
||||||
if (newSize == 0) {
|
if (newSize == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -84,7 +90,8 @@ public:
|
|||||||
(void)(originalSize);
|
(void)(originalSize);
|
||||||
return Malloc(newSize);
|
return Malloc(newSize);
|
||||||
}
|
}
|
||||||
static void Free(void* ptr) {
|
static void Free(void* ptr)
|
||||||
|
{
|
||||||
/* shrug */
|
/* shrug */
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
}
|
}
|
||||||
@ -95,7 +102,8 @@ class FixedLinearAllocator : public LinearAllocator {
|
|||||||
public:
|
public:
|
||||||
char fixedBuffer_[Size];
|
char fixedBuffer_[Size];
|
||||||
FixedLinearAllocator()
|
FixedLinearAllocator()
|
||||||
: LinearAllocator(fixedBuffer_, Size) {
|
: LinearAllocator(fixedBuffer_, Size)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
static const bool kNeedFree = false;
|
static const bool kNeedFree = false;
|
||||||
};
|
};
|
||||||
@ -109,10 +117,14 @@ public:
|
|||||||
char* current_;
|
char* current_;
|
||||||
|
|
||||||
DirectStringBuffer(char* buffer, size_t maxLen)
|
DirectStringBuffer(char* buffer, size_t maxLen)
|
||||||
: buffer_(buffer), end_(buffer + maxLen), current_(buffer) {
|
: buffer_(buffer)
|
||||||
|
, end_(buffer + maxLen)
|
||||||
|
, current_(buffer)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Put(char c) {
|
void Put(char c)
|
||||||
|
{
|
||||||
if (current_ < end_) {
|
if (current_ < end_) {
|
||||||
*current_++ = c;
|
*current_++ = c;
|
||||||
}
|
}
|
||||||
@ -135,7 +147,10 @@ public:
|
|||||||
StackAllocator stackAlloc_;
|
StackAllocator stackAlloc_;
|
||||||
|
|
||||||
JsonWriter(char* dest, size_t maxLen)
|
JsonWriter(char* dest, size_t maxLen)
|
||||||
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels), stringBuffer_(dest, maxLen), stackAlloc_() {
|
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels)
|
||||||
|
, stringBuffer_(dest, maxLen)
|
||||||
|
, stackAlloc_()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Size() const { return stringBuffer_.GetSize(); }
|
size_t Size() const { return stringBuffer_.GetSize(); }
|
||||||
@ -155,14 +170,17 @@ public:
|
|||||||
: JsonDocumentBase(rapidjson::kObjectType,
|
: JsonDocumentBase(rapidjson::kObjectType,
|
||||||
&poolAllocator_,
|
&poolAllocator_,
|
||||||
sizeof(stackAllocator_.fixedBuffer_),
|
sizeof(stackAllocator_.fixedBuffer_),
|
||||||
&stackAllocator_),
|
&stackAllocator_)
|
||||||
poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_), stackAllocator_() {
|
, poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_)
|
||||||
|
, stackAllocator_()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>;
|
using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>;
|
||||||
|
|
||||||
inline JsonValue* GetObjMember(JsonValue* obj, const char* name) {
|
inline JsonValue* GetObjMember(JsonValue* obj, const char* name)
|
||||||
|
{
|
||||||
if (obj) {
|
if (obj) {
|
||||||
auto member = obj->FindMember(name);
|
auto member = obj->FindMember(name);
|
||||||
if (member != obj->MemberEnd() && member->value.IsObject()) {
|
if (member != obj->MemberEnd() && member->value.IsObject()) {
|
||||||
@ -172,7 +190,8 @@ inline JsonValue* GetObjMember(JsonValue* obj, const char* name) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) {
|
inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0)
|
||||||
|
{
|
||||||
if (obj) {
|
if (obj) {
|
||||||
auto member = obj->FindMember(name);
|
auto member = obj->FindMember(name);
|
||||||
if (member != obj->MemberEnd() && member->value.IsInt()) {
|
if (member != obj->MemberEnd() && member->value.IsInt()) {
|
||||||
@ -184,7 +203,8 @@ inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault =
|
|||||||
|
|
||||||
inline const char* GetStrMember(JsonValue* obj,
|
inline const char* GetStrMember(JsonValue* obj,
|
||||||
const char* name,
|
const char* name,
|
||||||
const char* notFoundDefault = nullptr) {
|
const char* notFoundDefault = nullptr)
|
||||||
|
{
|
||||||
if (obj) {
|
if (obj) {
|
||||||
auto member = obj->FindMember(name);
|
auto member = obj->FindMember(name);
|
||||||
if (member != obj->MemberEnd() && member->value.IsString()) {
|
if (member != obj->MemberEnd() && member->value.IsString()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user