10358 lines
		
	
	
		
			450 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			10358 lines
		
	
	
		
			450 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From de043145d0d663f0e68157e236ad19621af0fb92 Mon Sep 17 00:00:00 2001
 | 
						|
From: Christoph Oelckers <coelckers@users.noreply.github.com>
 | 
						|
Date: Sun, 26 Mar 2023 08:46:23 +0200
 | 
						|
Subject: [PATCH 44/51] - updated RapidJson library.
 | 
						|
 | 
						|
This still needed the Nan hotfix to be reapplied. The problem hasn't been addressed yet. :(
 | 
						|
---
 | 
						|
 src/common/thirdparty/rapidjson/allocators.h  |  534 ++++-
 | 
						|
 .../rapidjson/cursorstreamwrapper.h           |   78 +
 | 
						|
 src/common/thirdparty/rapidjson/document.h    |  789 +++++--
 | 
						|
 .../thirdparty/rapidjson/encodedstream.h      |    4 +-
 | 
						|
 src/common/thirdparty/rapidjson/encodings.h   |   88 +-
 | 
						|
 src/common/thirdparty/rapidjson/error/en.h    |  118 +-
 | 
						|
 src/common/thirdparty/rapidjson/error/error.h |  146 +-
 | 
						|
 .../thirdparty/rapidjson/filereadstream.h     |    6 +-
 | 
						|
 .../thirdparty/rapidjson/filewritestream.h    |    6 +-
 | 
						|
 src/common/thirdparty/rapidjson/fwd.h         |    4 +-
 | 
						|
 .../rapidjson/internal/biginteger.h           |   25 +-
 | 
						|
 .../thirdparty/rapidjson/internal/clzll.h     |   71 +
 | 
						|
 .../thirdparty/rapidjson/internal/diyfp.h     |   59 +-
 | 
						|
 .../thirdparty/rapidjson/internal/dtoa.h      |   18 +-
 | 
						|
 .../thirdparty/rapidjson/internal/ieee754.h   |    6 +-
 | 
						|
 .../thirdparty/rapidjson/internal/itoa.h      |   84 +-
 | 
						|
 .../thirdparty/rapidjson/internal/meta.h      |   11 +-
 | 
						|
 .../thirdparty/rapidjson/internal/pow10.h     |    2 +-
 | 
						|
 .../thirdparty/rapidjson/internal/regex.h     |  246 +-
 | 
						|
 .../thirdparty/rapidjson/internal/stack.h     |   12 +-
 | 
						|
 .../thirdparty/rapidjson/internal/strfunc.h   |   27 +-
 | 
						|
 .../thirdparty/rapidjson/internal/strtod.h    |  122 +-
 | 
						|
 .../thirdparty/rapidjson/internal/swap.h      |    2 +-
 | 
						|
 .../thirdparty/rapidjson/istreamwrapper.h     |   89 +-
 | 
						|
 .../thirdparty/rapidjson/memorybuffer.h       |    2 +-
 | 
						|
 .../thirdparty/rapidjson/memorystream.h       |    2 +-
 | 
						|
 .../thirdparty/rapidjson/ostreamwrapper.h     |    2 +-
 | 
						|
 src/common/thirdparty/rapidjson/pointer.h     |  194 +-
 | 
						|
 .../thirdparty/rapidjson/prettywriter.h       |   58 +-
 | 
						|
 src/common/thirdparty/rapidjson/rapidjson.h   |  220 +-
 | 
						|
 src/common/thirdparty/rapidjson/reader.h      |  677 ++++--
 | 
						|
 src/common/thirdparty/rapidjson/schema.h      | 1996 ++++++++++++++---
 | 
						|
 src/common/thirdparty/rapidjson/stream.h      |   54 +-
 | 
						|
 .../thirdparty/rapidjson/stringbuffer.h       |    6 +-
 | 
						|
 src/common/thirdparty/rapidjson/uri.h         |  481 ++++
 | 
						|
 src/common/thirdparty/rapidjson/writer.h      |  169 +-
 | 
						|
 36 files changed, 5147 insertions(+), 1261 deletions(-)
 | 
						|
 create mode 100644 src/common/thirdparty/rapidjson/cursorstreamwrapper.h
 | 
						|
 create mode 100644 src/common/thirdparty/rapidjson/internal/clzll.h
 | 
						|
 create mode 100644 src/common/thirdparty/rapidjson/uri.h
 | 
						|
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/allocators.h b/src/common/thirdparty/rapidjson/allocators.h
 | 
						|
index 98affe03f..ddcf4781b 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/allocators.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/allocators.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -16,6 +16,14 @@
 | 
						|
 #define RAPIDJSON_ALLOCATORS_H_
 | 
						|
 
 | 
						|
 #include "rapidjson.h"
 | 
						|
+#include "internal/meta.h"
 | 
						|
+
 | 
						|
+#include <memory>
 | 
						|
+#include <limits>
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+#include <type_traits>
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 
 | 
						|
@@ -52,6 +60,19 @@ concept Allocator {
 | 
						|
 \endcode
 | 
						|
 */
 | 
						|
 
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief User-defined kDefaultChunkCapacity definition.
 | 
						|
+
 | 
						|
+    User can define this as any \c size that is a power of 2.
 | 
						|
+*/
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
 | 
						|
+#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // CrtAllocator
 | 
						|
 
 | 
						|
@@ -64,19 +85,26 @@ public:
 | 
						|
     static const bool kNeedFree = true;
 | 
						|
     void* Malloc(size_t size) { 
 | 
						|
         if (size) //  behavior of malloc(0) is implementation defined.
 | 
						|
-            return std::malloc(size);
 | 
						|
+            return RAPIDJSON_MALLOC(size);
 | 
						|
         else
 | 
						|
             return NULL; // standardize to returning NULL.
 | 
						|
     }
 | 
						|
     void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
 | 
						|
         (void)originalSize;
 | 
						|
         if (newSize == 0) {
 | 
						|
-            std::free(originalPtr);
 | 
						|
+            RAPIDJSON_FREE(originalPtr);
 | 
						|
             return NULL;
 | 
						|
         }
 | 
						|
-        return std::realloc(originalPtr, newSize);
 | 
						|
+        return RAPIDJSON_REALLOC(originalPtr, newSize);
 | 
						|
+    }
 | 
						|
+    static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
 | 
						|
+
 | 
						|
+    bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+    bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
 | 
						|
+        return false;
 | 
						|
     }
 | 
						|
-    static void Free(void *ptr) { std::free(ptr); }
 | 
						|
 };
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
@@ -100,16 +128,64 @@ public:
 | 
						|
 */
 | 
						|
 template <typename BaseAllocator = CrtAllocator>
 | 
						|
 class MemoryPoolAllocator {
 | 
						|
+    //! Chunk header for perpending to each chunk.
 | 
						|
+    /*! Chunks are stored as a singly linked list.
 | 
						|
+    */
 | 
						|
+    struct ChunkHeader {
 | 
						|
+        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
 | 
						|
+        size_t size;        //!< Current size of allocated memory in bytes.
 | 
						|
+        ChunkHeader *next;  //!< Next chunk in the linked list.
 | 
						|
+    };
 | 
						|
+
 | 
						|
+    struct SharedData {
 | 
						|
+        ChunkHeader *chunkHead;  //!< Head of the chunk linked-list. Only the head chunk serves allocation.
 | 
						|
+        BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
 | 
						|
+        size_t refcount;
 | 
						|
+        bool ownBuffer;
 | 
						|
+    };
 | 
						|
+
 | 
						|
+    static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
 | 
						|
+    static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
 | 
						|
+
 | 
						|
+    static inline ChunkHeader *GetChunkHead(SharedData *shared)
 | 
						|
+    {
 | 
						|
+        return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
 | 
						|
+    }
 | 
						|
+    static inline uint8_t *GetChunkBuffer(SharedData *shared)
 | 
						|
+    {
 | 
						|
+        return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
 | 
						|
+
 | 
						|
 public:
 | 
						|
     static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
 | 
						|
+    static const bool kRefCounted = true;   //!< Tell users that this allocator is reference counted on copy
 | 
						|
 
 | 
						|
     //! Constructor with chunkSize.
 | 
						|
     /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
 | 
						|
         \param baseAllocator The allocator for allocating memory chunks.
 | 
						|
     */
 | 
						|
+    explicit
 | 
						|
     MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 
 | 
						|
-        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
 | 
						|
+        chunk_capacity_(chunkSize),
 | 
						|
+        baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
 | 
						|
+        shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
 | 
						|
     {
 | 
						|
+        RAPIDJSON_ASSERT(baseAllocator_ != 0);
 | 
						|
+        RAPIDJSON_ASSERT(shared_ != 0);
 | 
						|
+        if (baseAllocator) {
 | 
						|
+            shared_->ownBaseAllocator = 0;
 | 
						|
+        }
 | 
						|
+        else {
 | 
						|
+            shared_->ownBaseAllocator = baseAllocator_;
 | 
						|
+        }
 | 
						|
+        shared_->chunkHead = GetChunkHead(shared_);
 | 
						|
+        shared_->chunkHead->capacity = 0;
 | 
						|
+        shared_->chunkHead->size = 0;
 | 
						|
+        shared_->chunkHead->next = 0;
 | 
						|
+        shared_->ownBuffer = true;
 | 
						|
+        shared_->refcount = 1;
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Constructor with user-supplied buffer.
 | 
						|
@@ -123,41 +199,101 @@ public:
 | 
						|
         \param baseAllocator The allocator for allocating memory chunks.
 | 
						|
     */
 | 
						|
     MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
 | 
						|
-        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
 | 
						|
+        chunk_capacity_(chunkSize),
 | 
						|
+        baseAllocator_(baseAllocator),
 | 
						|
+        shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
 | 
						|
     {
 | 
						|
-        RAPIDJSON_ASSERT(buffer != 0);
 | 
						|
-        RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
 | 
						|
-        chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
 | 
						|
-        chunkHead_->capacity = size - sizeof(ChunkHeader);
 | 
						|
-        chunkHead_->size = 0;
 | 
						|
-        chunkHead_->next = 0;
 | 
						|
+        RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
 | 
						|
+        shared_->chunkHead = GetChunkHead(shared_);
 | 
						|
+        shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
 | 
						|
+        shared_->chunkHead->size = 0;
 | 
						|
+        shared_->chunkHead->next = 0;
 | 
						|
+        shared_->ownBaseAllocator = 0;
 | 
						|
+        shared_->ownBuffer = false;
 | 
						|
+        shared_->refcount = 1;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        chunk_capacity_(rhs.chunk_capacity_),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_),
 | 
						|
+        shared_(rhs.shared_)
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
+        ++shared_->refcount;
 | 
						|
+    }
 | 
						|
+    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
						|
+        ++rhs.shared_->refcount;
 | 
						|
+        this->~MemoryPoolAllocator();
 | 
						|
+        baseAllocator_ = rhs.baseAllocator_;
 | 
						|
+        chunk_capacity_ = rhs.chunk_capacity_;
 | 
						|
+        shared_ = rhs.shared_;
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
+    MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        chunk_capacity_(rhs.chunk_capacity_),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_),
 | 
						|
+        shared_(rhs.shared_)
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
						|
+        rhs.shared_ = 0;
 | 
						|
+    }
 | 
						|
+    MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
						|
+        this->~MemoryPoolAllocator();
 | 
						|
+        baseAllocator_ = rhs.baseAllocator_;
 | 
						|
+        chunk_capacity_ = rhs.chunk_capacity_;
 | 
						|
+        shared_ = rhs.shared_;
 | 
						|
+        rhs.shared_ = 0;
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
     //! Destructor.
 | 
						|
     /*! This deallocates all memory chunks, excluding the user-supplied buffer.
 | 
						|
     */
 | 
						|
-    ~MemoryPoolAllocator() {
 | 
						|
+    ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
 | 
						|
+        if (!shared_) {
 | 
						|
+            // do nothing if moved
 | 
						|
+            return;
 | 
						|
+        }
 | 
						|
+        if (shared_->refcount > 1) {
 | 
						|
+            --shared_->refcount;
 | 
						|
+            return;
 | 
						|
+        }
 | 
						|
         Clear();
 | 
						|
-        RAPIDJSON_DELETE(ownBaseAllocator_);
 | 
						|
+        BaseAllocator *a = shared_->ownBaseAllocator;
 | 
						|
+        if (shared_->ownBuffer) {
 | 
						|
+            baseAllocator_->Free(shared_);
 | 
						|
+        }
 | 
						|
+        RAPIDJSON_DELETE(a);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    //! Deallocates all memory chunks, excluding the user-supplied buffer.
 | 
						|
-    void Clear() {
 | 
						|
-        while (chunkHead_ && chunkHead_ != userBuffer_) {
 | 
						|
-            ChunkHeader* next = chunkHead_->next;
 | 
						|
-            baseAllocator_->Free(chunkHead_);
 | 
						|
-            chunkHead_ = next;
 | 
						|
+    //! Deallocates all memory chunks, excluding the first/user one.
 | 
						|
+    void Clear() RAPIDJSON_NOEXCEPT {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
+        for (;;) {
 | 
						|
+            ChunkHeader* c = shared_->chunkHead;
 | 
						|
+            if (!c->next) {
 | 
						|
+                break;
 | 
						|
+            }
 | 
						|
+            shared_->chunkHead = c->next;
 | 
						|
+            baseAllocator_->Free(c);
 | 
						|
         }
 | 
						|
-        if (chunkHead_ && chunkHead_ == userBuffer_)
 | 
						|
-            chunkHead_->size = 0; // Clear user buffer
 | 
						|
+        shared_->chunkHead->size = 0;
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Computes the total capacity of allocated memory chunks.
 | 
						|
     /*! \return total capacity in bytes.
 | 
						|
     */
 | 
						|
-    size_t Capacity() const {
 | 
						|
+    size_t Capacity() const RAPIDJSON_NOEXCEPT {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
         size_t capacity = 0;
 | 
						|
-        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
 | 
						|
+        for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
 | 
						|
             capacity += c->capacity;
 | 
						|
         return capacity;
 | 
						|
     }
 | 
						|
@@ -165,25 +301,35 @@ public:
 | 
						|
     //! Computes the memory blocks allocated.
 | 
						|
     /*! \return total used bytes.
 | 
						|
     */
 | 
						|
-    size_t Size() const {
 | 
						|
+    size_t Size() const RAPIDJSON_NOEXCEPT {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
         size_t size = 0;
 | 
						|
-        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
 | 
						|
+        for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
 | 
						|
             size += c->size;
 | 
						|
         return size;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    //! Whether the allocator is shared.
 | 
						|
+    /*! \return true or false.
 | 
						|
+    */
 | 
						|
+    bool Shared() const RAPIDJSON_NOEXCEPT {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
+        return shared_->refcount > 1;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     //! Allocates a memory block. (concept Allocator)
 | 
						|
     void* Malloc(size_t size) {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
         if (!size)
 | 
						|
             return NULL;
 | 
						|
 
 | 
						|
         size = RAPIDJSON_ALIGN(size);
 | 
						|
-        if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
 | 
						|
+        if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
 | 
						|
             if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
 | 
						|
                 return NULL;
 | 
						|
 
 | 
						|
-        void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
 | 
						|
-        chunkHead_->size += size;
 | 
						|
+        void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
 | 
						|
+        shared_->chunkHead->size += size;
 | 
						|
         return buffer;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -192,6 +338,7 @@ public:
 | 
						|
         if (originalPtr == 0)
 | 
						|
             return Malloc(newSize);
 | 
						|
 
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
         if (newSize == 0)
 | 
						|
             return NULL;
 | 
						|
 
 | 
						|
@@ -203,10 +350,10 @@ public:
 | 
						|
             return originalPtr;
 | 
						|
 
 | 
						|
         // Simply expand it if it is the last allocation and there is sufficient space
 | 
						|
-        if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
 | 
						|
+        if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
 | 
						|
             size_t increment = static_cast<size_t>(newSize - originalSize);
 | 
						|
-            if (chunkHead_->size + increment <= chunkHead_->capacity) {
 | 
						|
-                chunkHead_->size += increment;
 | 
						|
+            if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
 | 
						|
+                shared_->chunkHead->size += increment;
 | 
						|
                 return originalPtr;
 | 
						|
             }
 | 
						|
         }
 | 
						|
@@ -222,50 +369,325 @@ public:
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Frees a memory block (concept Allocator)
 | 
						|
-    static void Free(void *ptr) { (void)ptr; } // Do nothing
 | 
						|
+    static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
 | 
						|
 
 | 
						|
-private:
 | 
						|
-    //! Copy constructor is not permitted.
 | 
						|
-    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
 | 
						|
-    //! Copy assignment operator is not permitted.
 | 
						|
-    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
 | 
						|
+    //! Compare (equality) with another MemoryPoolAllocator
 | 
						|
+    bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
						|
+        return shared_ == rhs.shared_;
 | 
						|
+    }
 | 
						|
+    //! Compare (inequality) with another MemoryPoolAllocator
 | 
						|
+    bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
 | 
						|
+        return !operator==(rhs);
 | 
						|
+    }
 | 
						|
 
 | 
						|
+private:
 | 
						|
     //! Creates a new chunk.
 | 
						|
     /*! \param capacity Capacity of the chunk in bytes.
 | 
						|
         \return true if success.
 | 
						|
     */
 | 
						|
     bool AddChunk(size_t capacity) {
 | 
						|
         if (!baseAllocator_)
 | 
						|
-            ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
 | 
						|
-        if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
 | 
						|
+            shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
 | 
						|
+        if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
 | 
						|
             chunk->capacity = capacity;
 | 
						|
             chunk->size = 0;
 | 
						|
-            chunk->next = chunkHead_;
 | 
						|
-            chunkHead_ =  chunk;
 | 
						|
+            chunk->next = shared_->chunkHead;
 | 
						|
+            shared_->chunkHead = chunk;
 | 
						|
             return true;
 | 
						|
         }
 | 
						|
         else
 | 
						|
             return false;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
 | 
						|
-
 | 
						|
-    //! Chunk header for perpending to each chunk.
 | 
						|
-    /*! Chunks are stored as a singly linked list.
 | 
						|
-    */
 | 
						|
-    struct ChunkHeader {
 | 
						|
-        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
 | 
						|
-        size_t size;        //!< Current size of allocated memory in bytes.
 | 
						|
-        ChunkHeader *next;  //!< Next chunk in the linked list.
 | 
						|
-    };
 | 
						|
+    static inline void* AlignBuffer(void* buf, size_t &size)
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
 | 
						|
+        const uintptr_t mask = sizeof(void*) - 1;
 | 
						|
+        const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
 | 
						|
+        if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
 | 
						|
+            const uintptr_t abuf = (ubuf + mask) & ~mask;
 | 
						|
+            RAPIDJSON_ASSERT(size >= abuf - ubuf);
 | 
						|
+            buf = reinterpret_cast<void*>(abuf);
 | 
						|
+            size -= abuf - ubuf;
 | 
						|
+        }
 | 
						|
+        return buf;
 | 
						|
+    }
 | 
						|
 
 | 
						|
-    ChunkHeader *chunkHead_;    //!< Head of the chunk linked-list. Only the head chunk serves allocation.
 | 
						|
     size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.
 | 
						|
-    void *userBuffer_;          //!< User supplied buffer.
 | 
						|
     BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.
 | 
						|
-    BaseAllocator* ownBaseAllocator_;   //!< base allocator created by this object.
 | 
						|
+    SharedData *shared_;        //!< The shared data of the allocator
 | 
						|
+};
 | 
						|
+
 | 
						|
+namespace internal {
 | 
						|
+    template<typename, typename = void>
 | 
						|
+    struct IsRefCounted :
 | 
						|
+        public FalseType
 | 
						|
+    { };
 | 
						|
+    template<typename T>
 | 
						|
+    struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
 | 
						|
+        public TrueType
 | 
						|
+    { };
 | 
						|
+}
 | 
						|
+
 | 
						|
+template<typename T, typename A>
 | 
						|
+inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
 | 
						|
+{
 | 
						|
+    RAPIDJSON_NOEXCEPT_ASSERT(old_n <= std::numeric_limits<size_t>::max() / sizeof(T) && new_n <= std::numeric_limits<size_t>::max() / sizeof(T));
 | 
						|
+    return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
 | 
						|
+}
 | 
						|
+
 | 
						|
+template<typename T, typename A>
 | 
						|
+inline T *Malloc(A& a, size_t n = 1)
 | 
						|
+{
 | 
						|
+    return Realloc<T, A>(a, NULL, 0, n);
 | 
						|
+}
 | 
						|
+
 | 
						|
+template<typename T, typename A>
 | 
						|
+inline void Free(A& a, T *p, size_t n = 1)
 | 
						|
+{
 | 
						|
+    static_cast<void>(Realloc<T, A>(a, p, n, 0));
 | 
						|
+}
 | 
						|
+
 | 
						|
+#ifdef __GNUC__
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+template <typename T, typename BaseAllocator = CrtAllocator>
 | 
						|
+class StdAllocator :
 | 
						|
+    public std::allocator<T>
 | 
						|
+{
 | 
						|
+    typedef std::allocator<T> allocator_type;
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+    typedef std::allocator_traits<allocator_type> traits_type;
 | 
						|
+#else
 | 
						|
+    typedef allocator_type traits_type;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+public:
 | 
						|
+    typedef BaseAllocator BaseAllocatorType;
 | 
						|
+
 | 
						|
+    StdAllocator() RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(),
 | 
						|
+        baseAllocator_()
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(rhs),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    template<typename U>
 | 
						|
+    StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(rhs),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
+    StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(std::move(rhs)),
 | 
						|
+        baseAllocator_(std::move(rhs.baseAllocator_))
 | 
						|
+    { }
 | 
						|
+#endif
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+    using propagate_on_container_move_assignment = std::true_type;
 | 
						|
+    using propagate_on_container_swap = std::true_type;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    /* implicit */
 | 
						|
+    StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(),
 | 
						|
+        baseAllocator_(allocator)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    ~StdAllocator() RAPIDJSON_NOEXCEPT
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    template<typename U>
 | 
						|
+    struct rebind {
 | 
						|
+        typedef StdAllocator<U, BaseAllocator> other;
 | 
						|
+    };
 | 
						|
+
 | 
						|
+    typedef typename traits_type::size_type         size_type;
 | 
						|
+    typedef typename traits_type::difference_type   difference_type;
 | 
						|
+
 | 
						|
+    typedef typename traits_type::value_type        value_type;
 | 
						|
+    typedef typename traits_type::pointer           pointer;
 | 
						|
+    typedef typename traits_type::const_pointer     const_pointer;
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+
 | 
						|
+    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;
 | 
						|
+
 | 
						|
+    pointer address(reference r) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return std::addressof(r);
 | 
						|
+    }
 | 
						|
+    const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return std::addressof(r);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    size_type max_size() const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return traits_type::max_size(*this);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    template <typename ...Args>
 | 
						|
+    void construct(pointer p, Args&&... args)
 | 
						|
+    {
 | 
						|
+        traits_type::construct(*this, p, std::forward<Args>(args)...);
 | 
						|
+    }
 | 
						|
+    void destroy(pointer p)
 | 
						|
+    {
 | 
						|
+        traits_type::destroy(*this, p);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#else // !RAPIDJSON_HAS_CXX11
 | 
						|
+
 | 
						|
+    typedef typename allocator_type::reference       reference;
 | 
						|
+    typedef typename allocator_type::const_reference const_reference;
 | 
						|
+
 | 
						|
+    pointer address(reference r) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return allocator_type::address(r);
 | 
						|
+    }
 | 
						|
+    const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return allocator_type::address(r);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    size_type max_size() const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return allocator_type::max_size();
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void construct(pointer p, const_reference r)
 | 
						|
+    {
 | 
						|
+        allocator_type::construct(p, r);
 | 
						|
+    }
 | 
						|
+    void destroy(pointer p)
 | 
						|
+    {
 | 
						|
+        allocator_type::destroy(p);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#endif // !RAPIDJSON_HAS_CXX11
 | 
						|
+
 | 
						|
+    template <typename U>
 | 
						|
+    U* allocate(size_type n = 1, const void* = 0)
 | 
						|
+    {
 | 
						|
+        return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
 | 
						|
+    }
 | 
						|
+    template <typename U>
 | 
						|
+    void deallocate(U* p, size_type n = 1)
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    pointer allocate(size_type n = 1, const void* = 0)
 | 
						|
+    {
 | 
						|
+        return allocate<value_type>(n);
 | 
						|
+    }
 | 
						|
+    void deallocate(pointer p, size_type n = 1)
 | 
						|
+    {
 | 
						|
+        deallocate<value_type>(p, n);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+    using is_always_equal = std::is_empty<BaseAllocator>;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    template<typename U>
 | 
						|
+    bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return baseAllocator_ == rhs.baseAllocator_;
 | 
						|
+    }
 | 
						|
+    template<typename U>
 | 
						|
+    bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        return !operator==(rhs);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! rapidjson Allocator concept
 | 
						|
+    static const bool kNeedFree = BaseAllocator::kNeedFree;
 | 
						|
+    static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
 | 
						|
+    void* Malloc(size_t size)
 | 
						|
+    {
 | 
						|
+        return baseAllocator_.Malloc(size);
 | 
						|
+    }
 | 
						|
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
 | 
						|
+    {
 | 
						|
+        return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
 | 
						|
+    }
 | 
						|
+    static void Free(void *ptr) RAPIDJSON_NOEXCEPT
 | 
						|
+    {
 | 
						|
+        BaseAllocator::Free(ptr);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    template <typename, typename>
 | 
						|
+    friend class StdAllocator; // access to StdAllocator<!T>.*
 | 
						|
+
 | 
						|
+    BaseAllocator baseAllocator_;
 | 
						|
 };
 | 
						|
 
 | 
						|
+#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
 | 
						|
+template <typename BaseAllocator>
 | 
						|
+class StdAllocator<void, BaseAllocator> :
 | 
						|
+    public std::allocator<void>
 | 
						|
+{
 | 
						|
+    typedef std::allocator<void> allocator_type;
 | 
						|
+
 | 
						|
+public:
 | 
						|
+    typedef BaseAllocator BaseAllocatorType;
 | 
						|
+
 | 
						|
+    StdAllocator() RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(),
 | 
						|
+        baseAllocator_()
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(rhs),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    template<typename U>
 | 
						|
+    StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(rhs),
 | 
						|
+        baseAllocator_(rhs.baseAllocator_)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    /* implicit */
 | 
						|
+    StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
 | 
						|
+        allocator_type(),
 | 
						|
+        baseAllocator_(baseAllocator)
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    ~StdAllocator() RAPIDJSON_NOEXCEPT
 | 
						|
+    { }
 | 
						|
+
 | 
						|
+    template<typename U>
 | 
						|
+    struct rebind {
 | 
						|
+        typedef StdAllocator<U, BaseAllocator> other;
 | 
						|
+    };
 | 
						|
+
 | 
						|
+    typedef typename allocator_type::value_type value_type;
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    template <typename, typename>
 | 
						|
+    friend class StdAllocator; // access to StdAllocator<!T>.*
 | 
						|
+
 | 
						|
+    BaseAllocator baseAllocator_;
 | 
						|
+};
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#ifdef __GNUC__
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
 #endif // RAPIDJSON_ENCODINGS_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/cursorstreamwrapper.h b/src/common/thirdparty/rapidjson/cursorstreamwrapper.h
 | 
						|
new file mode 100644
 | 
						|
index 000000000..fd6513db1
 | 
						|
--- /dev/null
 | 
						|
+++ b/src/common/thirdparty/rapidjson/cursorstreamwrapper.h
 | 
						|
@@ -0,0 +1,78 @@
 | 
						|
+// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
+//
 | 
						|
+// Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
+// in compliance with the License. You may obtain a copy of the License at
 | 
						|
+//
 | 
						|
+// http://opensource.org/licenses/MIT
 | 
						|
+//
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
+// specific language governing permissions and limitations under the License.
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
						|
+#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
						|
+
 | 
						|
+#include "stream.h"
 | 
						|
+
 | 
						|
+#if defined(__GNUC__)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(effc++)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
						|
+RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
+
 | 
						|
+
 | 
						|
+//! Cursor stream wrapper for counting line and column number if error exists.
 | 
						|
+/*!
 | 
						|
+    \tparam InputStream     Any stream that implements Stream Concept
 | 
						|
+*/
 | 
						|
+template <typename InputStream, typename Encoding = UTF8<> >
 | 
						|
+class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
 | 
						|
+public:
 | 
						|
+    typedef typename Encoding::Ch Ch;
 | 
						|
+
 | 
						|
+    CursorStreamWrapper(InputStream& is):
 | 
						|
+        GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
 | 
						|
+
 | 
						|
+    // counting line and column number
 | 
						|
+    Ch Take() {
 | 
						|
+        Ch ch = this->is_.Take();
 | 
						|
+        if(ch == '\n') {
 | 
						|
+            line_ ++;
 | 
						|
+            col_ = 0;
 | 
						|
+        } else {
 | 
						|
+            col_ ++;
 | 
						|
+        }
 | 
						|
+        return ch;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Get the error line number, if error exists.
 | 
						|
+    size_t GetLine() const { return line_; }
 | 
						|
+    //! Get the error column number, if error exists.
 | 
						|
+    size_t GetColumn() const { return col_; }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    size_t line_;   //!< Current Line
 | 
						|
+    size_t col_;    //!< Current Column
 | 
						|
+};
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#if defined(__GNUC__)
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_END
 | 
						|
+
 | 
						|
+#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/document.h b/src/common/thirdparty/rapidjson/document.h
 | 
						|
index 9cab4e83d..2cd9a70a6 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/document.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/document.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -24,33 +24,39 @@
 | 
						|
 #include "encodedstream.h"
 | 
						|
 #include <new>      // placement new
 | 
						|
 #include <limits>
 | 
						|
-
 | 
						|
-RAPIDJSON_DIAG_PUSH
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 | 
						|
-RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
 | 
						|
-RAPIDJSON_DIAG_OFF(4996) // deprecation of std::iterator
 | 
						|
+#ifdef __cpp_lib_three_way_comparison
 | 
						|
+#include <compare>
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
 #ifdef __clang__
 | 
						|
 RAPIDJSON_DIAG_OFF(padded)
 | 
						|
 RAPIDJSON_DIAG_OFF(switch-enum)
 | 
						|
 RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 | 
						|
+RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #ifdef __GNUC__
 | 
						|
 RAPIDJSON_DIAG_OFF(effc++)
 | 
						|
-#if __GNUC__ >= 6
 | 
						|
-RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
 | 
						|
-#endif
 | 
						|
 #endif // __GNUC__
 | 
						|
 
 | 
						|
+#ifdef GetObject
 | 
						|
+// see https://github.com/Tencent/rapidjson/issues/1448
 | 
						|
+// a former included windows.h might have defined a macro called GetObject, which affects
 | 
						|
+// GetObject defined here. This ensures the macro does not get applied
 | 
						|
+#pragma push_macro("GetObject")
 | 
						|
+#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
 | 
						|
+#undef GetObject
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #ifndef RAPIDJSON_NOMEMBERITERATORCLASS
 | 
						|
-#include <iterator> // std::iterator, std::random_access_iterator_tag
 | 
						|
+#include <iterator> // std::random_access_iterator_tag
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
-#include <utility> // std::move
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+#include <map> // std::multimap
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
@@ -62,6 +68,48 @@ class GenericValue;
 | 
						|
 template <typename Encoding, typename Allocator, typename StackAllocator>
 | 
						|
 class GenericDocument;
 | 
						|
 
 | 
						|
+/*! \def RAPIDJSON_DEFAULT_ALLOCATOR
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief Allows to choose default allocator.
 | 
						|
+
 | 
						|
+    User can define this to use CrtAllocator or MemoryPoolAllocator.
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_DEFAULT_ALLOCATOR
 | 
						|
+#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator>
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief Allows to choose default stack allocator for Document.
 | 
						|
+
 | 
						|
+    User can define this to use CrtAllocator or MemoryPoolAllocator.
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR
 | 
						|
+#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief User defined kDefaultObjectCapacity value.
 | 
						|
+
 | 
						|
+    User can define this as any natural number.
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY
 | 
						|
+// number of objects that rapidjson::Value allocates memory for by default
 | 
						|
+#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief User defined kDefaultArrayCapacity value.
 | 
						|
+
 | 
						|
+    User can define this as any natural number.
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY
 | 
						|
+// number of array elements that rapidjson::Value allocates memory for by default
 | 
						|
+#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 //! Name-value pair in a JSON object value.
 | 
						|
 /*!
 | 
						|
     This class was internal to GenericValue. It used to be a inner struct.
 | 
						|
@@ -69,9 +117,45 @@ class GenericDocument;
 | 
						|
     https://code.google.com/p/rapidjson/issues/detail?id=64
 | 
						|
 */
 | 
						|
 template <typename Encoding, typename Allocator> 
 | 
						|
-struct GenericMember { 
 | 
						|
+class GenericMember {
 | 
						|
+public:
 | 
						|
     GenericValue<Encoding, Allocator> name;     //!< name of member (must be a string)
 | 
						|
     GenericValue<Encoding, Allocator> value;    //!< value of member.
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
+    //! Move constructor in C++11
 | 
						|
+    GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT
 | 
						|
+        : name(std::move(rhs.name)),
 | 
						|
+          value(std::move(rhs.value))
 | 
						|
+    {
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Move assignment in C++11
 | 
						|
+    GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT {
 | 
						|
+        return *this = static_cast<GenericMember&>(rhs);
 | 
						|
+    }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    //! Assignment with move semantics.
 | 
						|
+    /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment.
 | 
						|
+    */
 | 
						|
+    GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT {
 | 
						|
+        if (RAPIDJSON_LIKELY(this != &rhs)) {
 | 
						|
+            name = rhs.name;
 | 
						|
+            value = rhs.value;
 | 
						|
+        }
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // swap() for std::sort() and other potential use in STL.
 | 
						|
+    friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT {
 | 
						|
+        a.name.Swap(b.name);
 | 
						|
+        a.value.Swap(b.value);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    //! Copy constructor is not permitted.
 | 
						|
+    GenericMember(const GenericMember& rhs);
 | 
						|
 };
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
@@ -99,16 +183,13 @@ struct GenericMember {
 | 
						|
     \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
 | 
						|
  */
 | 
						|
 template <bool Const, typename Encoding, typename Allocator>
 | 
						|
-class GenericMemberIterator
 | 
						|
-    : public std::iterator<std::random_access_iterator_tag
 | 
						|
-        , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
 | 
						|
+class GenericMemberIterator {
 | 
						|
 
 | 
						|
     friend class GenericValue<Encoding,Allocator>;
 | 
						|
     template <bool, typename, typename> friend class GenericMemberIterator;
 | 
						|
 
 | 
						|
     typedef GenericMember<Encoding,Allocator> PlainType;
 | 
						|
     typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
 | 
						|
-    typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
 | 
						|
 
 | 
						|
 public:
 | 
						|
     //! Iterator type itself
 | 
						|
@@ -118,12 +199,21 @@ public:
 | 
						|
     //! Non-constant iterator type
 | 
						|
     typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
 | 
						|
 
 | 
						|
+    /** \name std::iterator_traits support */
 | 
						|
+    //@{
 | 
						|
+    typedef ValueType      value_type;
 | 
						|
+    typedef ValueType *    pointer;
 | 
						|
+    typedef ValueType &    reference;
 | 
						|
+    typedef std::ptrdiff_t difference_type;
 | 
						|
+    typedef std::random_access_iterator_tag iterator_category;
 | 
						|
+    //@}
 | 
						|
+
 | 
						|
     //! Pointer to (const) GenericMember
 | 
						|
-    typedef typename BaseType::pointer         Pointer;
 | 
						|
+    typedef pointer         Pointer;
 | 
						|
     //! Reference to (const) GenericMember
 | 
						|
-    typedef typename BaseType::reference       Reference;
 | 
						|
+    typedef reference       Reference;
 | 
						|
     //! Signed integer type (e.g. \c ptrdiff_t)
 | 
						|
-    typedef typename BaseType::difference_type DifferenceType;
 | 
						|
+    typedef difference_type DifferenceType;
 | 
						|
 
 | 
						|
     //! Default constructor (singular value)
 | 
						|
     /*! Creates an iterator pointing to no element.
 | 
						|
@@ -169,12 +259,16 @@ public:
 | 
						|
 
 | 
						|
     //! @name relations
 | 
						|
     //@{
 | 
						|
-    bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
 | 
						|
-    bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
 | 
						|
-    bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
 | 
						|
-    bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
 | 
						|
-    bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
 | 
						|
-    bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
 | 
						|
+    template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; }
 | 
						|
+
 | 
						|
+#ifdef __cpp_lib_three_way_comparison
 | 
						|
+    template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
 | 
						|
+#endif
 | 
						|
     //@}
 | 
						|
 
 | 
						|
     //! @name dereference
 | 
						|
@@ -199,17 +293,19 @@ private:
 | 
						|
 // class-based member iterator implementation disabled, use plain pointers
 | 
						|
 
 | 
						|
 template <bool Const, typename Encoding, typename Allocator>
 | 
						|
-struct GenericMemberIterator;
 | 
						|
+class GenericMemberIterator;
 | 
						|
 
 | 
						|
 //! non-const GenericMemberIterator
 | 
						|
 template <typename Encoding, typename Allocator>
 | 
						|
-struct GenericMemberIterator<false,Encoding,Allocator> {
 | 
						|
+class GenericMemberIterator<false,Encoding,Allocator> {
 | 
						|
+public:
 | 
						|
     //! use plain pointer as iterator type
 | 
						|
     typedef GenericMember<Encoding,Allocator>* Iterator;
 | 
						|
 };
 | 
						|
 //! const GenericMemberIterator
 | 
						|
 template <typename Encoding, typename Allocator>
 | 
						|
-struct GenericMemberIterator<true,Encoding,Allocator> {
 | 
						|
+class GenericMemberIterator<true,Encoding,Allocator> {
 | 
						|
+public:
 | 
						|
     //! use plain const pointer as iterator type
 | 
						|
     typedef const GenericMember<Encoding,Allocator>* Iterator;
 | 
						|
 };
 | 
						|
@@ -301,7 +397,7 @@ struct GenericStringRef {
 | 
						|
      */
 | 
						|
 #endif
 | 
						|
     explicit GenericStringRef(const CharType* str)
 | 
						|
-        : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
 | 
						|
+        : s(str), length(NotNullStrLen(str)) {}
 | 
						|
 
 | 
						|
     //! Create constant string reference from pointer and length
 | 
						|
 #ifndef __clang__ // -Wdocumentation
 | 
						|
@@ -313,7 +409,7 @@ struct GenericStringRef {
 | 
						|
      */
 | 
						|
 #endif
 | 
						|
     GenericStringRef(const CharType* str, SizeType len)
 | 
						|
-        : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
 | 
						|
+        : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
 | 
						|
 
 | 
						|
     GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
 | 
						|
 
 | 
						|
@@ -324,6 +420,14 @@ struct GenericStringRef {
 | 
						|
     const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
 | 
						|
 
 | 
						|
 private:
 | 
						|
+    SizeType NotNullStrLen(const CharType* str) {
 | 
						|
+        RAPIDJSON_ASSERT(str != 0);
 | 
						|
+        return internal::StrLen(str);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    /// Empty string - used when passing in a NULL pointer
 | 
						|
+    static const Ch emptyString[];
 | 
						|
+
 | 
						|
     //! Disallow construction from non-const array
 | 
						|
     template<SizeType N>
 | 
						|
     GenericStringRef(CharType (&str)[N]) /* = delete */;
 | 
						|
@@ -331,6 +435,9 @@ private:
 | 
						|
     GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
 | 
						|
 };
 | 
						|
 
 | 
						|
+template<typename CharType>
 | 
						|
+const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
 | 
						|
+
 | 
						|
 //! Mark a character pointer as constant string
 | 
						|
 /*! Mark a plain character pointer as a "string literal".  This function
 | 
						|
     can be used to avoid copying a character string to be referenced as a
 | 
						|
@@ -345,7 +452,7 @@ private:
 | 
						|
 */
 | 
						|
 template<typename CharType>
 | 
						|
 inline GenericStringRef<CharType> StringRef(const CharType* str) {
 | 
						|
-    return GenericStringRef<CharType>(str, internal::StrLen(str));
 | 
						|
+    return GenericStringRef<CharType>(str);
 | 
						|
 }
 | 
						|
 
 | 
						|
 //! Mark a character pointer as constant string
 | 
						|
@@ -435,6 +542,26 @@ struct TypeHelper<ValueType, unsigned> {
 | 
						|
     static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
 | 
						|
 };
 | 
						|
 
 | 
						|
+#ifdef _MSC_VER
 | 
						|
+RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int));
 | 
						|
+template<typename ValueType>
 | 
						|
+struct TypeHelper<ValueType, long> {
 | 
						|
+    static bool Is(const ValueType& v) { return v.IsInt(); }
 | 
						|
+    static long Get(const ValueType& v) { return v.GetInt(); }
 | 
						|
+    static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); }
 | 
						|
+    static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
 | 
						|
+};
 | 
						|
+
 | 
						|
+RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned));
 | 
						|
+template<typename ValueType>
 | 
						|
+struct TypeHelper<ValueType, unsigned long> {
 | 
						|
+    static bool Is(const ValueType& v) { return v.IsUint(); }
 | 
						|
+    static unsigned long Get(const ValueType& v) { return v.GetUint(); }
 | 
						|
+    static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); }
 | 
						|
+    static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
 | 
						|
+};
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 template<typename ValueType> 
 | 
						|
 struct TypeHelper<ValueType, int64_t> {
 | 
						|
     static bool Is(const ValueType& v) { return v.IsInt64(); }
 | 
						|
@@ -508,7 +635,7 @@ struct TypeHelper<ValueType, typename ValueType::Object> {
 | 
						|
     static bool Is(const ValueType& v) { return v.IsObject(); }
 | 
						|
     static ObjectType Get(ValueType& v) { return v.GetObject(); }
 | 
						|
     static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
 | 
						|
-    static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
 | 
						|
+    static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }
 | 
						|
 };
 | 
						|
 
 | 
						|
 template<typename ValueType> 
 | 
						|
@@ -537,7 +664,7 @@ template <bool, typename> class GenericObject;
 | 
						|
     \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
 | 
						|
     \tparam Allocator   Allocator type for allocating memory of object, array and string.
 | 
						|
 */
 | 
						|
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > 
 | 
						|
+template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR >
 | 
						|
 class GenericValue {
 | 
						|
 public:
 | 
						|
     //! Name-value pair in an object.
 | 
						|
@@ -591,11 +718,11 @@ public:
 | 
						|
         \note Default content for number is zero.
 | 
						|
     */
 | 
						|
     explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
 | 
						|
-        static const uint16_t defaultFlags[7] = {
 | 
						|
+        static const uint16_t defaultFlags[] = {
 | 
						|
             kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
 | 
						|
             kNumberAnyFlag
 | 
						|
         };
 | 
						|
-        RAPIDJSON_ASSERT(type <= kNumberType);
 | 
						|
+        RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType);
 | 
						|
         data_.f.flags = defaultFlags[type];
 | 
						|
 
 | 
						|
         // Use ShortString to store empty string.
 | 
						|
@@ -608,10 +735,40 @@ public:
 | 
						|
         \tparam SourceAllocator allocator of \c rhs
 | 
						|
         \param rhs Value to copy from (read-only)
 | 
						|
         \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
 | 
						|
+        \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
 | 
						|
         \see CopyFrom()
 | 
						|
     */
 | 
						|
-    template< typename SourceAllocator >
 | 
						|
-    GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
 | 
						|
+    template <typename SourceAllocator>
 | 
						|
+    GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
 | 
						|
+        switch (rhs.GetType()) {
 | 
						|
+        case kObjectType:
 | 
						|
+            DoCopyMembers(rhs, allocator, copyConstStrings);
 | 
						|
+            break;
 | 
						|
+        case kArrayType: {
 | 
						|
+                SizeType count = rhs.data_.a.size;
 | 
						|
+                GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
 | 
						|
+                const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();
 | 
						|
+                for (SizeType i = 0; i < count; i++)
 | 
						|
+                    new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);
 | 
						|
+                data_.f.flags = kArrayFlag;
 | 
						|
+                data_.a.size = data_.a.capacity = count;
 | 
						|
+                SetElementsPointer(le);
 | 
						|
+            }
 | 
						|
+            break;
 | 
						|
+        case kStringType:
 | 
						|
+            if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
 | 
						|
+                data_.f.flags = rhs.data_.f.flags;
 | 
						|
+                data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 | 
						|
+            }
 | 
						|
+            else
 | 
						|
+                SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
 | 
						|
+            break;
 | 
						|
+        default:
 | 
						|
+            data_.f.flags = rhs.data_.f.flags;
 | 
						|
+            data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 | 
						|
+            break;
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
 
 | 
						|
     //! Constructor for boolean value.
 | 
						|
     /*! \param b Boolean value
 | 
						|
@@ -673,6 +830,9 @@ public:
 | 
						|
     //! Constructor for double value.
 | 
						|
     explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
 | 
						|
 
 | 
						|
+    //! Constructor for float value.
 | 
						|
+    explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
 | 
						|
+
 | 
						|
     //! Constructor for constant string (i.e. do not make a copy of string)
 | 
						|
     GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
 | 
						|
 
 | 
						|
@@ -718,25 +878,30 @@ public:
 | 
						|
     /*! Need to destruct elements of array, members of object, or copy-string.
 | 
						|
     */
 | 
						|
     ~GenericValue() {
 | 
						|
-        if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
 | 
						|
+        // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release
 | 
						|
+        // their Allocator if it's refcounted (e.g. MemoryPoolAllocator).
 | 
						|
+        if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 &&
 | 
						|
+                                     internal::IsRefCounted<Allocator>::Value)) {
 | 
						|
             switch(data_.f.flags) {
 | 
						|
             case kArrayFlag:
 | 
						|
                 {
 | 
						|
                     GenericValue* e = GetElementsPointer();
 | 
						|
                     for (GenericValue* v = e; v != e + data_.a.size; ++v)
 | 
						|
                         v->~GenericValue();
 | 
						|
-                    Allocator::Free(e);
 | 
						|
+                    if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
 | 
						|
+                        Allocator::Free(e);
 | 
						|
+                    }
 | 
						|
                 }
 | 
						|
                 break;
 | 
						|
 
 | 
						|
             case kObjectFlag:
 | 
						|
-                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 | 
						|
-                    m->~Member();
 | 
						|
-                Allocator::Free(GetMembersPointer());
 | 
						|
+                DoFreeMembers();
 | 
						|
                 break;
 | 
						|
 
 | 
						|
             case kCopyStringFlag:
 | 
						|
-                Allocator::Free(const_cast<Ch*>(GetStringPointer()));
 | 
						|
+                if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
 | 
						|
+                    Allocator::Free(const_cast<Ch*>(GetStringPointer()));
 | 
						|
+                }
 | 
						|
                 break;
 | 
						|
 
 | 
						|
             default:
 | 
						|
@@ -754,9 +919,15 @@ public:
 | 
						|
     /*! \param rhs Source of the assignment. It will become a null value after assignment.
 | 
						|
     */
 | 
						|
     GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
 | 
						|
-        RAPIDJSON_ASSERT(this != &rhs);
 | 
						|
-        this->~GenericValue();
 | 
						|
-        RawAssign(rhs);
 | 
						|
+        if (RAPIDJSON_LIKELY(this != &rhs)) {
 | 
						|
+            // Can't destroy "this" before assigning "rhs", otherwise "rhs"
 | 
						|
+            // could be used after free if it's an sub-Value of "this",
 | 
						|
+            // hence the temporary danse.
 | 
						|
+            GenericValue temp;
 | 
						|
+            temp.RawAssign(rhs);
 | 
						|
+            this->~GenericValue();
 | 
						|
+            RawAssign(temp);
 | 
						|
+        }
 | 
						|
         return *this;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -801,12 +972,13 @@ public:
 | 
						|
         \tparam SourceAllocator Allocator type of \c rhs
 | 
						|
         \param rhs Value to copy from (read-only)
 | 
						|
         \param allocator Allocator to use for copying
 | 
						|
+        \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
 | 
						|
      */
 | 
						|
     template <typename SourceAllocator>
 | 
						|
-    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
 | 
						|
+    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
 | 
						|
         RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
 | 
						|
         this->~GenericValue();
 | 
						|
-        new (this) GenericValue(rhs, allocator);
 | 
						|
+        new (this) GenericValue(rhs, allocator, copyConstStrings);
 | 
						|
         return *this;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -847,7 +1019,7 @@ public:
 | 
						|
     //! Equal-to operator
 | 
						|
     /*!
 | 
						|
         \note If an object contains duplicated named member, comparing equality with any object is always \c false.
 | 
						|
-        \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
 | 
						|
+        \note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings).
 | 
						|
     */
 | 
						|
     template <typename SourceAllocator>
 | 
						|
     bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
 | 
						|
@@ -906,6 +1078,7 @@ public:
 | 
						|
     */
 | 
						|
     template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
 | 
						|
 
 | 
						|
+#ifndef __cpp_impl_three_way_comparison
 | 
						|
     //! Not-equal-to operator
 | 
						|
     /*! \return !(*this == rhs)
 | 
						|
      */
 | 
						|
@@ -930,6 +1103,7 @@ public:
 | 
						|
      */
 | 
						|
     template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
 | 
						|
     //@}
 | 
						|
+#endif
 | 
						|
 
 | 
						|
     //!@name Type
 | 
						|
     //@{
 | 
						|
@@ -956,14 +1130,14 @@ public:
 | 
						|
             uint64_t u = GetUint64();
 | 
						|
             volatile double d = static_cast<double>(u);
 | 
						|
             return (d >= 0.0)
 | 
						|
-                && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
 | 
						|
+                && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))
 | 
						|
                 && (u == static_cast<uint64_t>(d));
 | 
						|
         }
 | 
						|
         if (IsInt64()) {
 | 
						|
             int64_t i = GetInt64();
 | 
						|
             volatile double d = static_cast<double>(i);
 | 
						|
-            return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
 | 
						|
-                && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
 | 
						|
+            return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
 | 
						|
+                && (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
 | 
						|
                 && (i == static_cast<int64_t>(d));
 | 
						|
         }
 | 
						|
         return true; // double, int, uint are always lossless
 | 
						|
@@ -980,8 +1154,8 @@ public:
 | 
						|
     bool IsLosslessFloat() const {
 | 
						|
         if (!IsNumber()) return false;
 | 
						|
         double a = GetDouble();
 | 
						|
-        if (a < static_cast<double>(-std::numeric_limits<float>::max())
 | 
						|
-                || a > static_cast<double>(std::numeric_limits<float>::max()))
 | 
						|
+        if (a < static_cast<double>(-(std::numeric_limits<float>::max)())
 | 
						|
+                || a > static_cast<double>((std::numeric_limits<float>::max)()))
 | 
						|
             return false;
 | 
						|
         double b = static_cast<double>(static_cast<float>(a));
 | 
						|
         return a >= b && a <= b;    // Prevent -Wfloat-equal
 | 
						|
@@ -1016,6 +1190,9 @@ public:
 | 
						|
     //! Get the number of members in the object.
 | 
						|
     SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
 | 
						|
 
 | 
						|
+    //! Get the capacity of object.
 | 
						|
+    SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }
 | 
						|
+
 | 
						|
     //! Check whether the object is empty.
 | 
						|
     bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
 | 
						|
 
 | 
						|
@@ -1053,13 +1230,28 @@ public:
 | 
						|
         else {
 | 
						|
             RAPIDJSON_ASSERT(false);    // see above note
 | 
						|
 
 | 
						|
-            // This will generate -Wexit-time-destructors in clang
 | 
						|
-            // static GenericValue NullValue;
 | 
						|
-            // return NullValue;
 | 
						|
-
 | 
						|
-            // Use static buffer and placement-new to prevent destruction
 | 
						|
-            static char buffer[sizeof(GenericValue)];
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+            // Use thread-local storage to prevent races between threads.
 | 
						|
+            // Use static buffer and placement-new to prevent destruction, with
 | 
						|
+            // alignas() to ensure proper alignment.
 | 
						|
+            alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
 | 
						|
+            return *new (buffer) GenericValue();
 | 
						|
+#elif defined(_MSC_VER) && _MSC_VER < 1900
 | 
						|
+            // There's no way to solve both thread locality and proper alignment
 | 
						|
+            // simultaneously.
 | 
						|
+            __declspec(thread) static char buffer[sizeof(GenericValue)];
 | 
						|
             return *new (buffer) GenericValue();
 | 
						|
+#elif defined(__GNUC__) || defined(__clang__)
 | 
						|
+            // This will generate -Wexit-time-destructors in clang, but that's
 | 
						|
+            // better than having under-alignment.
 | 
						|
+            __thread static GenericValue buffer;
 | 
						|
+            return buffer;
 | 
						|
+#else
 | 
						|
+            // Don't know what compiler this is, so don't know how to ensure
 | 
						|
+            // thread-locality.
 | 
						|
+            static GenericValue buffer;
 | 
						|
+            return buffer;
 | 
						|
+#endif
 | 
						|
         }
 | 
						|
     }
 | 
						|
     template <typename SourceAllocator>
 | 
						|
@@ -1084,6 +1276,18 @@ public:
 | 
						|
     /*! \pre IsObject() == true */
 | 
						|
     MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
 | 
						|
 
 | 
						|
+    //! Request the object to have enough capacity to store members.
 | 
						|
+    /*! \param newCapacity  The capacity that the object at least need to have.
 | 
						|
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 | 
						|
+        \return The value itself for fluent API.
 | 
						|
+        \note Linear time complexity.
 | 
						|
+    */
 | 
						|
+    GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
 | 
						|
+        RAPIDJSON_ASSERT(IsObject());
 | 
						|
+        DoReserveMembers(newCapacity, allocator);
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     //! Check whether a member exists in the object.
 | 
						|
     /*!
 | 
						|
         \param name Member name to be searched.
 | 
						|
@@ -1154,11 +1358,7 @@ public:
 | 
						|
     MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 | 
						|
         RAPIDJSON_ASSERT(IsObject());
 | 
						|
         RAPIDJSON_ASSERT(name.IsString());
 | 
						|
-        MemberIterator member = MemberBegin();
 | 
						|
-        for ( ; member != MemberEnd(); ++member)
 | 
						|
-            if (name.StringEqual(member->name))
 | 
						|
-                break;
 | 
						|
-        return member;
 | 
						|
+        return DoFindMember(name);
 | 
						|
     }
 | 
						|
     template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
 | 
						|
 
 | 
						|
@@ -1187,23 +1387,7 @@ public:
 | 
						|
     GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
 | 
						|
         RAPIDJSON_ASSERT(IsObject());
 | 
						|
         RAPIDJSON_ASSERT(name.IsString());
 | 
						|
-
 | 
						|
-        ObjectData& o = data_.o;
 | 
						|
-        if (o.size >= o.capacity) {
 | 
						|
-            if (o.capacity == 0) {
 | 
						|
-                o.capacity = kDefaultObjectCapacity;
 | 
						|
-                SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
 | 
						|
-            }
 | 
						|
-            else {
 | 
						|
-                SizeType oldCapacity = o.capacity;
 | 
						|
-                o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
 | 
						|
-                SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
 | 
						|
-            }
 | 
						|
-        }
 | 
						|
-        Member* members = GetMembersPointer();
 | 
						|
-        members[o.size].name.RawAssign(name);
 | 
						|
-        members[o.size].value.RawAssign(value);
 | 
						|
-        o.size++;
 | 
						|
+        DoAddMember(name, value, allocator);
 | 
						|
         return *this;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -1337,9 +1521,7 @@ public:
 | 
						|
     */
 | 
						|
     void RemoveAllMembers() {
 | 
						|
         RAPIDJSON_ASSERT(IsObject()); 
 | 
						|
-        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 | 
						|
-            m->~Member();
 | 
						|
-        data_.o.size = 0;
 | 
						|
+        DoClearMembers();
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Remove a member in object by its name.
 | 
						|
@@ -1383,14 +1565,7 @@ public:
 | 
						|
         RAPIDJSON_ASSERT(data_.o.size > 0);
 | 
						|
         RAPIDJSON_ASSERT(GetMembersPointer() != 0);
 | 
						|
         RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
 | 
						|
-
 | 
						|
-        MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
 | 
						|
-        if (data_.o.size > 1 && m != last)
 | 
						|
-            *m = *last; // Move the last one to this place
 | 
						|
-        else
 | 
						|
-            m->~Member(); // Only one left, just destroy
 | 
						|
-        --data_.o.size;
 | 
						|
-        return m;
 | 
						|
+        return DoRemoveMember(m);
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Remove a member from an object by iterator.
 | 
						|
@@ -1422,13 +1597,7 @@ public:
 | 
						|
         RAPIDJSON_ASSERT(first >= MemberBegin());
 | 
						|
         RAPIDJSON_ASSERT(first <= last);
 | 
						|
         RAPIDJSON_ASSERT(last <= MemberEnd());
 | 
						|
-
 | 
						|
-        MemberIterator pos = MemberBegin() + (first - MemberBegin());
 | 
						|
-        for (MemberIterator itr = pos; itr != last; ++itr)
 | 
						|
-            itr->~Member();
 | 
						|
-        std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
 | 
						|
-        data_.o.size -= static_cast<SizeType>(last - first);
 | 
						|
-        return pos;
 | 
						|
+        return DoEraseMembers(first, last);
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Erase a member in object by its name.
 | 
						|
@@ -1457,7 +1626,9 @@ public:
 | 
						|
     }
 | 
						|
 
 | 
						|
     Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
 | 
						|
+    Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
 | 
						|
     ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
 | 
						|
+    ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
 | 
						|
 
 | 
						|
     //@}
 | 
						|
 
 | 
						|
@@ -1629,8 +1800,8 @@ public:
 | 
						|
         RAPIDJSON_ASSERT(last <= End());
 | 
						|
         ValueIterator pos = Begin() + (first - Begin());
 | 
						|
         for (ValueIterator itr = pos; itr != last; ++itr)
 | 
						|
-            itr->~GenericValue();       
 | 
						|
-        std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
 | 
						|
+            itr->~GenericValue();
 | 
						|
+        std::memmove(static_cast<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
 | 
						|
         data_.a.size -= static_cast<SizeType>(last - first);
 | 
						|
         return pos;
 | 
						|
     }
 | 
						|
@@ -1672,19 +1843,19 @@ public:
 | 
						|
     GenericValue& SetInt64(int64_t i64)     { this->~GenericValue(); new (this) GenericValue(i64);  return *this; }
 | 
						|
     GenericValue& SetUint64(uint64_t u64)   { this->~GenericValue(); new (this) GenericValue(u64);  return *this; }
 | 
						|
     GenericValue& SetDouble(double d)       { this->~GenericValue(); new (this) GenericValue(d);    return *this; }
 | 
						|
-    GenericValue& SetFloat(float f)         { this->~GenericValue(); new (this) GenericValue(f);    return *this; }
 | 
						|
+    GenericValue& SetFloat(float f)         { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
 | 
						|
 
 | 
						|
     //@}
 | 
						|
 
 | 
						|
     //!@name String
 | 
						|
     //@{
 | 
						|
 
 | 
						|
-    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
 | 
						|
+    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
 | 
						|
 
 | 
						|
     //! Get the length of string.
 | 
						|
     /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
 | 
						|
     */
 | 
						|
-    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
 | 
						|
+    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
 | 
						|
 
 | 
						|
     //! Set this value as a string without copying source string.
 | 
						|
     /*! This version has better performance with supplied length, and also support string containing null character.
 | 
						|
@@ -1711,7 +1882,7 @@ public:
 | 
						|
         \return The value itself for fluent API.
 | 
						|
         \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 | 
						|
     */
 | 
						|
-    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
 | 
						|
+    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }
 | 
						|
 
 | 
						|
     //! Set this value as a string by copying from source string.
 | 
						|
     /*! \param s source string. 
 | 
						|
@@ -1719,7 +1890,15 @@ public:
 | 
						|
         \return The value itself for fluent API.
 | 
						|
         \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 | 
						|
     */
 | 
						|
-    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
 | 
						|
+    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
 | 
						|
+
 | 
						|
+    //! Set this value as a string by copying from source string.
 | 
						|
+    /*! \param s source string reference
 | 
						|
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
 | 
						|
+        \return The value itself for fluent API.
 | 
						|
+        \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 | 
						|
+    */
 | 
						|
+    GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
 | 
						|
 
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
     //! Set this value as a string by copying from source string.
 | 
						|
@@ -1729,7 +1908,7 @@ public:
 | 
						|
         \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
 | 
						|
         \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
 | 
						|
     */
 | 
						|
-    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
 | 
						|
+    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
 | 
						|
 #endif
 | 
						|
 
 | 
						|
     //@}
 | 
						|
@@ -1787,7 +1966,7 @@ public:
 | 
						|
         case kArrayType:
 | 
						|
             if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
 | 
						|
                 return false;
 | 
						|
-            for (const GenericValue* v = Begin(); v != End(); ++v)
 | 
						|
+            for (ConstValueIterator v = Begin(); v != End(); ++v)
 | 
						|
                 if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
 | 
						|
                     return false;
 | 
						|
             return handler.EndArray(data_.a.size);
 | 
						|
@@ -1823,25 +2002,26 @@ private:
 | 
						|
 
 | 
						|
         // Initial flags of different types.
 | 
						|
         kNullFlag = kNullType,
 | 
						|
-        kTrueFlag = kTrueType | kBoolFlag,
 | 
						|
-        kFalseFlag = kFalseType | kBoolFlag,
 | 
						|
-        kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
 | 
						|
-        kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
 | 
						|
-        kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
 | 
						|
-        kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
 | 
						|
-        kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
 | 
						|
-        kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
 | 
						|
-        kConstStringFlag = kStringType | kStringFlag,
 | 
						|
-        kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
 | 
						|
-        kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
 | 
						|
+        // These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types.
 | 
						|
+        kTrueFlag = static_cast<int>(kTrueType) | static_cast<int>(kBoolFlag),
 | 
						|
+        kFalseFlag = static_cast<int>(kFalseType) | static_cast<int>(kBoolFlag),
 | 
						|
+        kNumberIntFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag),
 | 
						|
+        kNumberUintFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag),
 | 
						|
+        kNumberInt64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kInt64Flag),
 | 
						|
+        kNumberUint64Flag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kUint64Flag),
 | 
						|
+        kNumberDoubleFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kDoubleFlag),
 | 
						|
+        kNumberAnyFlag = static_cast<int>(kNumberType) | static_cast<int>(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag),
 | 
						|
+        kConstStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag),
 | 
						|
+        kCopyStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag | kCopyFlag),
 | 
						|
+        kShortStringFlag = static_cast<int>(kStringType) | static_cast<int>(kStringFlag | kCopyFlag | kInlineStrFlag),
 | 
						|
         kObjectFlag = kObjectType,
 | 
						|
         kArrayFlag = kArrayType,
 | 
						|
 
 | 
						|
         kTypeMask = 0x07
 | 
						|
     };
 | 
						|
 
 | 
						|
-    static const SizeType kDefaultArrayCapacity = 16;
 | 
						|
-    static const SizeType kDefaultObjectCapacity = 16;
 | 
						|
+    static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY;
 | 
						|
+    static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY;
 | 
						|
 
 | 
						|
     struct Flag {
 | 
						|
 #if RAPIDJSON_48BITPOINTER_OPTIMIZATION
 | 
						|
@@ -1924,6 +2104,13 @@ private:
 | 
						|
         Flag f;
 | 
						|
     };  // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
 | 
						|
 
 | 
						|
+    static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) {
 | 
						|
+        return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str);
 | 
						|
+    }
 | 
						|
+    static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) {
 | 
						|
+        return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
 | 
						|
     RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
 | 
						|
     RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
 | 
						|
@@ -1931,13 +2118,293 @@ private:
 | 
						|
     RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
 | 
						|
     RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
 | 
						|
 
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+
 | 
						|
+    struct MapTraits {
 | 
						|
+        struct Less {
 | 
						|
+            bool operator()(const Data& s1, const Data& s2) const {
 | 
						|
+                SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2);
 | 
						|
+                int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2));
 | 
						|
+                return cmp < 0 || (cmp == 0 && n1 < n2);
 | 
						|
+            }
 | 
						|
+        };
 | 
						|
+        typedef std::pair<const Data, SizeType> Pair;
 | 
						|
+        typedef std::multimap<Data, SizeType, Less, StdAllocator<Pair, Allocator> > Map;
 | 
						|
+        typedef typename Map::iterator Iterator;
 | 
						|
+    };
 | 
						|
+    typedef typename MapTraits::Map         Map;
 | 
						|
+    typedef typename MapTraits::Less        MapLess;
 | 
						|
+    typedef typename MapTraits::Pair        MapPair;
 | 
						|
+    typedef typename MapTraits::Iterator    MapIterator;
 | 
						|
+
 | 
						|
+    //
 | 
						|
+    // Layout of the members' map/array, re(al)located according to the needed capacity:
 | 
						|
+    //
 | 
						|
+    //    {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]}
 | 
						|
+    //
 | 
						|
+    // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed)
 | 
						|
+    //
 | 
						|
+
 | 
						|
+    static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) {
 | 
						|
+        return RAPIDJSON_ALIGN(sizeof(Map*)) +
 | 
						|
+               RAPIDJSON_ALIGN(sizeof(SizeType)) +
 | 
						|
+               RAPIDJSON_ALIGN(capacity * sizeof(Member)) +
 | 
						|
+               capacity * sizeof(MapIterator);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) {
 | 
						|
+        return *reinterpret_cast<SizeType*>(reinterpret_cast<uintptr_t>(&map) +
 | 
						|
+                                            RAPIDJSON_ALIGN(sizeof(Map*)));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) {
 | 
						|
+        return reinterpret_cast<Member*>(reinterpret_cast<uintptr_t>(&map) +
 | 
						|
+                                         RAPIDJSON_ALIGN(sizeof(Map*)) +
 | 
						|
+                                         RAPIDJSON_ALIGN(sizeof(SizeType)));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) {
 | 
						|
+        return reinterpret_cast<MapIterator*>(reinterpret_cast<uintptr_t>(&map) +
 | 
						|
+                                              RAPIDJSON_ALIGN(sizeof(Map*)) +
 | 
						|
+                                              RAPIDJSON_ALIGN(sizeof(SizeType)) +
 | 
						|
+                                              RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member)));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) {
 | 
						|
+        RAPIDJSON_ASSERT(members != 0);
 | 
						|
+        return *reinterpret_cast<Map**>(reinterpret_cast<uintptr_t>(members) -
 | 
						|
+                                        RAPIDJSON_ALIGN(sizeof(SizeType)) -
 | 
						|
+                                        RAPIDJSON_ALIGN(sizeof(Map*)));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting..
 | 
						|
+    RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) {
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+        MapIterator ret = std::move(rhs);
 | 
						|
+#else
 | 
						|
+        MapIterator ret = rhs;
 | 
						|
+#endif
 | 
						|
+        rhs.~MapIterator();
 | 
						|
+        return ret;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) {
 | 
						|
+        Map **newMap = static_cast<Map**>(allocator.Malloc(GetMapLayoutSize(newCapacity)));
 | 
						|
+        GetMapCapacity(*newMap) = newCapacity;
 | 
						|
+        if (!oldMap) {
 | 
						|
+            *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator);
 | 
						|
+        }
 | 
						|
+        else {
 | 
						|
+            *newMap = *oldMap;
 | 
						|
+            size_t count = (*oldMap)->size();
 | 
						|
+            std::memcpy(static_cast<void*>(GetMapMembers(*newMap)),
 | 
						|
+                        static_cast<void*>(GetMapMembers(*oldMap)),
 | 
						|
+                        count * sizeof(Member));
 | 
						|
+            MapIterator *oldIt = GetMapIterators(*oldMap),
 | 
						|
+                        *newIt = GetMapIterators(*newMap);
 | 
						|
+            while (count--) {
 | 
						|
+                new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count]));
 | 
						|
+            }
 | 
						|
+            Allocator::Free(oldMap);
 | 
						|
+        }
 | 
						|
+        return *newMap;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
 | 
						|
+        return GetMapMembers(DoReallocMap(0, capacity, allocator));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
 | 
						|
+        ObjectData& o = data_.o;
 | 
						|
+        if (newCapacity > o.capacity) {
 | 
						|
+            Member* oldMembers = GetMembersPointer();
 | 
						|
+            Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0,
 | 
						|
+                *&newMap = DoReallocMap(oldMap, newCapacity, allocator);
 | 
						|
+            RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap));
 | 
						|
+            o.capacity = newCapacity;
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    template <typename SourceAllocator>
 | 
						|
+    MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 | 
						|
+        if (Member* members = GetMembersPointer()) {
 | 
						|
+            Map* &map = GetMap(members);
 | 
						|
+            MapIterator mit = map->find(reinterpret_cast<const Data&>(name.data_));
 | 
						|
+            if (mit != map->end()) {
 | 
						|
+                return MemberIterator(&members[mit->second]);
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        return MemberEnd();
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoClearMembers() {
 | 
						|
+        if (Member* members = GetMembersPointer()) {
 | 
						|
+            Map* &map = GetMap(members);
 | 
						|
+            MapIterator* mit = GetMapIterators(map);
 | 
						|
+            for (SizeType i = 0; i < data_.o.size; i++) {
 | 
						|
+                map->erase(DropMapIterator(mit[i]));
 | 
						|
+                members[i].~Member();
 | 
						|
+            }
 | 
						|
+            data_.o.size = 0;
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoFreeMembers() {
 | 
						|
+        if (Member* members = GetMembersPointer()) {
 | 
						|
+            GetMap(members)->~Map();
 | 
						|
+            for (SizeType i = 0; i < data_.o.size; i++) {
 | 
						|
+                members[i].~Member();
 | 
						|
+            }
 | 
						|
+            if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
 | 
						|
+                Map** map = &GetMap(members);
 | 
						|
+                Allocator::Free(*map);
 | 
						|
+                Allocator::Free(map);
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#else // !RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+
 | 
						|
+    RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
 | 
						|
+        return Malloc<Member>(allocator, capacity);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
 | 
						|
+        ObjectData& o = data_.o;
 | 
						|
+        if (newCapacity > o.capacity) {
 | 
						|
+            Member* newMembers = Realloc<Member>(allocator, GetMembersPointer(), o.capacity, newCapacity);
 | 
						|
+            RAPIDJSON_SETPOINTER(Member, o.members, newMembers);
 | 
						|
+            o.capacity = newCapacity;
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    template <typename SourceAllocator>
 | 
						|
+    MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 | 
						|
+        MemberIterator member = MemberBegin();
 | 
						|
+        for ( ; member != MemberEnd(); ++member)
 | 
						|
+            if (name.StringEqual(member->name))
 | 
						|
+                break;
 | 
						|
+        return member;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoClearMembers() {
 | 
						|
+        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 | 
						|
+            m->~Member();
 | 
						|
+        data_.o.size = 0;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DoFreeMembers() {
 | 
						|
+        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 | 
						|
+            m->~Member();
 | 
						|
+        Allocator::Free(GetMembersPointer());
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#endif // !RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+
 | 
						|
+    void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
 | 
						|
+        ObjectData& o = data_.o;
 | 
						|
+        if (o.size >= o.capacity)
 | 
						|
+            DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator);
 | 
						|
+        Member* members = GetMembersPointer();
 | 
						|
+        Member* m = members + o.size;
 | 
						|
+        m->name.RawAssign(name);
 | 
						|
+        m->value.RawAssign(value);
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+        Map* &map = GetMap(members);
 | 
						|
+        MapIterator* mit = GetMapIterators(map);
 | 
						|
+        new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size)));
 | 
						|
+#endif
 | 
						|
+        ++o.size;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    MemberIterator DoRemoveMember(MemberIterator m) {
 | 
						|
+        ObjectData& o = data_.o;
 | 
						|
+        Member* members = GetMembersPointer();
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+        Map* &map = GetMap(members);
 | 
						|
+        MapIterator* mit = GetMapIterators(map);
 | 
						|
+        SizeType mpos = static_cast<SizeType>(&*m - members);
 | 
						|
+        map->erase(DropMapIterator(mit[mpos]));
 | 
						|
+#endif
 | 
						|
+        MemberIterator last(members + (o.size - 1));
 | 
						|
+        if (o.size > 1 && m != last) {
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+            new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members]));
 | 
						|
+            mit[mpos]->second = mpos;
 | 
						|
+#endif
 | 
						|
+            *m = *last; // Move the last one to this place
 | 
						|
+        }
 | 
						|
+        else {
 | 
						|
+            m->~Member(); // Only one left, just destroy
 | 
						|
+        }
 | 
						|
+        --o.size;
 | 
						|
+        return m;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) {
 | 
						|
+        ObjectData& o = data_.o;
 | 
						|
+        MemberIterator beg = MemberBegin(),
 | 
						|
+                       pos = beg + (first - beg),
 | 
						|
+                       end = MemberEnd();
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+        Map* &map = GetMap(GetMembersPointer());
 | 
						|
+        MapIterator* mit = GetMapIterators(map);
 | 
						|
+#endif
 | 
						|
+        for (MemberIterator itr = pos; itr != last; ++itr) {
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+            map->erase(DropMapIterator(mit[itr - beg]));
 | 
						|
+#endif
 | 
						|
+            itr->~Member();
 | 
						|
+        }
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+        if (first != last) {
 | 
						|
+            // Move remaining members/iterators
 | 
						|
+            MemberIterator next = pos + (last - first);
 | 
						|
+            for (MemberIterator itr = pos; next != end; ++itr, ++next) {
 | 
						|
+                std::memcpy(static_cast<void*>(&*itr), &*next, sizeof(Member));
 | 
						|
+                SizeType mpos = static_cast<SizeType>(itr - beg);
 | 
						|
+                new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg]));
 | 
						|
+                mit[mpos]->second = mpos;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+#else
 | 
						|
+        std::memmove(static_cast<void*>(&*pos), &*last,
 | 
						|
+                     static_cast<size_t>(end - last) * sizeof(Member));
 | 
						|
+#endif
 | 
						|
+        o.size -= static_cast<SizeType>(last - first);
 | 
						|
+        return pos;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    template <typename SourceAllocator>
 | 
						|
+    void DoCopyMembers(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings) {
 | 
						|
+        RAPIDJSON_ASSERT(rhs.GetType() == kObjectType);
 | 
						|
+
 | 
						|
+        data_.f.flags = kObjectFlag;
 | 
						|
+        SizeType count = rhs.data_.o.size;
 | 
						|
+        Member* lm = DoAllocMembers(count, allocator);
 | 
						|
+        const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+        Map* &map = GetMap(lm);
 | 
						|
+        MapIterator* mit = GetMapIterators(map);
 | 
						|
+#endif
 | 
						|
+        for (SizeType i = 0; i < count; i++) {
 | 
						|
+            new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
 | 
						|
+            new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+            new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i)));
 | 
						|
+#endif
 | 
						|
+        }
 | 
						|
+        data_.o.size = data_.o.capacity = count;
 | 
						|
+        SetMembersPointer(lm);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     // Initialize this value as array with initial data, without calling destructor.
 | 
						|
     void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
 | 
						|
         data_.f.flags = kArrayFlag;
 | 
						|
         if (count) {
 | 
						|
             GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
 | 
						|
             SetElementsPointer(e);
 | 
						|
-            std::memcpy((void*)e, (void*)values, count * sizeof(GenericValue));
 | 
						|
+            std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue));
 | 
						|
         }
 | 
						|
         else
 | 
						|
             SetElementsPointer(0);
 | 
						|
@@ -1948,9 +2415,16 @@ private:
 | 
						|
     void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
 | 
						|
         data_.f.flags = kObjectFlag;
 | 
						|
         if (count) {
 | 
						|
-            Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
 | 
						|
+            Member* m = DoAllocMembers(count, allocator);
 | 
						|
             SetMembersPointer(m);
 | 
						|
-            std::memcpy((void*)m, (void*)members, count * sizeof(Member));
 | 
						|
+            std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
 | 
						|
+#if RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+            Map* &map = GetMap(m);
 | 
						|
+            MapIterator* mit = GetMapIterators(map);
 | 
						|
+            for (SizeType i = 0; i < count; i++) {
 | 
						|
+                new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i)));
 | 
						|
+            }
 | 
						|
+#endif
 | 
						|
         }
 | 
						|
         else
 | 
						|
             SetMembersPointer(0);
 | 
						|
@@ -2021,12 +2495,13 @@ typedef GenericValue<UTF8<> > Value;
 | 
						|
     \tparam StackAllocator Allocator for allocating memory for stack during parsing.
 | 
						|
     \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor.  To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
 | 
						|
 */
 | 
						|
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
 | 
						|
+template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR, typename StackAllocator = RAPIDJSON_DEFAULT_STACK_ALLOCATOR >
 | 
						|
 class GenericDocument : public GenericValue<Encoding, Allocator> {
 | 
						|
 public:
 | 
						|
     typedef typename Encoding::Ch Ch;                       //!< Character type derived from Encoding.
 | 
						|
     typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of the document.
 | 
						|
     typedef Allocator AllocatorType;                        //!< Allocator type from template parameter.
 | 
						|
+    typedef StackAllocator StackAllocatorType;              //!< StackAllocator type from template parameter.
 | 
						|
 
 | 
						|
     //! Constructor
 | 
						|
     /*! Creates an empty document of specified type.
 | 
						|
@@ -2039,7 +2514,7 @@ public:
 | 
						|
         GenericValue<Encoding, Allocator>(type),  allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
 | 
						|
     {
 | 
						|
         if (!allocator_)
 | 
						|
-            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Constructor
 | 
						|
@@ -2052,7 +2527,7 @@ public:
 | 
						|
         allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
 | 
						|
     {
 | 
						|
         if (!allocator_)
 | 
						|
-            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
     }
 | 
						|
 
 | 
						|
 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
@@ -2071,6 +2546,13 @@ public:
 | 
						|
 #endif
 | 
						|
 
 | 
						|
     ~GenericDocument() {
 | 
						|
+        // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType()
 | 
						|
+        // runs last and may access its elements or members which would be freed
 | 
						|
+        // with an allocator like MemoryPoolAllocator (CrtAllocator does not
 | 
						|
+        // free its data when destroyed, but MemoryPoolAllocator does).
 | 
						|
+        if (ownAllocator_) {
 | 
						|
+            ValueType::SetNull();
 | 
						|
+        }
 | 
						|
         Destroy();
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -2113,6 +2595,10 @@ public:
 | 
						|
         return *this;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    // Allow Swap with ValueType.
 | 
						|
+    // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.
 | 
						|
+    using ValueType::Swap;
 | 
						|
+
 | 
						|
     //! free-standing swap function helper
 | 
						|
     /*!
 | 
						|
         Helper function to enable support for common swap implementation pattern based on \c std::swap:
 | 
						|
@@ -2244,7 +2730,7 @@ public:
 | 
						|
     template <unsigned parseFlags, typename SourceEncoding>
 | 
						|
     GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
 | 
						|
         RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
 | 
						|
-        MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
 | 
						|
+        MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
 | 
						|
         EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
 | 
						|
         ParseStream<parseFlags, SourceEncoding>(is);
 | 
						|
         return *this;
 | 
						|
@@ -2281,7 +2767,7 @@ public:
 | 
						|
     //!@name Handling parse errors
 | 
						|
     //!@{
 | 
						|
 
 | 
						|
-    //! Whether a parse error has occured in the last parsing.
 | 
						|
+    //! Whether a parse error has occurred in the last parsing.
 | 
						|
     bool HasParseError() const { return parseResult_.IsError(); }
 | 
						|
 
 | 
						|
     //! Get the \ref ParseErrorCode of last parsing.
 | 
						|
@@ -2402,34 +2888,6 @@ private:
 | 
						|
 //! GenericDocument with UTF8 encoding
 | 
						|
 typedef GenericDocument<UTF8<> > Document;
 | 
						|
 
 | 
						|
-// defined here due to the dependency on GenericDocument
 | 
						|
-template <typename Encoding, typename Allocator>
 | 
						|
-template <typename SourceAllocator>
 | 
						|
-inline
 | 
						|
-GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
 | 
						|
-{
 | 
						|
-    switch (rhs.GetType()) {
 | 
						|
-    case kObjectType:
 | 
						|
-    case kArrayType: { // perform deep copy via SAX Handler
 | 
						|
-            GenericDocument<Encoding,Allocator> d(&allocator);
 | 
						|
-            rhs.Accept(d);
 | 
						|
-            RawAssign(*d.stack_.template Pop<GenericValue>(1));
 | 
						|
-        }
 | 
						|
-        break;
 | 
						|
-    case kStringType:
 | 
						|
-        if (rhs.data_.f.flags == kConstStringFlag) {
 | 
						|
-            data_.f.flags = rhs.data_.f.flags;
 | 
						|
-            data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 | 
						|
-        } else {
 | 
						|
-            SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
 | 
						|
-        }
 | 
						|
-        break;
 | 
						|
-    default:
 | 
						|
-        data_.f.flags = rhs.data_.f.flags;
 | 
						|
-        data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 | 
						|
-        break;
 | 
						|
-    }
 | 
						|
-}
 | 
						|
 
 | 
						|
 //! Helper class for accessing Value of array type.
 | 
						|
 /*!
 | 
						|
@@ -2455,6 +2913,7 @@ public:
 | 
						|
     GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
 | 
						|
     ~GenericArray() {}
 | 
						|
 
 | 
						|
+    operator ValueType&() const { return value_; }
 | 
						|
     SizeType Size() const { return value_.Size(); }
 | 
						|
     SizeType Capacity() const { return value_.Capacity(); }
 | 
						|
     bool Empty() const { return value_.Empty(); }
 | 
						|
@@ -2510,7 +2969,9 @@ public:
 | 
						|
     GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
 | 
						|
     ~GenericObject() {}
 | 
						|
 
 | 
						|
+    operator ValueType&() const { return value_; }
 | 
						|
     SizeType MemberCount() const { return value_.MemberCount(); }
 | 
						|
+    SizeType MemberCapacity() const { return value_.MemberCapacity(); }
 | 
						|
     bool ObjectEmpty() const { return value_.ObjectEmpty(); }
 | 
						|
     template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
 | 
						|
     template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
 | 
						|
@@ -2519,6 +2980,7 @@ public:
 | 
						|
 #endif
 | 
						|
     MemberIterator MemberBegin() const { return value_.MemberBegin(); }
 | 
						|
     MemberIterator MemberEnd() const { return value_.MemberEnd(); }
 | 
						|
+    GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }
 | 
						|
     bool HasMember(const Ch* name) const { return value_.HasMember(name); }
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
     bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
 | 
						|
@@ -2544,7 +3006,7 @@ public:
 | 
						|
     GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 | 
						|
     GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 | 
						|
     template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 | 
						|
-    void RemoveAllMembers() { return value_.RemoveAllMembers(); }
 | 
						|
+    void RemoveAllMembers() { value_.RemoveAllMembers(); }
 | 
						|
     bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
     bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
 | 
						|
@@ -2573,4 +3035,9 @@ private:
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 
 | 
						|
+#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
 | 
						|
+#pragma pop_macro("GetObject")
 | 
						|
+#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #endif // RAPIDJSON_DOCUMENT_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/encodedstream.h b/src/common/thirdparty/rapidjson/encodedstream.h
 | 
						|
index 145068386..cf046b892 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/encodedstream.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/encodedstream.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -200,7 +200,7 @@ private:
 | 
						|
         // xx xx xx xx  UTF-8
 | 
						|
 
 | 
						|
         if (!hasBOM_) {
 | 
						|
-            unsigned 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) {
 | 
						|
             case 0x08: type_ = kUTF32BE; break;
 | 
						|
             case 0x0A: type_ = kUTF16BE; break;
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/encodings.h b/src/common/thirdparty/rapidjson/encodings.h
 | 
						|
index baa7c2b17..50ad18bdc 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/encodings.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/encodings.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -17,7 +17,7 @@
 | 
						|
 
 | 
						|
 #include "rapidjson.h"
 | 
						|
 
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#if defined(_MSC_VER) && !defined(__clang__)
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
 | 
						|
 RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
						|
@@ -144,9 +144,9 @@ struct UTF8 {
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
     static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
						|
-#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
 | 
						|
-#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 | 
						|
-#define TAIL() COPY(); TRANS(0x70)
 | 
						|
+#define RAPIDJSON_COPY() 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_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
 | 
						|
         typename InputStream::Ch c = is.Take();
 | 
						|
         if (!(c & 0x80)) {
 | 
						|
             *codepoint = static_cast<unsigned char>(c);
 | 
						|
@@ -157,48 +157,48 @@ struct UTF8 {
 | 
						|
         if (type >= 32) {
 | 
						|
             *codepoint = 0;
 | 
						|
         } else {
 | 
						|
-            *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
 | 
						|
+            *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
 | 
						|
         }
 | 
						|
         bool result = true;
 | 
						|
         switch (type) {
 | 
						|
-        case 2: TAIL(); return result;
 | 
						|
-        case 3: TAIL(); TAIL(); return result;
 | 
						|
-        case 4: COPY(); TRANS(0x50); TAIL(); return result;
 | 
						|
-        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
 | 
						|
-        case 6: TAIL(); TAIL(); TAIL(); return result;
 | 
						|
-        case 10: COPY(); TRANS(0x20); TAIL(); return result;
 | 
						|
-        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
 | 
						|
+        case 2: RAPIDJSON_TAIL(); return result;
 | 
						|
+        case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
						|
+        case 4: 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 COPY
 | 
						|
-#undef TRANS
 | 
						|
-#undef TAIL
 | 
						|
+#undef RAPIDJSON_COPY
 | 
						|
+#undef RAPIDJSON_TRANS
 | 
						|
+#undef RAPIDJSON_TAIL
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream, typename OutputStream>
 | 
						|
     static bool Validate(InputStream& is, OutputStream& os) {
 | 
						|
-#define COPY() os.Put(c = is.Take())
 | 
						|
-#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 | 
						|
-#define TAIL() COPY(); TRANS(0x70)
 | 
						|
+#define RAPIDJSON_COPY() os.Put(c = is.Take())
 | 
						|
+#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 | 
						|
+#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
 | 
						|
         Ch c;
 | 
						|
-        COPY();
 | 
						|
+        RAPIDJSON_COPY();
 | 
						|
         if (!(c & 0x80))
 | 
						|
             return true;
 | 
						|
 
 | 
						|
         bool result = true;
 | 
						|
         switch (GetRange(static_cast<unsigned char>(c))) {
 | 
						|
-        case 2: TAIL(); return result;
 | 
						|
-        case 3: TAIL(); TAIL(); return result;
 | 
						|
-        case 4: COPY(); TRANS(0x50); TAIL(); return result;
 | 
						|
-        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
 | 
						|
-        case 6: TAIL(); TAIL(); TAIL(); return result;
 | 
						|
-        case 10: COPY(); TRANS(0x20); TAIL(); return result;
 | 
						|
-        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
 | 
						|
+        case 2: RAPIDJSON_TAIL(); return result;
 | 
						|
+        case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
						|
+        case 4: 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 COPY
 | 
						|
-#undef TRANS
 | 
						|
-#undef TAIL
 | 
						|
+#undef RAPIDJSON_COPY
 | 
						|
+#undef RAPIDJSON_TRANS
 | 
						|
+#undef RAPIDJSON_TAIL
 | 
						|
     }
 | 
						|
 
 | 
						|
     static unsigned char GetRange(unsigned char c) {
 | 
						|
@@ -283,7 +283,7 @@ struct UTF16 {
 | 
						|
             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
						|
             unsigned v = codepoint - 0x10000;
 | 
						|
             os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 | 
						|
-            os.Put((v & 0x3FF) | 0xDC00);
 | 
						|
+            os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -299,7 +299,7 @@ struct UTF16 {
 | 
						|
             RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
						|
             unsigned v = codepoint - 0x10000;
 | 
						|
             PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 | 
						|
-            PutUnsafe(os, (v & 0x3FF) | 0xDC00);
 | 
						|
+            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -384,7 +384,7 @@ struct UTF16BE : UTF16<CharType> {
 | 
						|
     static CharType Take(InputByteStream& is) {
 | 
						|
         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
						|
         unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 | 
						|
-        c |= static_cast<uint8_t>(is.Take());
 | 
						|
+        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
 | 
						|
         return static_cast<CharType>(c);
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -620,28 +620,28 @@ struct AutoUTF {
 | 
						|
 #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
 | 
						|
 
 | 
						|
     template<typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
 | 
						|
         typedef void (*EncodeFunc)(OutputStream&, unsigned);
 | 
						|
         static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
 | 
						|
         (*f[os.GetType()])(os, codepoint);
 | 
						|
     }
 | 
						|
 
 | 
						|
     template<typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
						|
         typedef void (*EncodeFunc)(OutputStream&, unsigned);
 | 
						|
         static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
 | 
						|
         (*f[os.GetType()])(os, codepoint);
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
 | 
						|
         typedef bool (*DecodeFunc)(InputStream&, unsigned*);
 | 
						|
         static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
 | 
						|
         return (*f[is.GetType()])(is, codepoint);
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
 | 
						|
         typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
 | 
						|
         static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
 | 
						|
         return (*f[is.GetType()])(is, os);
 | 
						|
@@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
 | 
						|
 struct Transcoder {
 | 
						|
     //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
 | 
						|
         unsigned codepoint;
 | 
						|
         if (!SourceEncoding::Decode(is, &codepoint))
 | 
						|
             return false;
 | 
						|
@@ -667,7 +667,7 @@ struct Transcoder {
 | 
						|
     }
 | 
						|
 
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
 | 
						|
+    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
 | 
						|
         unsigned codepoint;
 | 
						|
         if (!SourceEncoding::Decode(is, &codepoint))
 | 
						|
             return false;
 | 
						|
@@ -677,7 +677,7 @@ struct Transcoder {
 | 
						|
 
 | 
						|
     //! Validate one Unicode codepoint from an encoded stream.
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static 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.
 | 
						|
     }
 | 
						|
 };
 | 
						|
@@ -690,26 +690,26 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
 | 
						|
 template<typename Encoding>
 | 
						|
 struct Transcoder<Encoding, Encoding> {
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static 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.
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
     
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static 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.
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
     
 | 
						|
     template<typename InputStream, typename OutputStream>
 | 
						|
-    RAPIDJSON_FORCEINLINE static 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
 | 
						|
     }
 | 
						|
 };
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
-#if defined(__GNUC__) || defined(_MSC_VER)
 | 
						|
+#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/error/en.h b/src/common/thirdparty/rapidjson/error/en.h
 | 
						|
index 2db838bff..c87b04eb1 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/error/en.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/error/en.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_ERROR_EN_H_
 | 
						|
@@ -39,13 +39,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
 | 
						|
 
 | 
						|
         case kParseErrorDocumentEmpty:                  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 kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
 | 
						|
-    
 | 
						|
+
 | 
						|
         case kParseErrorObjectMissName:                 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 kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
 | 
						|
-    
 | 
						|
+
 | 
						|
         case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
 | 
						|
 
 | 
						|
         case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
 | 
						|
@@ -65,6 +65,108 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
 | 
						|
     }
 | 
						|
 }
 | 
						|
 
 | 
						|
+//! Maps error code of validation into error message.
 | 
						|
+/*!
 | 
						|
+    \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \param validateErrorCode Error code obtained from validator.
 | 
						|
+    \return the error message.
 | 
						|
+    \note User can make a copy of this function for localization.
 | 
						|
+        Using switch-case is safer for future modification of error codes.
 | 
						|
+*/
 | 
						|
+inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
 | 
						|
+    switch (validateErrorCode) {
 | 
						|
+        case kValidateErrors:                           return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
 | 
						|
+        case kValidateErrorNone:                        return RAPIDJSON_ERROR_STRING("No error.");
 | 
						|
+
 | 
						|
+        case kValidateErrorMultipleOf:                  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 kValidateErrorExclusiveMaximum:            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:                   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 kValidateErrorPattern:                     return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
 | 
						|
+
 | 
						|
+        case kValidateErrorMaxItems:                    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 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:               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 kValidateErrorRequired:                    return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
 | 
						|
+        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:                        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 kValidateErrorOneOf:                       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', indices '%matches'.");
 | 
						|
+        case kValidateErrorAllOf:                       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'.");
 | 
						|
+
 | 
						|
+        case kValidateErrorReadOnly:                    return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing.");
 | 
						|
+        case kValidateErrorWriteOnly:                   return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading.");
 | 
						|
+
 | 
						|
+        default:                                        return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
						|
+    }
 | 
						|
+}
 | 
						|
+
 | 
						|
+//! Maps error code of schema document compilation into error message.
 | 
						|
+/*!
 | 
						|
+    \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \param schemaErrorCode Error code obtained from compiling the schema document.
 | 
						|
+    \return the error message.
 | 
						|
+    \note User can make a copy of this function for localization.
 | 
						|
+        Using switch-case is safer for future modification of error codes.
 | 
						|
+*/
 | 
						|
+  inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) {
 | 
						|
+      switch (schemaErrorCode) {
 | 
						|
+          case kSchemaErrorNone:                        return RAPIDJSON_ERROR_STRING("No error.");
 | 
						|
+
 | 
						|
+          case kSchemaErrorStartUnknown:                return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document.");
 | 
						|
+          case kSchemaErrorRefPlainName:                return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer.");
 | 
						|
+          case kSchemaErrorRefInvalid:                  return RAPIDJSON_ERROR_STRING("$ref must not be an empty string.");
 | 
						|
+          case kSchemaErrorRefPointerInvalid:           return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'.");
 | 
						|
+          case kSchemaErrorRefUnknown:                  return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document.");
 | 
						|
+          case kSchemaErrorRefCyclical:                 return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical.");
 | 
						|
+          case kSchemaErrorRefNoRemoteProvider:         return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider.");
 | 
						|
+          case kSchemaErrorRefNoRemoteSchema:           return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema.");
 | 
						|
+          case kSchemaErrorRegexInvalid:                return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'.");
 | 
						|
+          case kSchemaErrorSpecUnknown:                 return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized.");
 | 
						|
+          case kSchemaErrorSpecUnsupported:             return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported.");
 | 
						|
+          case kSchemaErrorSpecIllegal:                 return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document.");
 | 
						|
+          case kSchemaErrorReadOnlyAndWriteOnly:        return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'.");
 | 
						|
+
 | 
						|
+          default:                                      return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
						|
+    }
 | 
						|
+  }
 | 
						|
+
 | 
						|
+//! Maps error code of pointer parse into error message.
 | 
						|
+/*!
 | 
						|
+    \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \param pointerParseErrorCode Error code obtained from pointer parse.
 | 
						|
+    \return the error message.
 | 
						|
+    \note User can make a copy of this function for localization.
 | 
						|
+        Using switch-case is safer for future modification of error codes.
 | 
						|
+*/
 | 
						|
+inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) {
 | 
						|
+    switch (pointerParseErrorCode) {
 | 
						|
+        case kPointerParseErrorNone:                       return RAPIDJSON_ERROR_STRING("No error.");
 | 
						|
+
 | 
						|
+        case kPointerParseErrorTokenMustBeginWithSolidus:  return RAPIDJSON_ERROR_STRING("A token must begin with a '/'.");
 | 
						|
+        case kPointerParseErrorInvalidEscape:              return RAPIDJSON_ERROR_STRING("Invalid escape.");
 | 
						|
+        case kPointerParseErrorInvalidPercentEncoding:     return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment.");
 | 
						|
+        case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment.");
 | 
						|
+
 | 
						|
+        default:                                           return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
						|
+    }
 | 
						|
+}
 | 
						|
+
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/error/error.h b/src/common/thirdparty/rapidjson/error/error.h
 | 
						|
index 95cb31a72..cae345db3 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/error/error.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/error/error.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_ERROR_ERROR_H_
 | 
						|
@@ -42,7 +42,7 @@ RAPIDJSON_DIAG_OFF(padded)
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_ERROR_STRING
 | 
						|
 
 | 
						|
-//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
 | 
						|
+//! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[].
 | 
						|
 /*! \ingroup RAPIDJSON_ERRORS
 | 
						|
     By default this conversion macro does nothing.
 | 
						|
     On Windows, user can define this macro as \c _T(x) for supporting both
 | 
						|
@@ -104,6 +104,8 @@ enum ParseErrorCode {
 | 
						|
     \see GenericReader::Parse, GenericDocument::Parse
 | 
						|
 */
 | 
						|
 struct ParseResult {
 | 
						|
+    //!! Unspecified boolean type
 | 
						|
+    typedef bool (ParseResult::*BooleanType)() const;
 | 
						|
 public:
 | 
						|
     //! Default constructor, no error.
 | 
						|
     ParseResult() : code_(kParseErrorNone), offset_(0) {}
 | 
						|
@@ -115,8 +117,8 @@ public:
 | 
						|
     //! Get the error offset, if \ref IsError(), 0 otherwise.
 | 
						|
     size_t Offset() const { return offset_; }
 | 
						|
 
 | 
						|
-    //! Conversion to \c bool, returns \c true, iff !\ref IsError().
 | 
						|
-    operator bool() const { return !IsError(); }
 | 
						|
+    //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
 | 
						|
+    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
 | 
						|
     //! Whether the result is an error.
 | 
						|
     bool IsError() const { return code_ != kParseErrorNone; }
 | 
						|
 
 | 
						|
@@ -124,6 +126,10 @@ public:
 | 
						|
     bool operator==(ParseErrorCode code) const { return code_ == code; }
 | 
						|
     friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
 | 
						|
 
 | 
						|
+    bool operator!=(const ParseResult& that) const { return !(*this == that); }
 | 
						|
+    bool operator!=(ParseErrorCode code) const { return !(*this == code); }
 | 
						|
+    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
 | 
						|
+
 | 
						|
     //! Reset error code.
 | 
						|
     void Clear() { Set(kParseErrorNone); }
 | 
						|
     //! Update error code and offset.
 | 
						|
@@ -146,6 +152,130 @@ private:
 | 
						|
 */
 | 
						|
 typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// ValidateErrorCode
 | 
						|
+
 | 
						|
+//! Error codes when validating.
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \see GenericSchemaValidator
 | 
						|
+*/
 | 
						|
+enum ValidateErrorCode {
 | 
						|
+    kValidateErrors    = -1,                   //!< Top level error code when kValidateContinueOnErrorsFlag set.
 | 
						|
+    kValidateErrorNone = 0,                    //!< No error.
 | 
						|
+
 | 
						|
+    kValidateErrorMultipleOf,                  //!< Number is not a multiple of the 'multipleOf' value.
 | 
						|
+    kValidateErrorMaximum,                     //!< Number is greater than the 'maximum' value.
 | 
						|
+    kValidateErrorExclusiveMaximum,            //!< Number is greater than or equal to the 'maximum' value.
 | 
						|
+    kValidateErrorMinimum,                     //!< Number is less than the 'minimum' value.
 | 
						|
+    kValidateErrorExclusiveMinimum,            //!< Number is less than or equal to the 'minimum' value.
 | 
						|
+
 | 
						|
+    kValidateErrorMaxLength,                   //!< String is longer than the 'maxLength' value.
 | 
						|
+    kValidateErrorMinLength,                   //!< String is longer than the 'maxLength' value.
 | 
						|
+    kValidateErrorPattern,                     //!< String does not match the 'pattern' regular expression.
 | 
						|
+
 | 
						|
+    kValidateErrorMaxItems,                    //!< Array is longer than the 'maxItems' value.
 | 
						|
+    kValidateErrorMinItems,                    //!< Array is shorter than the 'minItems' value.
 | 
						|
+    kValidateErrorUniqueItems,                 //!< Array has duplicate items but 'uniqueItems' is true.
 | 
						|
+    kValidateErrorAdditionalItems,             //!< Array has additional items that are not allowed by the schema.
 | 
						|
+
 | 
						|
+    kValidateErrorMaxProperties,               //!< Object has more members than 'maxProperties' value.
 | 
						|
+    kValidateErrorMinProperties,               //!< Object has less members than 'minProperties' value.
 | 
						|
+    kValidateErrorRequired,                    //!< Object is missing one or more members required by the schema.
 | 
						|
+    kValidateErrorAdditionalProperties,        //!< Object has additional members that are not allowed by the schema.
 | 
						|
+    kValidateErrorPatternProperties,           //!< See other errors.
 | 
						|
+    kValidateErrorDependencies,                //!< Object has missing property or schema dependencies.
 | 
						|
+
 | 
						|
+    kValidateErrorEnum,                        //!< Property has a value that is not one of its allowed enumerated values.
 | 
						|
+    kValidateErrorType,                        //!< Property has a type that is not allowed by the schema.
 | 
						|
+
 | 
						|
+    kValidateErrorOneOf,                       //!< Property did not match any of the sub-schemas specified by 'oneOf'.
 | 
						|
+    kValidateErrorOneOfMatch,                  //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
 | 
						|
+    kValidateErrorAllOf,                       //!< Property did not match all of the sub-schemas specified by 'allOf'.
 | 
						|
+    kValidateErrorAnyOf,                       //!< Property did not match any of the sub-schemas specified by 'anyOf'.
 | 
						|
+    kValidateErrorNot,                         //!< Property matched the sub-schema specified by 'not'.
 | 
						|
+
 | 
						|
+    kValidateErrorReadOnly,                    //!< Property is read-only but has been provided when validation is for writing
 | 
						|
+    kValidateErrorWriteOnly                    //!< Property is write-only but has been provided when validation is for reading
 | 
						|
+};
 | 
						|
+
 | 
						|
+//! Function pointer type of GetValidateError().
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+
 | 
						|
+    This is the prototype for \c GetValidateError_X(), where \c X is a locale.
 | 
						|
+    User can dynamically change locale in runtime, e.g.:
 | 
						|
+\code
 | 
						|
+    GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
 | 
						|
+    const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
 | 
						|
+\endcode
 | 
						|
+*/
 | 
						|
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// SchemaErrorCode
 | 
						|
+
 | 
						|
+//! Error codes when validating.
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \see GenericSchemaValidator
 | 
						|
+*/
 | 
						|
+enum SchemaErrorCode {
 | 
						|
+    kSchemaErrorNone = 0,                      //!< No error.
 | 
						|
+
 | 
						|
+    kSchemaErrorStartUnknown,                  //!< Pointer to start of schema does not resolve to a location in the document
 | 
						|
+    kSchemaErrorRefPlainName,                  //!< $ref fragment must be a JSON pointer
 | 
						|
+    kSchemaErrorRefInvalid,                    //!< $ref must not be an empty string
 | 
						|
+    kSchemaErrorRefPointerInvalid,             //!< $ref fragment is not a valid JSON pointer at offset
 | 
						|
+    kSchemaErrorRefUnknown,                    //!< $ref does not resolve to a location in the target document
 | 
						|
+    kSchemaErrorRefCyclical,                   //!< $ref is cyclical
 | 
						|
+    kSchemaErrorRefNoRemoteProvider,           //!< $ref is remote but there is no remote provider
 | 
						|
+    kSchemaErrorRefNoRemoteSchema,             //!< $ref is remote but the remote provider did not return a schema
 | 
						|
+    kSchemaErrorRegexInvalid,                  //!< Invalid regular expression in 'pattern' or 'patternProperties'
 | 
						|
+    kSchemaErrorSpecUnknown,                   //!< JSON schema draft or OpenAPI version is not recognized
 | 
						|
+    kSchemaErrorSpecUnsupported,               //!< JSON schema draft or OpenAPI version is not supported
 | 
						|
+    kSchemaErrorSpecIllegal,                   //!< Both JSON schema draft and OpenAPI version found in document
 | 
						|
+    kSchemaErrorReadOnlyAndWriteOnly           //!< Property must not be both 'readOnly' and 'writeOnly'
 | 
						|
+};
 | 
						|
+
 | 
						|
+//! Function pointer type of GetSchemaError().
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+
 | 
						|
+    This is the prototype for \c GetSchemaError_X(), where \c X is a locale.
 | 
						|
+    User can dynamically change locale in runtime, e.g.:
 | 
						|
+\code
 | 
						|
+    GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever
 | 
						|
+    const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode());
 | 
						|
+\endcode
 | 
						|
+*/
 | 
						|
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode);
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// PointerParseErrorCode
 | 
						|
+
 | 
						|
+//! Error code of JSON pointer parsing.
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+    \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
 | 
						|
+*/
 | 
						|
+enum PointerParseErrorCode {
 | 
						|
+    kPointerParseErrorNone = 0,                     //!< The parse is successful
 | 
						|
+
 | 
						|
+    kPointerParseErrorTokenMustBeginWithSolidus,    //!< A token must begin with a '/'
 | 
						|
+    kPointerParseErrorInvalidEscape,                //!< Invalid escape
 | 
						|
+    kPointerParseErrorInvalidPercentEncoding,       //!< Invalid percent encoding in URI fragment
 | 
						|
+    kPointerParseErrorCharacterMustPercentEncode    //!< A character must percent encoded in URI fragment
 | 
						|
+};
 | 
						|
+
 | 
						|
+//! Function pointer type of GetPointerParseError().
 | 
						|
+/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
+
 | 
						|
+    This is the prototype for \c GetPointerParseError_X(), where \c X is a locale.
 | 
						|
+    User can dynamically change locale in runtime, e.g.:
 | 
						|
+\code
 | 
						|
+    GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever
 | 
						|
+    const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode());
 | 
						|
+\endcode
 | 
						|
+*/
 | 
						|
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode);
 | 
						|
+
 | 
						|
+
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/filereadstream.h b/src/common/thirdparty/rapidjson/filereadstream.h
 | 
						|
index b56ea13b3..f8bb43cb0 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/filereadstream.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/filereadstream.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -59,7 +59,7 @@ public:
 | 
						|
 
 | 
						|
     // For encoding detection only.
 | 
						|
     const Ch* Peek4() const {
 | 
						|
-        return (current_ + 4 <= bufferLast_) ? current_ : 0;
 | 
						|
+        return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
 | 
						|
     }
 | 
						|
 
 | 
						|
 private:
 | 
						|
@@ -68,7 +68,7 @@ private:
 | 
						|
             ++current_;
 | 
						|
         else if (!eof_) {
 | 
						|
             count_ += readCount_;
 | 
						|
-            readCount_ = fread(buffer_, 1, bufferSize_, fp_);
 | 
						|
+            readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
 | 
						|
             bufferLast_ = buffer_ + readCount_ - 1;
 | 
						|
             current_ = buffer_;
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/filewritestream.h b/src/common/thirdparty/rapidjson/filewritestream.h
 | 
						|
index 6378dd60e..5d89588c2 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/filewritestream.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/filewritestream.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -25,7 +25,7 @@ RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 
 | 
						|
-//! Wrapper of C file stream for input using fread().
 | 
						|
+//! Wrapper of C file stream for output using fwrite().
 | 
						|
 /*!
 | 
						|
     \note implements Stream concept
 | 
						|
 */
 | 
						|
@@ -62,7 +62,7 @@ public:
 | 
						|
 
 | 
						|
     void Flush() {
 | 
						|
         if (current_ != buffer_) {
 | 
						|
-            size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
 | 
						|
+            size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
 | 
						|
             if (result < static_cast<size_t>(current_ - buffer_)) {
 | 
						|
                 // failure deliberately ignored at this time
 | 
						|
                 // added to avoid warn_unused_result build errors
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/fwd.h b/src/common/thirdparty/rapidjson/fwd.h
 | 
						|
index e8104e841..d62f77f0e 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/fwd.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/fwd.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -102,7 +102,7 @@ class PrettyWriter;
 | 
						|
 // document.h
 | 
						|
 
 | 
						|
 template <typename Encoding, typename Allocator> 
 | 
						|
-struct GenericMember;
 | 
						|
+class GenericMember;
 | 
						|
 
 | 
						|
 template <bool Const, typename Encoding, typename Allocator>
 | 
						|
 class GenericMemberIterator;
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/biginteger.h b/src/common/thirdparty/rapidjson/internal/biginteger.h
 | 
						|
index 9d3e88c99..af4873803 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/biginteger.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/biginteger.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -17,9 +17,13 @@
 | 
						|
 
 | 
						|
 #include "../rapidjson.h"
 | 
						|
 
 | 
						|
-#if defined(_MSC_VER) && defined(_M_AMD64)
 | 
						|
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
 | 
						|
 #include <intrin.h> // for _umul128
 | 
						|
+#if !defined(_ARM64EC_)
 | 
						|
 #pragma intrinsic(_umul128)
 | 
						|
+#else
 | 
						|
+#pragma comment(lib,"softintrin")
 | 
						|
+#endif
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
@@ -37,7 +41,8 @@ public:
 | 
						|
         digits_[0] = u;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    BigInteger(const char* decimals, size_t length) : count_(1) {
 | 
						|
+    template<typename Ch>
 | 
						|
+    BigInteger(const Ch* decimals, size_t length) : count_(1) {
 | 
						|
         RAPIDJSON_ASSERT(length > 0);
 | 
						|
         digits_[0] = 0;
 | 
						|
         size_t i = 0;
 | 
						|
@@ -133,7 +138,7 @@ public:
 | 
						|
         RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
 | 
						|
 
 | 
						|
         if (interShift == 0) {
 | 
						|
-            std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
 | 
						|
+            std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
 | 
						|
             count_ += offset;
 | 
						|
         }
 | 
						|
         else {
 | 
						|
@@ -221,7 +226,8 @@ public:
 | 
						|
     bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
 | 
						|
 
 | 
						|
 private:
 | 
						|
-    void AppendDecimal64(const char* begin, const char* end) {
 | 
						|
+    template<typename Ch>
 | 
						|
+    void AppendDecimal64(const Ch* begin, const Ch* end) {
 | 
						|
         uint64_t u = ParseUint64(begin, end);
 | 
						|
         if (IsZero())
 | 
						|
             *this = u;
 | 
						|
@@ -236,11 +242,12 @@ private:
 | 
						|
         digits_[count_++] = digit;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    static uint64_t ParseUint64(const char* begin, const char* end) {
 | 
						|
+    template<typename Ch>
 | 
						|
+    static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
 | 
						|
         uint64_t r = 0;
 | 
						|
-        for (const char* p = begin; p != end; ++p) {
 | 
						|
-            RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
 | 
						|
-            r = r * 10u + static_cast<unsigned>(*p - '0');
 | 
						|
+        for (const Ch* p = begin; p != end; ++p) {
 | 
						|
+            RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
 | 
						|
+            r = r * 10u + static_cast<unsigned>(*p - Ch('0'));
 | 
						|
         }
 | 
						|
         return r;
 | 
						|
     }
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/clzll.h b/src/common/thirdparty/rapidjson/internal/clzll.h
 | 
						|
new file mode 100644
 | 
						|
index 000000000..8fc5118aa
 | 
						|
--- /dev/null
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/clzll.h
 | 
						|
@@ -0,0 +1,71 @@
 | 
						|
+// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
+//
 | 
						|
+// Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
+// in compliance with the License. You may obtain a copy of the License at
 | 
						|
+//
 | 
						|
+// http://opensource.org/licenses/MIT
 | 
						|
+//
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
+// specific language governing permissions and limitations under the License.
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_CLZLL_H_
 | 
						|
+#define RAPIDJSON_CLZLL_H_
 | 
						|
+
 | 
						|
+#include "../rapidjson.h"
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && !defined(UNDER_CE)
 | 
						|
+#include <intrin.h>
 | 
						|
+#if defined(_WIN64)
 | 
						|
+#pragma intrinsic(_BitScanReverse64)
 | 
						|
+#else
 | 
						|
+#pragma intrinsic(_BitScanReverse)
 | 
						|
+#endif
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
+namespace internal {
 | 
						|
+
 | 
						|
+inline uint32_t clzll(uint64_t x) {
 | 
						|
+    // Passing 0 to __builtin_clzll is UB in GCC and results in an
 | 
						|
+    // infinite loop in the software implementation.
 | 
						|
+    RAPIDJSON_ASSERT(x != 0);
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && !defined(UNDER_CE)
 | 
						|
+    unsigned long r = 0;
 | 
						|
+#if defined(_WIN64)
 | 
						|
+    _BitScanReverse64(&r, x);
 | 
						|
+#else
 | 
						|
+    // Scan the high 32 bits.
 | 
						|
+    if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
 | 
						|
+        return 63 - (r + 32);
 | 
						|
+
 | 
						|
+    // Scan the low 32 bits.
 | 
						|
+    _BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
 | 
						|
+#endif // _WIN64
 | 
						|
+
 | 
						|
+    return 63 - r;
 | 
						|
+#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
 | 
						|
+    // __builtin_clzll wrapper
 | 
						|
+    return static_cast<uint32_t>(__builtin_clzll(x));
 | 
						|
+#else
 | 
						|
+    // naive version
 | 
						|
+    uint32_t r = 0;
 | 
						|
+    while (!(x & (static_cast<uint64_t>(1) << 63))) {
 | 
						|
+        x <<= 1;
 | 
						|
+        ++r;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    return r;
 | 
						|
+#endif // _MSC_VER
 | 
						|
+}
 | 
						|
+
 | 
						|
+#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
 | 
						|
+
 | 
						|
+} // namespace internal
 | 
						|
+RAPIDJSON_NAMESPACE_END
 | 
						|
+
 | 
						|
+#endif // RAPIDJSON_CLZLL_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/diyfp.h b/src/common/thirdparty/rapidjson/internal/diyfp.h
 | 
						|
index c9fefdc61..f7d46539a 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/diyfp.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/diyfp.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 // This is a C++ header-only implementation of Grisu2 algorithm from the publication:
 | 
						|
@@ -20,11 +20,16 @@
 | 
						|
 #define RAPIDJSON_DIYFP_H_
 | 
						|
 
 | 
						|
 #include "../rapidjson.h"
 | 
						|
+#include "clzll.h"
 | 
						|
+#include <limits>
 | 
						|
 
 | 
						|
-#if defined(_MSC_VER) && defined(_M_AMD64)
 | 
						|
+#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
 | 
						|
 #include <intrin.h>
 | 
						|
-#pragma intrinsic(_BitScanReverse64)
 | 
						|
+#if !defined(_ARM64EC_)
 | 
						|
 #pragma intrinsic(_umul128)
 | 
						|
+#else
 | 
						|
+#pragma comment(lib,"softintrin")
 | 
						|
+#endif
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
@@ -56,7 +61,7 @@ struct DiyFp {
 | 
						|
         if (biased_e != 0) {
 | 
						|
             f = significand + kDpHiddenBit;
 | 
						|
             e = biased_e - kDpExponentBias;
 | 
						|
-        } 
 | 
						|
+        }
 | 
						|
         else {
 | 
						|
             f = significand;
 | 
						|
             e = kDpMinExponent + 1;
 | 
						|
@@ -99,21 +104,8 @@ struct DiyFp {
 | 
						|
     }
 | 
						|
 
 | 
						|
     DiyFp Normalize() const {
 | 
						|
-#if defined(_MSC_VER) && defined(_M_AMD64)
 | 
						|
-        unsigned long index;
 | 
						|
-        _BitScanReverse64(&index, f);
 | 
						|
-        return DiyFp(f << (63 - index), e - (63 - index));
 | 
						|
-#elif defined(__GNUC__) && __GNUC__ >= 4
 | 
						|
-        int s = __builtin_clzll(f);
 | 
						|
+        int s = static_cast<int>(clzll(f));
 | 
						|
         return DiyFp(f << s, e - s);
 | 
						|
-#else
 | 
						|
-        DiyFp res = *this;
 | 
						|
-        while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
 | 
						|
-            res.f <<= 1;
 | 
						|
-            res.e--;
 | 
						|
-        }
 | 
						|
-        return res;
 | 
						|
-#endif
 | 
						|
     }
 | 
						|
 
 | 
						|
     DiyFp NormalizeBoundary() const {
 | 
						|
@@ -141,7 +133,16 @@ struct DiyFp {
 | 
						|
             double d;
 | 
						|
             uint64_t u64;
 | 
						|
         }u;
 | 
						|
-        const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : 
 | 
						|
+        RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
 | 
						|
+        if (e < kDpDenormalExponent) {
 | 
						|
+            // Underflow.
 | 
						|
+            return 0.0;
 | 
						|
+        }
 | 
						|
+        if (e >= kDpMaxExponent) {
 | 
						|
+            // Overflow.
 | 
						|
+            return std::numeric_limits<double>::infinity();
 | 
						|
+        }
 | 
						|
+        const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
 | 
						|
             static_cast<uint64_t>(e + kDpExponentBias);
 | 
						|
         u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
 | 
						|
         return u.d;
 | 
						|
@@ -220,9 +221,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
 | 
						|
         641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
 | 
						|
         907,   933,   960,   986,  1013,  1039,  1066
 | 
						|
     };
 | 
						|
+    RAPIDJSON_ASSERT(index < 87);
 | 
						|
     return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
 | 
						|
 }
 | 
						|
-    
 | 
						|
+
 | 
						|
 inline DiyFp GetCachedPower(int e, int* K) {
 | 
						|
 
 | 
						|
     //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
 | 
						|
@@ -238,10 +240,11 @@ inline DiyFp GetCachedPower(int e, int* K) {
 | 
						|
 }
 | 
						|
 
 | 
						|
 inline DiyFp GetCachedPower10(int exp, int *outExp) {
 | 
						|
-     unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
 | 
						|
-     *outExp = -348 + static_cast<int>(index) * 8;
 | 
						|
-     return GetCachedPowerByIndex(index);
 | 
						|
- }
 | 
						|
+    RAPIDJSON_ASSERT(exp >= -348);
 | 
						|
+    unsigned index = static_cast<unsigned>(exp + 348) / 8u;
 | 
						|
+    *outExp = -348 + static_cast<int>(index) * 8;
 | 
						|
+    return GetCachedPowerByIndex(index);
 | 
						|
+}
 | 
						|
 
 | 
						|
 #ifdef __GNUC__
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/dtoa.h b/src/common/thirdparty/rapidjson/internal/dtoa.h
 | 
						|
index 8d6350e62..cd456721a 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/dtoa.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/dtoa.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
 | 
						|
     }
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline unsigned CountDecimalDigit32(uint32_t n) {
 | 
						|
+inline int CountDecimalDigit32(uint32_t n) {
 | 
						|
     // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
 | 
						|
     if (n < 10) return 1;
 | 
						|
     if (n < 100) return 2;
 | 
						|
@@ -58,12 +58,16 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
 | 
						|
 }
 | 
						|
 
 | 
						|
 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 uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL,
 | 
						|
+                                       1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
 | 
						|
+                                       10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
 | 
						|
+                                       10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL,
 | 
						|
+                                       10000000000000000000ULL };
 | 
						|
     const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
 | 
						|
     const DiyFp wp_w = Mp - W;
 | 
						|
     uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
 | 
						|
     uint64_t p2 = Mp.f & (one.f - 1);
 | 
						|
-    unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
 | 
						|
+    int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
 | 
						|
     *len = 0;
 | 
						|
 
 | 
						|
     while (kappa > 0) {
 | 
						|
@@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
 | 
						|
         uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
 | 
						|
         if (tmp <= delta) {
 | 
						|
             *K += kappa;
 | 
						|
-            GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
 | 
						|
+            GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
 | 
						|
             return;
 | 
						|
         }
 | 
						|
     }
 | 
						|
@@ -102,8 +106,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
 | 
						|
         kappa--;
 | 
						|
         if (p2 < delta) {
 | 
						|
             *K += kappa;
 | 
						|
-            int index = -static_cast<int>(kappa);
 | 
						|
-            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
 | 
						|
+            int index = -kappa;
 | 
						|
+            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
 | 
						|
             return;
 | 
						|
         }
 | 
						|
     }
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/ieee754.h b/src/common/thirdparty/rapidjson/internal/ieee754.h
 | 
						|
index 82bb0b99e..68c9e9664 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/ieee754.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/ieee754.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -48,13 +48,13 @@ public:
 | 
						|
     int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
 | 
						|
     uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
 | 
						|
 
 | 
						|
-    static unsigned EffectiveSignificandSize(int order) {
 | 
						|
+    static int EffectiveSignificandSize(int order) {
 | 
						|
         if (order >= -1021)
 | 
						|
             return 53;
 | 
						|
         else if (order <= -1074)
 | 
						|
             return 0;
 | 
						|
         else
 | 
						|
-            return static_cast<unsigned>(order) + 1074;
 | 
						|
+            return order + 1074;
 | 
						|
     }
 | 
						|
 
 | 
						|
 private:
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/itoa.h b/src/common/thirdparty/rapidjson/internal/itoa.h
 | 
						|
index 01a4e7e72..9fe8c932f 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/itoa.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/itoa.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_ITOA_
 | 
						|
@@ -37,12 +37,14 @@ inline const char* GetDigitsLut() {
 | 
						|
 }
 | 
						|
 
 | 
						|
 inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
+    RAPIDJSON_ASSERT(buffer != 0);
 | 
						|
+
 | 
						|
     const char* cDigitsLut = GetDigitsLut();
 | 
						|
 
 | 
						|
     if (value < 10000) {
 | 
						|
         const uint32_t d1 = (value / 100) << 1;
 | 
						|
         const uint32_t d2 = (value % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         if (value >= 1000)
 | 
						|
             *buffer++ = cDigitsLut[d1];
 | 
						|
         if (value >= 100)
 | 
						|
@@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
         // value = bbbbcccc
 | 
						|
         const uint32_t b = value / 10000;
 | 
						|
         const uint32_t c = value % 10000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d1 = (b / 100) << 1;
 | 
						|
         const uint32_t d2 = (b % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d3 = (c / 100) << 1;
 | 
						|
         const uint32_t d4 = (c % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         if (value >= 10000000)
 | 
						|
             *buffer++ = cDigitsLut[d1];
 | 
						|
         if (value >= 1000000)
 | 
						|
@@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
         if (value >= 100000)
 | 
						|
             *buffer++ = cDigitsLut[d2];
 | 
						|
         *buffer++ = cDigitsLut[d2 + 1];
 | 
						|
-        
 | 
						|
+
 | 
						|
         *buffer++ = cDigitsLut[d3];
 | 
						|
         *buffer++ = cDigitsLut[d3 + 1];
 | 
						|
         *buffer++ = cDigitsLut[d4];
 | 
						|
@@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
     }
 | 
						|
     else {
 | 
						|
         // value = aabbbbcccc in decimal
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t a = value / 100000000; // 1 to 42
 | 
						|
         value %= 100000000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         if (a >= 10) {
 | 
						|
             const unsigned i = a << 1;
 | 
						|
             *buffer++ = cDigitsLut[i];
 | 
						|
@@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
 
 | 
						|
         const uint32_t b = value / 10000; // 0 to 9999
 | 
						|
         const uint32_t c = value % 10000; // 0 to 9999
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d1 = (b / 100) << 1;
 | 
						|
         const uint32_t d2 = (b % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d3 = (c / 100) << 1;
 | 
						|
         const uint32_t d4 = (c % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         *buffer++ = cDigitsLut[d1];
 | 
						|
         *buffer++ = cDigitsLut[d1 + 1];
 | 
						|
         *buffer++ = cDigitsLut[d2];
 | 
						|
@@ -111,6 +113,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
 | 
						|
 }
 | 
						|
 
 | 
						|
 inline char* i32toa(int32_t value, char* buffer) {
 | 
						|
+    RAPIDJSON_ASSERT(buffer != 0);
 | 
						|
     uint32_t u = static_cast<uint32_t>(value);
 | 
						|
     if (value < 0) {
 | 
						|
         *buffer++ = '-';
 | 
						|
@@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) {
 | 
						|
 }
 | 
						|
 
 | 
						|
 inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
+    RAPIDJSON_ASSERT(buffer != 0);
 | 
						|
     const char* cDigitsLut = GetDigitsLut();
 | 
						|
     const uint64_t  kTen8 = 100000000;
 | 
						|
     const uint64_t  kTen9 = kTen8 * 10;
 | 
						|
@@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
     const uint64_t kTen14 = kTen8 * 1000000;
 | 
						|
     const uint64_t kTen15 = kTen8 * 10000000;
 | 
						|
     const uint64_t kTen16 = kTen8 * kTen8;
 | 
						|
-    
 | 
						|
+
 | 
						|
     if (value < kTen8) {
 | 
						|
         uint32_t v = static_cast<uint32_t>(value);
 | 
						|
         if (v < 10000) {
 | 
						|
             const uint32_t d1 = (v / 100) << 1;
 | 
						|
             const uint32_t d2 = (v % 100) << 1;
 | 
						|
-            
 | 
						|
+
 | 
						|
             if (v >= 1000)
 | 
						|
                 *buffer++ = cDigitsLut[d1];
 | 
						|
             if (v >= 100)
 | 
						|
@@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
             // value = bbbbcccc
 | 
						|
             const uint32_t b = v / 10000;
 | 
						|
             const uint32_t c = v % 10000;
 | 
						|
-            
 | 
						|
+
 | 
						|
             const uint32_t d1 = (b / 100) << 1;
 | 
						|
             const uint32_t d2 = (b % 100) << 1;
 | 
						|
-            
 | 
						|
+
 | 
						|
             const uint32_t d3 = (c / 100) << 1;
 | 
						|
             const uint32_t d4 = (c % 100) << 1;
 | 
						|
-            
 | 
						|
+
 | 
						|
             if (value >= 10000000)
 | 
						|
                 *buffer++ = cDigitsLut[d1];
 | 
						|
             if (value >= 1000000)
 | 
						|
@@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
             if (value >= 100000)
 | 
						|
                 *buffer++ = cDigitsLut[d2];
 | 
						|
             *buffer++ = cDigitsLut[d2 + 1];
 | 
						|
-            
 | 
						|
+
 | 
						|
             *buffer++ = cDigitsLut[d3];
 | 
						|
             *buffer++ = cDigitsLut[d3 + 1];
 | 
						|
             *buffer++ = cDigitsLut[d4];
 | 
						|
@@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
     else if (value < kTen16) {
 | 
						|
         const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
 | 
						|
         const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t b0 = v0 / 10000;
 | 
						|
         const uint32_t c0 = v0 % 10000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d1 = (b0 / 100) << 1;
 | 
						|
         const uint32_t d2 = (b0 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d3 = (c0 / 100) << 1;
 | 
						|
         const uint32_t d4 = (c0 % 100) << 1;
 | 
						|
 
 | 
						|
         const uint32_t b1 = v1 / 10000;
 | 
						|
         const uint32_t c1 = v1 % 10000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d5 = (b1 / 100) << 1;
 | 
						|
         const uint32_t d6 = (b1 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d7 = (c1 / 100) << 1;
 | 
						|
         const uint32_t d8 = (c1 % 100) << 1;
 | 
						|
 
 | 
						|
@@ -207,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
             *buffer++ = cDigitsLut[d3 + 1];
 | 
						|
         if (value >= kTen9)
 | 
						|
             *buffer++ = cDigitsLut[d4];
 | 
						|
-        if (value >= kTen8)
 | 
						|
-            *buffer++ = cDigitsLut[d4 + 1];
 | 
						|
-        
 | 
						|
+
 | 
						|
+        *buffer++ = cDigitsLut[d4 + 1];
 | 
						|
         *buffer++ = cDigitsLut[d5];
 | 
						|
         *buffer++ = cDigitsLut[d5 + 1];
 | 
						|
         *buffer++ = cDigitsLut[d6];
 | 
						|
@@ -222,7 +225,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
     else {
 | 
						|
         const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
 | 
						|
         value %= kTen16;
 | 
						|
-        
 | 
						|
+
 | 
						|
         if (a < 10)
 | 
						|
             *buffer++ = static_cast<char>('0' + static_cast<char>(a));
 | 
						|
         else if (a < 100) {
 | 
						|
@@ -232,7 +235,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
         }
 | 
						|
         else if (a < 1000) {
 | 
						|
             *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
 | 
						|
-            
 | 
						|
+
 | 
						|
             const uint32_t i = (a % 100) << 1;
 | 
						|
             *buffer++ = cDigitsLut[i];
 | 
						|
             *buffer++ = cDigitsLut[i + 1];
 | 
						|
@@ -245,28 +248,28 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
             *buffer++ = cDigitsLut[j];
 | 
						|
             *buffer++ = cDigitsLut[j + 1];
 | 
						|
         }
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
 | 
						|
         const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t b0 = v0 / 10000;
 | 
						|
         const uint32_t c0 = v0 % 10000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d1 = (b0 / 100) << 1;
 | 
						|
         const uint32_t d2 = (b0 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d3 = (c0 / 100) << 1;
 | 
						|
         const uint32_t d4 = (c0 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t b1 = v1 / 10000;
 | 
						|
         const uint32_t c1 = v1 % 10000;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d5 = (b1 / 100) << 1;
 | 
						|
         const uint32_t d6 = (b1 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         const uint32_t d7 = (c1 / 100) << 1;
 | 
						|
         const uint32_t d8 = (c1 % 100) << 1;
 | 
						|
-        
 | 
						|
+
 | 
						|
         *buffer++ = cDigitsLut[d1];
 | 
						|
         *buffer++ = cDigitsLut[d1 + 1];
 | 
						|
         *buffer++ = cDigitsLut[d2];
 | 
						|
@@ -284,11 +287,12 @@ inline char* u64toa(uint64_t value, char* buffer) {
 | 
						|
         *buffer++ = cDigitsLut[d8];
 | 
						|
         *buffer++ = cDigitsLut[d8 + 1];
 | 
						|
     }
 | 
						|
-    
 | 
						|
+
 | 
						|
     return buffer;
 | 
						|
 }
 | 
						|
 
 | 
						|
 inline char* i64toa(int64_t value, char* buffer) {
 | 
						|
+    RAPIDJSON_ASSERT(buffer != 0);
 | 
						|
     uint64_t u = static_cast<uint64_t>(value);
 | 
						|
     if (value < 0) {
 | 
						|
         *buffer++ = '-';
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/meta.h b/src/common/thirdparty/rapidjson/internal/meta.h
 | 
						|
index 5a9aaa428..27092dc0d 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/meta.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/meta.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -21,7 +21,8 @@
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(effc++)
 | 
						|
 #endif
 | 
						|
-#if defined(_MSC_VER)
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && !defined(__clang__)
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(6334)
 | 
						|
 #endif
 | 
						|
@@ -174,7 +175,11 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 //@endcond
 | 
						|
 
 | 
						|
-#if defined(__GNUC__) || defined(_MSC_VER)
 | 
						|
+#if defined(_MSC_VER) && !defined(__clang__)
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#ifdef __GNUC__
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/pow10.h b/src/common/thirdparty/rapidjson/internal/pow10.h
 | 
						|
index 02f475d70..eae1a43ed 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/pow10.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/pow10.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/regex.h b/src/common/thirdparty/rapidjson/internal/regex.h
 | 
						|
index 422a5240b..6446c403a 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/regex.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/regex.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -23,7 +23,9 @@
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(padded)
 | 
						|
 RAPIDJSON_DIAG_OFF(switch-enum)
 | 
						|
-RAPIDJSON_DIAG_OFF(implicit-fallthrough)
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #ifdef __GNUC__
 | 
						|
@@ -31,11 +33,6 @@ RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(effc++)
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_PUSH
 | 
						|
-RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
-#endif
 | 
						|
-
 | 
						|
 #ifndef RAPIDJSON_REGEX_VERBOSE
 | 
						|
 #define RAPIDJSON_REGEX_VERBOSE 0
 | 
						|
 #endif
 | 
						|
@@ -43,12 +40,40 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 namespace internal {
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// DecodedStream
 | 
						|
+
 | 
						|
+template <typename SourceStream, typename Encoding>
 | 
						|
+class DecodedStream {
 | 
						|
+public:
 | 
						|
+    DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
 | 
						|
+    unsigned Peek() { return codepoint_; }
 | 
						|
+    unsigned Take() {
 | 
						|
+        unsigned c = codepoint_;
 | 
						|
+        if (c) // No further decoding when '\0'
 | 
						|
+            Decode();
 | 
						|
+        return c;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    void Decode() {
 | 
						|
+        if (!Encoding::Decode(ss_, &codepoint_))
 | 
						|
+            codepoint_ = 0;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    SourceStream& ss_;
 | 
						|
+    unsigned codepoint_;
 | 
						|
+};
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // GenericRegex
 | 
						|
 
 | 
						|
 static const SizeType kRegexInvalidState = ~SizeType(0);  //!< Represents an invalid index in GenericRegex::State::out, out1
 | 
						|
 static const SizeType kRegexInvalidRange = ~SizeType(0);
 | 
						|
 
 | 
						|
+template <typename Encoding, typename Allocator>
 | 
						|
+class GenericRegexSearch;
 | 
						|
+
 | 
						|
 //! Regular expression engine with subset of ECMAscript grammar.
 | 
						|
 /*!
 | 
						|
     Supported regular expression syntax:
 | 
						|
@@ -84,45 +109,29 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
 | 
						|
 template <typename Encoding, typename Allocator = CrtAllocator>
 | 
						|
 class GenericRegex {
 | 
						|
 public:
 | 
						|
+    typedef Encoding EncodingType;
 | 
						|
     typedef typename Encoding::Ch Ch;
 | 
						|
+    template <typename, typename> friend class GenericRegexSearch;
 | 
						|
 
 | 
						|
     GenericRegex(const Ch* source, Allocator* allocator = 0) : 
 | 
						|
-        states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), 
 | 
						|
-        stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
 | 
						|
+        ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), 
 | 
						|
+        states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), 
 | 
						|
+        anchorBegin_(), anchorEnd_()
 | 
						|
     {
 | 
						|
         GenericStringStream<Encoding> ss(source);
 | 
						|
-        DecodedStream<GenericStringStream<Encoding> > ds(ss);
 | 
						|
+        DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
 | 
						|
         Parse(ds);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    ~GenericRegex() {
 | 
						|
-        Allocator::Free(stateSet_);
 | 
						|
+    ~GenericRegex()
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_DELETE(ownAllocator_);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool IsValid() const {
 | 
						|
         return root_ != kRegexInvalidState;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    template <typename InputStream>
 | 
						|
-    bool Match(InputStream& is) const {
 | 
						|
-        return SearchWithAnchoring(is, true, true);
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    bool Match(const Ch* s) const {
 | 
						|
-        GenericStringStream<Encoding> is(s);
 | 
						|
-        return Match(is);
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    template <typename InputStream>
 | 
						|
-    bool Search(InputStream& is) const {
 | 
						|
-        return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
 | 
						|
-    }
 | 
						|
-
 | 
						|
-    bool Search(const Ch* s) const {
 | 
						|
-        GenericStringStream<Encoding> is(s);
 | 
						|
-        return Search(is);
 | 
						|
-    }
 | 
						|
-
 | 
						|
 private:
 | 
						|
     enum Operator {
 | 
						|
         kZeroOrOne,
 | 
						|
@@ -157,28 +166,6 @@ private:
 | 
						|
         SizeType minIndex;
 | 
						|
     };
 | 
						|
 
 | 
						|
-    template <typename SourceStream>
 | 
						|
-    class DecodedStream {
 | 
						|
-    public:
 | 
						|
-        DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
 | 
						|
-        unsigned Peek() { return codepoint_; }
 | 
						|
-        unsigned Take() {
 | 
						|
-            unsigned c = codepoint_;
 | 
						|
-            if (c) // No further decoding when '\0'
 | 
						|
-                Decode();
 | 
						|
-            return c;
 | 
						|
-        }
 | 
						|
-
 | 
						|
-    private:
 | 
						|
-        void Decode() {
 | 
						|
-            if (!Encoding::Decode(ss_, &codepoint_))
 | 
						|
-                codepoint_ = 0;
 | 
						|
-        }
 | 
						|
-
 | 
						|
-        SourceStream& ss_;
 | 
						|
-        unsigned codepoint_;
 | 
						|
-    };
 | 
						|
-
 | 
						|
     State& GetState(SizeType index) {
 | 
						|
         RAPIDJSON_ASSERT(index < stateCount_);
 | 
						|
         return states_.template Bottom<State>()[index];
 | 
						|
@@ -200,11 +187,10 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
-    void Parse(DecodedStream<InputStream>& ds) {
 | 
						|
-        Allocator allocator;
 | 
						|
-        Stack<Allocator> operandStack(&allocator, 256);     // Frag
 | 
						|
-        Stack<Allocator> operatorStack(&allocator, 256);    // Operator
 | 
						|
-        Stack<Allocator> atomCountStack(&allocator, 256);   // unsigned (Atom per parenthesis)
 | 
						|
+    void Parse(DecodedStream<InputStream, Encoding>& ds) {
 | 
						|
+        Stack<Allocator> operandStack(allocator_, 256);    // Frag
 | 
						|
+        Stack<Allocator> operatorStack(allocator_, 256);   // Operator
 | 
						|
+        Stack<Allocator> atomCountStack(allocator_, 256);  // unsigned (Atom per parenthesis)
 | 
						|
 
 | 
						|
         *atomCountStack.template Push<unsigned>() = 0;
 | 
						|
 
 | 
						|
@@ -301,6 +287,7 @@ private:
 | 
						|
                     if (!CharacterEscape(ds, &codepoint))
 | 
						|
                         return; // Unsupported escape character
 | 
						|
                     // fall through to default
 | 
						|
+                    RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
						|
 
 | 
						|
                 default: // Pattern character
 | 
						|
                     PushOperand(operandStack, codepoint);
 | 
						|
@@ -327,14 +314,6 @@ private:
 | 
						|
             printf("\n");
 | 
						|
 #endif
 | 
						|
         }
 | 
						|
-
 | 
						|
-        // Preallocate buffer for SearchWithAnchoring()
 | 
						|
-        RAPIDJSON_ASSERT(stateSet_ == 0);
 | 
						|
-        if (stateCount_ > 0) {
 | 
						|
-            stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
 | 
						|
-            state0_.template Reserve<SizeType>(stateCount_);
 | 
						|
-            state1_.template Reserve<SizeType>(stateCount_);
 | 
						|
-        }
 | 
						|
     }
 | 
						|
 
 | 
						|
     SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
 | 
						|
@@ -413,8 +392,7 @@ private:
 | 
						|
                 }
 | 
						|
                 return false;
 | 
						|
 
 | 
						|
-            default: 
 | 
						|
-                RAPIDJSON_ASSERT(op == kOneOrMore);
 | 
						|
+            case kOneOrMore:
 | 
						|
                 if (operandStack.GetSize() >= sizeof(Frag)) {
 | 
						|
                     Frag e = *operandStack.template Pop<Frag>(1);
 | 
						|
                     SizeType s = NewState(kRegexInvalidState, e.start, 0);
 | 
						|
@@ -423,6 +401,10 @@ private:
 | 
						|
                     return true;
 | 
						|
                 }
 | 
						|
                 return false;
 | 
						|
+
 | 
						|
+            default: 
 | 
						|
+                // syntax error (e.g. unclosed kLeftParenthesis)
 | 
						|
+                return false;
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -483,7 +465,7 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
-    bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
 | 
						|
+    bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
 | 
						|
         unsigned r = 0;
 | 
						|
         if (ds.Peek() < '0' || ds.Peek() > '9')
 | 
						|
             return false;
 | 
						|
@@ -497,7 +479,7 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
-    bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
 | 
						|
+    bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
 | 
						|
         bool isBegin = true;
 | 
						|
         bool negate = false;
 | 
						|
         int step = 0;
 | 
						|
@@ -535,6 +517,7 @@ private:
 | 
						|
                 else if (!CharacterEscape(ds, &codepoint))
 | 
						|
                     return false;
 | 
						|
                 // fall through to default
 | 
						|
+                RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
						|
 
 | 
						|
             default:
 | 
						|
                 switch (step) {
 | 
						|
@@ -544,6 +527,7 @@ private:
 | 
						|
                         break;
 | 
						|
                     }
 | 
						|
                     // fall through to step 0 for other characters
 | 
						|
+                    RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
						|
 
 | 
						|
                 case 0:
 | 
						|
                     {
 | 
						|
@@ -575,7 +559,7 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     template <typename InputStream>
 | 
						|
-    bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
 | 
						|
+    bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
 | 
						|
         unsigned codepoint;
 | 
						|
         switch (codepoint = ds.Take()) {
 | 
						|
             case '^':
 | 
						|
@@ -603,34 +587,95 @@ private:
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
+    Allocator* ownAllocator_;
 | 
						|
+    Allocator* allocator_;
 | 
						|
+    Stack<Allocator> states_;
 | 
						|
+    Stack<Allocator> ranges_;
 | 
						|
+    SizeType root_;
 | 
						|
+    SizeType stateCount_;
 | 
						|
+    SizeType rangeCount_;
 | 
						|
+
 | 
						|
+    static const unsigned kInfinityQuantifier = ~0u;
 | 
						|
+
 | 
						|
+    // For SearchWithAnchoring()
 | 
						|
+    bool anchorBegin_;
 | 
						|
+    bool anchorEnd_;
 | 
						|
+};
 | 
						|
+
 | 
						|
+template <typename RegexType, typename Allocator = CrtAllocator>
 | 
						|
+class GenericRegexSearch {
 | 
						|
+public:
 | 
						|
+    typedef typename RegexType::EncodingType Encoding;
 | 
						|
+    typedef typename Encoding::Ch Ch;
 | 
						|
+
 | 
						|
+    GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : 
 | 
						|
+        regex_(regex), allocator_(allocator), ownAllocator_(0),
 | 
						|
+        state0_(allocator, 0), state1_(allocator, 0), stateSet_()
 | 
						|
+    {
 | 
						|
+        RAPIDJSON_ASSERT(regex_.IsValid());
 | 
						|
+        if (!allocator_)
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
+        stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
 | 
						|
+        state0_.template Reserve<SizeType>(regex_.stateCount_);
 | 
						|
+        state1_.template Reserve<SizeType>(regex_.stateCount_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    ~GenericRegexSearch() {
 | 
						|
+        Allocator::Free(stateSet_);
 | 
						|
+        RAPIDJSON_DELETE(ownAllocator_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     template <typename InputStream>
 | 
						|
-    bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
 | 
						|
-        RAPIDJSON_ASSERT(IsValid());
 | 
						|
-        DecodedStream<InputStream> ds(is);
 | 
						|
+    bool Match(InputStream& is) {
 | 
						|
+        return SearchWithAnchoring(is, true, true);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    bool Match(const Ch* s) {
 | 
						|
+        GenericStringStream<Encoding> is(s);
 | 
						|
+        return Match(is);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    template <typename InputStream>
 | 
						|
+    bool Search(InputStream& is) {
 | 
						|
+        return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    bool Search(const Ch* s) {
 | 
						|
+        GenericStringStream<Encoding> is(s);
 | 
						|
+        return Search(is);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    typedef typename RegexType::State State;
 | 
						|
+    typedef typename RegexType::Range Range;
 | 
						|
+
 | 
						|
+    template <typename InputStream>
 | 
						|
+    bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
 | 
						|
+        DecodedStream<InputStream, Encoding> ds(is);
 | 
						|
 
 | 
						|
         state0_.Clear();
 | 
						|
         Stack<Allocator> *current = &state0_, *next = &state1_;
 | 
						|
         const size_t stateSetSize = GetStateSetSize();
 | 
						|
         std::memset(stateSet_, 0, stateSetSize);
 | 
						|
 
 | 
						|
-        bool matched = AddState(*current, root_);
 | 
						|
+        bool matched = AddState(*current, regex_.root_);
 | 
						|
         unsigned codepoint;
 | 
						|
         while (!current->Empty() && (codepoint = ds.Take()) != 0) {
 | 
						|
             std::memset(stateSet_, 0, stateSetSize);
 | 
						|
             next->Clear();
 | 
						|
             matched = false;
 | 
						|
             for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
 | 
						|
-                const State& sr = GetState(*s);
 | 
						|
+                const State& sr = regex_.GetState(*s);
 | 
						|
                 if (sr.codepoint == codepoint ||
 | 
						|
-                    sr.codepoint == kAnyCharacterClass || 
 | 
						|
-                    (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
 | 
						|
+                    sr.codepoint == RegexType::kAnyCharacterClass || 
 | 
						|
+                    (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
 | 
						|
                 {
 | 
						|
                     matched = AddState(*next, sr.out) || matched;
 | 
						|
                     if (!anchorEnd && matched)
 | 
						|
                         return true;
 | 
						|
                 }
 | 
						|
                 if (!anchorBegin)
 | 
						|
-                    AddState(*next, root_);
 | 
						|
+                    AddState(*next, regex_.root_);
 | 
						|
             }
 | 
						|
             internal::Swap(current, next);
 | 
						|
         }
 | 
						|
@@ -639,62 +684,55 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     size_t GetStateSetSize() const {
 | 
						|
-        return (stateCount_ + 31) / 32 * 4;
 | 
						|
+        return (regex_.stateCount_ + 31) / 32 * 4;
 | 
						|
     }
 | 
						|
 
 | 
						|
     // Return whether the added states is a match state
 | 
						|
-    bool AddState(Stack<Allocator>& l, SizeType index) const {
 | 
						|
+    bool AddState(Stack<Allocator>& l, SizeType index) {
 | 
						|
         RAPIDJSON_ASSERT(index != kRegexInvalidState);
 | 
						|
 
 | 
						|
-        const State& s = GetState(index);
 | 
						|
+        const State& s = regex_.GetState(index);
 | 
						|
         if (s.out1 != kRegexInvalidState) { // Split
 | 
						|
             bool matched = AddState(l, s.out);
 | 
						|
             return AddState(l, s.out1) || matched;
 | 
						|
         }
 | 
						|
-        else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
 | 
						|
-            stateSet_[index >> 5] |= (1 << (index & 31));
 | 
						|
+        else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
 | 
						|
+            stateSet_[index >> 5] |= (1u << (index & 31));
 | 
						|
             *l.template PushUnsafe<SizeType>() = index;
 | 
						|
         }
 | 
						|
         return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
 | 
						|
-        bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
 | 
						|
+        bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
 | 
						|
         while (rangeIndex != kRegexInvalidRange) {
 | 
						|
-            const Range& r = GetRange(rangeIndex);
 | 
						|
-            if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
 | 
						|
+            const Range& r = regex_.GetRange(rangeIndex);
 | 
						|
+            if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
 | 
						|
                 return yes;
 | 
						|
             rangeIndex = r.next;
 | 
						|
         }
 | 
						|
         return !yes;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    Stack<Allocator> states_;
 | 
						|
-    Stack<Allocator> ranges_;
 | 
						|
-    SizeType root_;
 | 
						|
-    SizeType stateCount_;
 | 
						|
-    SizeType rangeCount_;
 | 
						|
-
 | 
						|
-    static const unsigned kInfinityQuantifier = ~0u;
 | 
						|
-
 | 
						|
-    // For SearchWithAnchoring()
 | 
						|
-    uint32_t* stateSet_;        // allocated by states_.GetAllocator()
 | 
						|
-    mutable Stack<Allocator> state0_;
 | 
						|
-    mutable Stack<Allocator> state1_;
 | 
						|
-    bool anchorBegin_;
 | 
						|
-    bool anchorEnd_;
 | 
						|
+    const RegexType& regex_;
 | 
						|
+    Allocator* allocator_;
 | 
						|
+    Allocator* ownAllocator_;
 | 
						|
+    Stack<Allocator> state0_;
 | 
						|
+    Stack<Allocator> state1_;
 | 
						|
+    uint32_t* stateSet_;
 | 
						|
 };
 | 
						|
 
 | 
						|
 typedef GenericRegex<UTF8<> > Regex;
 | 
						|
+typedef GenericRegexSearch<Regex> RegexSearch;
 | 
						|
 
 | 
						|
 } // namespace internal
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
-#ifdef __clang__
 | 
						|
+#ifdef __GNUC__
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#if defined(__clang__) || defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/stack.h b/src/common/thirdparty/rapidjson/internal/stack.h
 | 
						|
index 022c9aab4..73abd706e 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/stack.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/stack.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -17,6 +17,7 @@
 | 
						|
 
 | 
						|
 #include "../allocators.h"
 | 
						|
 #include "swap.h"
 | 
						|
+#include <cstddef>
 | 
						|
 
 | 
						|
 #if defined(__clang__)
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
@@ -100,7 +101,7 @@ public:
 | 
						|
     void ShrinkToFit() { 
 | 
						|
         if (Empty()) {
 | 
						|
             // If the stack is empty, completely deallocate the memory.
 | 
						|
-            Allocator::Free(stack_);
 | 
						|
+            Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
 | 
						|
             stack_ = 0;
 | 
						|
             stackTop_ = 0;
 | 
						|
             stackEnd_ = 0;
 | 
						|
@@ -114,7 +115,7 @@ public:
 | 
						|
     template<typename T>
 | 
						|
     RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
 | 
						|
          // Expand the stack if needed
 | 
						|
-        if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
 | 
						|
+        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
 | 
						|
             Expand<T>(count);
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -126,7 +127,8 @@ public:
 | 
						|
 
 | 
						|
     template<typename T>
 | 
						|
     RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
 | 
						|
-        RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
 | 
						|
+        RAPIDJSON_ASSERT(stackTop_);
 | 
						|
+        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
 | 
						|
         T* ret = reinterpret_cast<T*>(stackTop_);
 | 
						|
         stackTop_ += sizeof(T) * count;
 | 
						|
         return ret;
 | 
						|
@@ -183,7 +185,7 @@ private:
 | 
						|
         size_t newCapacity;
 | 
						|
         if (stack_ == 0) {
 | 
						|
             if (!allocator_)
 | 
						|
-                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
             newCapacity = initialCapacity_;
 | 
						|
         } else {
 | 
						|
             newCapacity = GetCapacity();
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/strfunc.h b/src/common/thirdparty/rapidjson/internal/strfunc.h
 | 
						|
index de41d8f9c..b698a8f43 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/strfunc.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/strfunc.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -16,6 +16,7 @@
 | 
						|
 #define RAPIDJSON_INTERNAL_STRFUNC_H_
 | 
						|
 
 | 
						|
 #include "../stream.h"
 | 
						|
+#include <cwchar>
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 namespace internal {
 | 
						|
@@ -34,6 +35,30 @@ inline SizeType StrLen(const Ch* s) {
 | 
						|
     return SizeType(p - s);
 | 
						|
 }
 | 
						|
 
 | 
						|
+template <>
 | 
						|
+inline SizeType StrLen(const char* s) {
 | 
						|
+    return SizeType(std::strlen(s));
 | 
						|
+}
 | 
						|
+
 | 
						|
+template <>
 | 
						|
+inline SizeType StrLen(const wchar_t* s) {
 | 
						|
+    return SizeType(std::wcslen(s));
 | 
						|
+}
 | 
						|
+
 | 
						|
+//! Custom strcmpn() which works on different character types.
 | 
						|
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
 | 
						|
+    \param s1 Null-terminated input string.
 | 
						|
+    \param s2 Null-terminated input string.
 | 
						|
+    \return 0 if equal
 | 
						|
+*/
 | 
						|
+template<typename Ch>
 | 
						|
+inline int StrCmp(const Ch* s1, const Ch* s2) {
 | 
						|
+    RAPIDJSON_ASSERT(s1 != 0);
 | 
						|
+    RAPIDJSON_ASSERT(s2 != 0);
 | 
						|
+    while(*s1 && (*s1 == *s2)) { s1++; s2++; }
 | 
						|
+    return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
 | 
						|
+}
 | 
						|
+
 | 
						|
 //! Returns number of code points in a encoded string.
 | 
						|
 template<typename Encoding>
 | 
						|
 bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/strtod.h b/src/common/thirdparty/rapidjson/internal/strtod.h
 | 
						|
index 289c413b0..55f0e380b 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/strtod.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/strtod.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -19,6 +19,8 @@
 | 
						|
 #include "biginteger.h"
 | 
						|
 #include "diyfp.h"
 | 
						|
 #include "pow10.h"
 | 
						|
+#include <climits>
 | 
						|
+#include <limits>
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 namespace internal {
 | 
						|
@@ -126,46 +128,47 @@ inline bool StrtodFast(double d, int p, double* result) {
 | 
						|
 }
 | 
						|
 
 | 
						|
 // Compute an approximation and see if it is within 1/2 ULP
 | 
						|
-inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
 | 
						|
+template<typename Ch>
 | 
						|
+inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
 | 
						|
     uint64_t significand = 0;
 | 
						|
-    size_t i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    
 | 
						|
-    for (; i < length; i++) {
 | 
						|
+    int i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    
 | 
						|
+    for (; i < dLen; i++) {
 | 
						|
         if (significand  >  RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
 | 
						|
-            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
 | 
						|
+            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5')))
 | 
						|
             break;
 | 
						|
-        significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
 | 
						|
+        significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
 | 
						|
     }
 | 
						|
     
 | 
						|
-    if (i < length && decimals[i] >= '5') // Rounding
 | 
						|
+    if (i < dLen && decimals[i] >= Ch('5')) // Rounding
 | 
						|
         significand++;
 | 
						|
 
 | 
						|
-    size_t remaining = length - i;
 | 
						|
-    const unsigned kUlpShift = 3;
 | 
						|
-    const unsigned kUlp = 1 << kUlpShift;
 | 
						|
+    int remaining = dLen - i;
 | 
						|
+    const int kUlpShift = 3;
 | 
						|
+    const int kUlp = 1 << kUlpShift;
 | 
						|
     int64_t error = (remaining == 0) ? 0 : kUlp / 2;
 | 
						|
 
 | 
						|
     DiyFp v(significand, 0);
 | 
						|
     v = v.Normalize();
 | 
						|
     error <<= -v.e;
 | 
						|
 
 | 
						|
-    const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
 | 
						|
+    dExp += remaining;
 | 
						|
 
 | 
						|
     int actualExp;
 | 
						|
     DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
 | 
						|
     if (actualExp != dExp) {
 | 
						|
         static const DiyFp kPow10[] = {
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60),  // 10^1
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57),  // 10^2
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54),  // 10^3
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50),  // 10^4
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47),  // 10^5
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44),  // 10^6
 | 
						|
-            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40)   // 10^7
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60),  // 10^1
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57),  // 10^2
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54),  // 10^3
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50),  // 10^4
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47),  // 10^5
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44),  // 10^6
 | 
						|
+            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40)   // 10^7
 | 
						|
         };
 | 
						|
-        int  adjustment = dExp - actualExp - 1;
 | 
						|
-        RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
 | 
						|
-        v = v * kPow10[adjustment];
 | 
						|
-        if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
 | 
						|
+        int adjustment = dExp - actualExp;
 | 
						|
+        RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
 | 
						|
+        v = v * kPow10[adjustment - 1];
 | 
						|
+        if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
 | 
						|
             error += kUlp / 2;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -177,17 +180,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
 | 
						|
     v = v.Normalize();
 | 
						|
     error <<= oldExp - v.e;
 | 
						|
 
 | 
						|
-    const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
 | 
						|
-    unsigned precisionSize = 64 - effectiveSignificandSize;
 | 
						|
+    const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
 | 
						|
+    int precisionSize = 64 - effectiveSignificandSize;
 | 
						|
     if (precisionSize + kUlpShift >= 64) {
 | 
						|
-        unsigned scaleExp = (precisionSize + kUlpShift) - 63;
 | 
						|
+        int scaleExp = (precisionSize + kUlpShift) - 63;
 | 
						|
         v.f >>= scaleExp;
 | 
						|
         v.e += scaleExp; 
 | 
						|
-        error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
 | 
						|
+        error = (error >> scaleExp) + 1 + kUlp;
 | 
						|
         precisionSize -= scaleExp;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
 | 
						|
+    DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
 | 
						|
     const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
 | 
						|
     const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
 | 
						|
     if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
 | 
						|
@@ -203,9 +206,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
 | 
						|
     return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
 | 
						|
-    const BigInteger dInt(decimals, length);
 | 
						|
-    const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
 | 
						|
+template<typename Ch>
 | 
						|
+inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
 | 
						|
+    RAPIDJSON_ASSERT(dLen >= 0);
 | 
						|
+    const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
 | 
						|
     Double a(approx);
 | 
						|
     int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
 | 
						|
     if (cmp < 0)
 | 
						|
@@ -221,46 +225,66 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
 | 
						|
         return a.NextPositiveDouble();
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
 | 
						|
+template<typename Ch>
 | 
						|
+inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
 | 
						|
     RAPIDJSON_ASSERT(d >= 0.0);
 | 
						|
     RAPIDJSON_ASSERT(length >= 1);
 | 
						|
 
 | 
						|
-    double result;
 | 
						|
+    double result = 0.0;
 | 
						|
     if (StrtodFast(d, p, &result))
 | 
						|
         return result;
 | 
						|
 
 | 
						|
+    RAPIDJSON_ASSERT(length <= INT_MAX);
 | 
						|
+    int dLen = static_cast<int>(length);
 | 
						|
+
 | 
						|
+    RAPIDJSON_ASSERT(length >= decimalPosition);
 | 
						|
+    RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
 | 
						|
+    int dExpAdjust = static_cast<int>(length - decimalPosition);
 | 
						|
+
 | 
						|
+    RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
 | 
						|
+    int dExp = exp - dExpAdjust;
 | 
						|
+
 | 
						|
+    // Make sure length+dExp does not overflow
 | 
						|
+    RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
 | 
						|
+
 | 
						|
     // Trim leading zeros
 | 
						|
-    while (*decimals == '0' && length > 1) {
 | 
						|
-        length--;
 | 
						|
+    while (dLen > 0 && *decimals == '0') {
 | 
						|
+        dLen--;
 | 
						|
         decimals++;
 | 
						|
-        decimalPosition--;
 | 
						|
     }
 | 
						|
 
 | 
						|
     // Trim trailing zeros
 | 
						|
-    while (decimals[length - 1] == '0' && length > 1) {
 | 
						|
-        length--;
 | 
						|
-        decimalPosition--;
 | 
						|
-        exp++;
 | 
						|
+    while (dLen > 0 && decimals[dLen - 1] == '0') {
 | 
						|
+        dLen--;
 | 
						|
+        dExp++;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    if (dLen == 0) { // Buffer only contains zeros.
 | 
						|
+        return 0.0;
 | 
						|
     }
 | 
						|
 
 | 
						|
     // Trim right-most digits
 | 
						|
-    const int kMaxDecimalDigit = 780;
 | 
						|
-    if (static_cast<int>(length) > kMaxDecimalDigit) {
 | 
						|
-        int delta = (static_cast<int>(length) - kMaxDecimalDigit);
 | 
						|
-        exp += delta;
 | 
						|
-        decimalPosition -= static_cast<unsigned>(delta);
 | 
						|
-        length = kMaxDecimalDigit;
 | 
						|
+    const int kMaxDecimalDigit = 767 + 1;
 | 
						|
+    if (dLen > kMaxDecimalDigit) {
 | 
						|
+        dExp += dLen - kMaxDecimalDigit;
 | 
						|
+        dLen = kMaxDecimalDigit;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    // If too small, underflow to zero
 | 
						|
-    if (int(length) + exp < -324)
 | 
						|
+    // If too small, underflow to zero.
 | 
						|
+    // Any x <= 10^-324 is interpreted as zero.
 | 
						|
+    if (dLen + dExp <= -324)
 | 
						|
         return 0.0;
 | 
						|
 
 | 
						|
-    if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
 | 
						|
+    // If too large, overflow to infinity.
 | 
						|
+    // Any x >= 10^309 is interpreted as +infinity.
 | 
						|
+    if (dLen + dExp > 309)
 | 
						|
+        return std::numeric_limits<double>::infinity();
 | 
						|
+
 | 
						|
+    if (StrtodDiyFp(decimals, dLen, dExp, &result))
 | 
						|
         return result;
 | 
						|
 
 | 
						|
     // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
 | 
						|
-    return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
 | 
						|
+    return StrtodBigInteger(result, decimals, dLen, dExp);
 | 
						|
 }
 | 
						|
 
 | 
						|
 } // namespace internal
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/internal/swap.h b/src/common/thirdparty/rapidjson/internal/swap.h
 | 
						|
index 666e49f97..2cf92f93a 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/internal/swap.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/internal/swap.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 //
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/istreamwrapper.h b/src/common/thirdparty/rapidjson/istreamwrapper.h
 | 
						|
index f5fe28977..01437ec01 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/istreamwrapper.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/istreamwrapper.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -17,13 +17,12 @@
 | 
						|
 
 | 
						|
 #include "stream.h"
 | 
						|
 #include <iosfwd>
 | 
						|
+#include <ios>
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(padded)
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
 | 
						|
 #endif
 | 
						|
@@ -50,57 +49,71 @@ template <typename StreamType>
 | 
						|
 class BasicIStreamWrapper {
 | 
						|
 public:
 | 
						|
     typedef typename StreamType::char_type Ch;
 | 
						|
-    BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
 | 
						|
 
 | 
						|
-    Ch Peek() const { 
 | 
						|
-        typename StreamType::int_type c = stream_.peek();
 | 
						|
-        return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
 | 
						|
+    //! Constructor.
 | 
						|
+    /*!
 | 
						|
+        \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) { 
 | 
						|
+        Read();
 | 
						|
     }
 | 
						|
 
 | 
						|
-    Ch Take() { 
 | 
						|
-        typename StreamType::int_type c = stream_.get();
 | 
						|
-        if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
 | 
						|
-            count_++;
 | 
						|
-            return static_cast<Ch>(c);
 | 
						|
-        }
 | 
						|
-        else
 | 
						|
-            return '\0';
 | 
						|
+    //! Constructor.
 | 
						|
+    /*!
 | 
						|
+        \param stream stream opened for read.
 | 
						|
+        \param buffer user-supplied buffer.
 | 
						|
+        \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) { 
 | 
						|
+        RAPIDJSON_ASSERT(bufferSize >= 4);
 | 
						|
+        Read();
 | 
						|
     }
 | 
						|
 
 | 
						|
-    // tellg() may return -1 when failed. So we count by ourself.
 | 
						|
-    size_t Tell() const { return count_; }
 | 
						|
+    Ch Peek() const { return *current_; }
 | 
						|
+    Ch Take() { Ch c = *current_; Read(); return c; }
 | 
						|
+    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
 | 
						|
 
 | 
						|
-    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
						|
+    // Not implemented
 | 
						|
     void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
						|
-    void Flush() { RAPIDJSON_ASSERT(false); }
 | 
						|
+    void Flush() { RAPIDJSON_ASSERT(false); } 
 | 
						|
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
						|
     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
						|
 
 | 
						|
     // For encoding detection only.
 | 
						|
     const Ch* Peek4() const {
 | 
						|
-        RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
 | 
						|
-        int i;
 | 
						|
-        bool hasError = false;
 | 
						|
-        for (i = 0; i < 4; ++i) {
 | 
						|
-            typename StreamType::int_type c = stream_.get();
 | 
						|
-            if (c == StreamType::traits_type::eof()) {
 | 
						|
-                hasError = true;
 | 
						|
-                stream_.clear();
 | 
						|
-                break;
 | 
						|
-            }
 | 
						|
-            peekBuffer_[i] = static_cast<Ch>(c);
 | 
						|
-        }
 | 
						|
-        for (--i; i >= 0; --i)
 | 
						|
-            stream_.putback(peekBuffer_[i]);
 | 
						|
-        return !hasError ? peekBuffer_ : 0;
 | 
						|
+        return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
 | 
						|
     }
 | 
						|
 
 | 
						|
 private:
 | 
						|
+    BasicIStreamWrapper();
 | 
						|
     BasicIStreamWrapper(const BasicIStreamWrapper&);
 | 
						|
     BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
 | 
						|
 
 | 
						|
-    StreamType& stream_;
 | 
						|
-    size_t count_;  //!< Number of characters read. Note:
 | 
						|
-    mutable Ch peekBuffer_[4];
 | 
						|
+    void Read() {
 | 
						|
+        if (current_ < bufferLast_)
 | 
						|
+            ++current_;
 | 
						|
+        else if (!eof_) {
 | 
						|
+            count_ += readCount_;
 | 
						|
+            readCount_ = bufferSize_;
 | 
						|
+            bufferLast_ = buffer_ + readCount_ - 1;
 | 
						|
+            current_ = buffer_;
 | 
						|
+
 | 
						|
+            if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
 | 
						|
+                readCount_ = static_cast<size_t>(stream_.gcount());
 | 
						|
+                *(bufferLast_ = buffer_ + readCount_) = '\0';
 | 
						|
+                eof_ = true;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    StreamType &stream_;
 | 
						|
+    Ch peekBuffer_[4], *buffer_;
 | 
						|
+    size_t bufferSize_;
 | 
						|
+    Ch *bufferLast_;
 | 
						|
+    Ch *current_;
 | 
						|
+    size_t readCount_;
 | 
						|
+    size_t count_;  //!< Number of characters read
 | 
						|
+    bool eof_;
 | 
						|
 };
 | 
						|
 
 | 
						|
 typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/memorybuffer.h b/src/common/thirdparty/rapidjson/memorybuffer.h
 | 
						|
index 39bee1dec..ffbc41ed1 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/memorybuffer.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/memorybuffer.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/memorystream.h b/src/common/thirdparty/rapidjson/memorystream.h
 | 
						|
index 1d71d8a4f..77af6c999 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/memorystream.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/memorystream.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/ostreamwrapper.h b/src/common/thirdparty/rapidjson/ostreamwrapper.h
 | 
						|
index 6f4667c08..11ed4d33f 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/ostreamwrapper.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/ostreamwrapper.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/pointer.h b/src/common/thirdparty/rapidjson/pointer.h
 | 
						|
index 0206ac1c8..05b1704dd 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/pointer.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/pointer.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -16,14 +16,14 @@
 | 
						|
 #define RAPIDJSON_POINTER_H_
 | 
						|
 
 | 
						|
 #include "document.h"
 | 
						|
+#include "uri.h"
 | 
						|
 #include "internal/itoa.h"
 | 
						|
+#include "error/error.h" // PointerParseErrorCode
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(switch-enum)
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
 #endif
 | 
						|
@@ -32,19 +32,6 @@ RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 
 | 
						|
 static const SizeType kPointerInvalidIndex = ~SizeType(0);  //!< Represents an invalid index in GenericPointer::Token
 | 
						|
 
 | 
						|
-//! Error code of parsing.
 | 
						|
-/*! \ingroup RAPIDJSON_ERRORS
 | 
						|
-    \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
 | 
						|
-*/
 | 
						|
-enum PointerParseErrorCode {
 | 
						|
-    kPointerParseErrorNone = 0,                     //!< The parse is successful
 | 
						|
-
 | 
						|
-    kPointerParseErrorTokenMustBeginWithSolidus,    //!< A token must begin with a '/'
 | 
						|
-    kPointerParseErrorInvalidEscape,                //!< Invalid escape
 | 
						|
-    kPointerParseErrorInvalidPercentEncoding,       //!< Invalid percent encoding in URI fragment
 | 
						|
-    kPointerParseErrorCharacterMustPercentEncode    //!< A character must percent encoded in URI fragment
 | 
						|
-};
 | 
						|
-
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // GenericPointer
 | 
						|
 
 | 
						|
@@ -70,10 +57,10 @@ enum PointerParseErrorCode {
 | 
						|
     supplied tokens eliminates these.
 | 
						|
 
 | 
						|
     GenericPointer depends on GenericDocument and GenericValue.
 | 
						|
-    
 | 
						|
+
 | 
						|
     \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
 | 
						|
     \tparam Allocator The allocator type for allocating memory for internal representation.
 | 
						|
-    
 | 
						|
+
 | 
						|
     \note GenericPointer uses same encoding of ValueType.
 | 
						|
     However, Allocator of GenericPointer is independent of Allocator of Value.
 | 
						|
 */
 | 
						|
@@ -82,8 +69,10 @@ class GenericPointer {
 | 
						|
 public:
 | 
						|
     typedef typename ValueType::EncodingType EncodingType;  //!< Encoding type from Value
 | 
						|
     typedef typename ValueType::Ch Ch;                      //!< Character type from Value
 | 
						|
+    typedef GenericUri<ValueType, Allocator> UriType;
 | 
						|
 
 | 
						|
-    //! A token is the basic units of internal representation.
 | 
						|
+
 | 
						|
+  //! A token is the basic units of internal representation.
 | 
						|
     /*!
 | 
						|
         A JSON pointer string representation "/foo/123" is parsed to two tokens: 
 | 
						|
         "foo" and 123. 123 will be represented in both numeric form and string form.
 | 
						|
@@ -165,7 +154,12 @@ public:
 | 
						|
     GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
 | 
						|
 
 | 
						|
     //! Copy constructor.
 | 
						|
-    GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
 | 
						|
+    GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
 | 
						|
+        *this = rhs;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Copy constructor.
 | 
						|
+    GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
 | 
						|
         *this = rhs;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -197,6 +191,36 @@ public:
 | 
						|
         return *this;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    //! Swap the content of this pointer with an other.
 | 
						|
+    /*!
 | 
						|
+        \param other The pointer to swap with.
 | 
						|
+        \note Constant complexity.
 | 
						|
+    */
 | 
						|
+    GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
 | 
						|
+        internal::Swap(allocator_, other.allocator_);
 | 
						|
+        internal::Swap(ownAllocator_, other.ownAllocator_);
 | 
						|
+        internal::Swap(nameBuffer_, other.nameBuffer_);
 | 
						|
+        internal::Swap(tokens_, other.tokens_);
 | 
						|
+        internal::Swap(tokenCount_, other.tokenCount_);
 | 
						|
+        internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
 | 
						|
+        internal::Swap(parseErrorCode_, other.parseErrorCode_);
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! free-standing swap function helper
 | 
						|
+    /*!
 | 
						|
+        Helper function to enable support for common swap implementation pattern based on \c std::swap:
 | 
						|
+        \code
 | 
						|
+        void swap(MyClass& a, MyClass& b) {
 | 
						|
+            using std::swap;
 | 
						|
+            swap(a.pointer, b.pointer);
 | 
						|
+            // ...
 | 
						|
+        }
 | 
						|
+        \endcode
 | 
						|
+        \see Swap()
 | 
						|
+     */
 | 
						|
+    friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
 | 
						|
+
 | 
						|
     //@}
 | 
						|
 
 | 
						|
     //!@name Append token
 | 
						|
@@ -240,7 +264,7 @@ public:
 | 
						|
     template <typename T>
 | 
						|
     RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
 | 
						|
     Append(T* name, Allocator* allocator = 0) const {
 | 
						|
-        return Append(name, StrLen(name), allocator);
 | 
						|
+        return Append(name, internal::StrLen(name), allocator);
 | 
						|
     }
 | 
						|
 
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
@@ -274,7 +298,7 @@ public:
 | 
						|
         else {
 | 
						|
             Ch name[21];
 | 
						|
             for (size_t i = 0; i <= length; i++)
 | 
						|
-                name[i] = buffer[i];
 | 
						|
+                name[i] = static_cast<Ch>(buffer[i]);
 | 
						|
             Token token = { name, length, index };
 | 
						|
             return Append(token, allocator);
 | 
						|
         }
 | 
						|
@@ -353,6 +377,33 @@ public:
 | 
						|
     */
 | 
						|
     bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
 | 
						|
 
 | 
						|
+    //! Less than operator.
 | 
						|
+    /*!
 | 
						|
+        \note Invalid pointers are always greater than valid ones.
 | 
						|
+    */
 | 
						|
+    bool operator<(const GenericPointer& rhs) const {
 | 
						|
+        if (!IsValid())
 | 
						|
+            return false;
 | 
						|
+        if (!rhs.IsValid())
 | 
						|
+            return true;
 | 
						|
+
 | 
						|
+        if (tokenCount_ != rhs.tokenCount_)
 | 
						|
+            return tokenCount_ < rhs.tokenCount_;
 | 
						|
+
 | 
						|
+        for (size_t i = 0; i < tokenCount_; i++) {
 | 
						|
+            if (tokens_[i].index != rhs.tokens_[i].index)
 | 
						|
+                return tokens_[i].index < rhs.tokens_[i].index;
 | 
						|
+
 | 
						|
+            if (tokens_[i].length != rhs.tokens_[i].length)
 | 
						|
+                return tokens_[i].length < rhs.tokens_[i].length;
 | 
						|
+
 | 
						|
+            if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
 | 
						|
+                return cmp < 0;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        return false;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     //@}
 | 
						|
 
 | 
						|
     //!@name Stringify
 | 
						|
@@ -428,10 +479,11 @@ public:
 | 
						|
                     v = &((*v)[t->index]);
 | 
						|
                 }
 | 
						|
                 else {
 | 
						|
-                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
 | 
						|
+                    typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
 | 
						|
                     if (m == v->MemberEnd()) {
 | 
						|
                         v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
 | 
						|
-                        v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
 | 
						|
+                        m = v->MemberEnd();
 | 
						|
+                        v = &(--m)->value; // Assumes AddMember() appends at the end
 | 
						|
                         exist = false;
 | 
						|
                     }
 | 
						|
                     else
 | 
						|
@@ -459,6 +511,70 @@ public:
 | 
						|
 
 | 
						|
     //@}
 | 
						|
 
 | 
						|
+    //!@name Compute URI
 | 
						|
+    //@{
 | 
						|
+
 | 
						|
+    //! Compute the in-scope URI for a subtree.
 | 
						|
+    //  For use with JSON pointers into JSON schema documents.
 | 
						|
+    /*!
 | 
						|
+        \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
 | 
						|
+        \param rootUri Root URI
 | 
						|
+        \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
 | 
						|
+        \param allocator Allocator for Uris
 | 
						|
+        \return Uri if it can be resolved. Otherwise null.
 | 
						|
+
 | 
						|
+        \note
 | 
						|
+        There are only 3 situations when a URI cannot be resolved:
 | 
						|
+        1. A value in the path is not an array nor object.
 | 
						|
+        2. An object value does not contain the token.
 | 
						|
+        3. A token is out of range of an array value.
 | 
						|
+
 | 
						|
+        Use unresolvedTokenIndex to retrieve the token index.
 | 
						|
+    */
 | 
						|
+    UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
 | 
						|
+        static const Ch kIdString[] = { 'i', 'd', '\0' };
 | 
						|
+        static const ValueType kIdValue(kIdString, 2);
 | 
						|
+        UriType base = UriType(rootUri, allocator);
 | 
						|
+        RAPIDJSON_ASSERT(IsValid());
 | 
						|
+        ValueType* v = &root;
 | 
						|
+        for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
 | 
						|
+            switch (v->GetType()) {
 | 
						|
+                case kObjectType:
 | 
						|
+                {
 | 
						|
+                    // See if we have an id, and if so resolve with the current base
 | 
						|
+                    typename ValueType::MemberIterator m = v->FindMember(kIdValue);
 | 
						|
+                    if (m != v->MemberEnd() && (m->value).IsString()) {
 | 
						|
+                        UriType here = UriType(m->value, allocator).Resolve(base, allocator);
 | 
						|
+                        base = here;
 | 
						|
+                    }
 | 
						|
+                    m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
 | 
						|
+                    if (m == v->MemberEnd())
 | 
						|
+                        break;
 | 
						|
+                    v = &m->value;
 | 
						|
+                }
 | 
						|
+                  continue;
 | 
						|
+                case kArrayType:
 | 
						|
+                    if (t->index == kPointerInvalidIndex || t->index >= v->Size())
 | 
						|
+                        break;
 | 
						|
+                    v = &((*v)[t->index]);
 | 
						|
+                    continue;
 | 
						|
+                default:
 | 
						|
+                    break;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            // Error: unresolved token
 | 
						|
+            if (unresolvedTokenIndex)
 | 
						|
+                *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
 | 
						|
+            return UriType(allocator);
 | 
						|
+        }
 | 
						|
+        return base;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
 | 
						|
+      return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+
 | 
						|
     //!@name Query value
 | 
						|
     //@{
 | 
						|
 
 | 
						|
@@ -483,7 +599,7 @@ public:
 | 
						|
             switch (v->GetType()) {
 | 
						|
             case kObjectType:
 | 
						|
                 {
 | 
						|
-                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
 | 
						|
+                    typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
 | 
						|
                     if (m == v->MemberEnd())
 | 
						|
                         break;
 | 
						|
                     v = &m->value;
 | 
						|
@@ -532,14 +648,14 @@ public:
 | 
						|
     */
 | 
						|
     ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
 | 
						|
         bool alreadyExist;
 | 
						|
-        Value& v = Create(root, allocator, &alreadyExist);
 | 
						|
+        ValueType& v = Create(root, allocator, &alreadyExist);
 | 
						|
         return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Query a value in a subtree with default null-terminated string.
 | 
						|
     ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
 | 
						|
         bool alreadyExist;
 | 
						|
-        Value& v = Create(root, allocator, &alreadyExist);
 | 
						|
+        ValueType& v = Create(root, allocator, &alreadyExist);
 | 
						|
         return alreadyExist ? v : v.SetString(defaultValue, allocator);
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -547,7 +663,7 @@ public:
 | 
						|
     //! Query a value in a subtree with default std::basic_string.
 | 
						|
     ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
 | 
						|
         bool alreadyExist;
 | 
						|
-        Value& v = Create(root, allocator, &alreadyExist);
 | 
						|
+        ValueType& v = Create(root, allocator, &alreadyExist);
 | 
						|
         return alreadyExist ? v : v.SetString(defaultValue, allocator);
 | 
						|
     }
 | 
						|
 #endif
 | 
						|
@@ -573,7 +689,7 @@ public:
 | 
						|
     ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
 | 
						|
         return GetWithDefault(document, defaultValue, document.GetAllocator());
 | 
						|
     }
 | 
						|
-    
 | 
						|
+
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
     //! Query a value in a document with default std::basic_string.
 | 
						|
     template <typename stackAllocator>
 | 
						|
@@ -719,7 +835,7 @@ public:
 | 
						|
             switch (v->GetType()) {
 | 
						|
             case kObjectType:
 | 
						|
                 {
 | 
						|
-                    typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
 | 
						|
+                    typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
 | 
						|
                     if (m == v->MemberEnd())
 | 
						|
                         return false;
 | 
						|
                     v = &m->value;
 | 
						|
@@ -758,7 +874,7 @@ private:
 | 
						|
     */
 | 
						|
     Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
 | 
						|
         if (!allocator_) // allocator is independently owned.
 | 
						|
-            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
 
 | 
						|
         size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
 | 
						|
         for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
 | 
						|
@@ -806,7 +922,7 @@ private:
 | 
						|
 
 | 
						|
         // Create own allocator if user did not supply.
 | 
						|
         if (!allocator_)
 | 
						|
-            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
 
 | 
						|
         // Count number of '/' as tokenCount
 | 
						|
         tokenCount_ = 0;
 | 
						|
@@ -867,7 +983,7 @@ private:
 | 
						|
                 }
 | 
						|
 
 | 
						|
                 i++;
 | 
						|
-                
 | 
						|
+
 | 
						|
                 // Escaping "~0" -> '~', "~1" -> '/'
 | 
						|
                 if (c == '~') {
 | 
						|
                     if (i < length) {
 | 
						|
@@ -1029,8 +1145,8 @@ private:
 | 
						|
             unsigned char u = static_cast<unsigned char>(c);
 | 
						|
             static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 | 
						|
             os_.Put('%');
 | 
						|
-            os_.Put(hexDigits[u >> 4]);
 | 
						|
-            os_.Put(hexDigits[u & 15]);
 | 
						|
+            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
 | 
						|
+            os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
 | 
						|
         }
 | 
						|
     private:
 | 
						|
         OutputStream& os_;
 | 
						|
@@ -1347,11 +1463,7 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
-#ifdef __clang__
 | 
						|
-RAPIDJSON_DIAG_POP
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#if defined(__clang__) || defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/prettywriter.h b/src/common/thirdparty/rapidjson/prettywriter.h
 | 
						|
index c6f0216e9..fe45df1d1 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/prettywriter.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/prettywriter.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -22,6 +22,11 @@ RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(effc++)
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+#if defined(__clang__)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 
 | 
						|
 //! Combination of PrettyWriter format flags.
 | 
						|
@@ -34,7 +39,7 @@ enum PrettyFormatOptions {
 | 
						|
 
 | 
						|
 //! Writer with indentation and spacing.
 | 
						|
 /*!
 | 
						|
-    \tparam OutputStream Type of ouptut os.
 | 
						|
+    \tparam OutputStream Type of output os.
 | 
						|
     \tparam SourceEncoding Encoding of source string.
 | 
						|
     \tparam TargetEncoding Encoding of output stream.
 | 
						|
     \tparam StackAllocator Type of allocator for allocating memory of stack.
 | 
						|
@@ -42,7 +47,7 @@ enum PrettyFormatOptions {
 | 
						|
 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
 | 
						|
 class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
 | 
						|
 public:
 | 
						|
-    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
 | 
						|
+    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
 | 
						|
     typedef typename Base::Ch Ch;
 | 
						|
 
 | 
						|
     //! Constructor
 | 
						|
@@ -55,7 +60,12 @@ public:
 | 
						|
 
 | 
						|
 
 | 
						|
     explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
 | 
						|
-        Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
 | 
						|
+        Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
+    PrettyWriter(PrettyWriter&& rhs) :
 | 
						|
+        Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
 | 
						|
+#endif
 | 
						|
 
 | 
						|
     //! Set custom indentation.
 | 
						|
     /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
 | 
						|
@@ -82,26 +92,26 @@ public:
 | 
						|
     */
 | 
						|
     //@{
 | 
						|
 
 | 
						|
-    bool Null()                 { PrettyPrefix(kNullType);   return Base::WriteNull(); }
 | 
						|
-    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
 | 
						|
-    bool Int(int i)             { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
 | 
						|
-    bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
 | 
						|
-    bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
 | 
						|
-    bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::WriteUint64(u64);  }
 | 
						|
-    bool Double(double d)       { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
 | 
						|
+    bool Null()                 { PrettyPrefix(kNullType);   return Base::EndValue(Base::WriteNull()); }
 | 
						|
+    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
 | 
						|
+    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) {
 | 
						|
         RAPIDJSON_ASSERT(str != 0);
 | 
						|
         (void)copy;
 | 
						|
         PrettyPrefix(kNumberType);
 | 
						|
-        return Base::WriteString(str, length);
 | 
						|
+        return Base::EndValue(Base::WriteString(str, length));
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool String(const Ch* str, SizeType length, bool copy = false) {
 | 
						|
         RAPIDJSON_ASSERT(str != 0);
 | 
						|
         (void)copy;
 | 
						|
         PrettyPrefix(kStringType);
 | 
						|
-        return Base::WriteString(str, length);
 | 
						|
+        return Base::EndValue(Base::WriteString(str, length));
 | 
						|
     }
 | 
						|
 
 | 
						|
 #if RAPIDJSON_HAS_STDSTRING
 | 
						|
@@ -126,19 +136,21 @@ public:
 | 
						|
 	
 | 
						|
     bool EndObject(SizeType memberCount = 0) {
 | 
						|
         (void)memberCount;
 | 
						|
-        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
 | 
						|
-        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
 | 
						|
+        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
 | 
						|
+        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
 | 
						|
+        RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
 | 
						|
+       
 | 
						|
         bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
 | 
						|
 
 | 
						|
         if (!empty) {
 | 
						|
             Base::os_->Put('\n');
 | 
						|
             WriteIndent();
 | 
						|
         }
 | 
						|
-        bool ret = Base::WriteEndObject();
 | 
						|
+        bool ret = Base::EndValue(Base::WriteEndObject());
 | 
						|
         (void)ret;
 | 
						|
         RAPIDJSON_ASSERT(ret == true);
 | 
						|
         if (Base::level_stack_.Empty()) // end of json text
 | 
						|
-            Base::os_->Flush();
 | 
						|
+            Base::Flush();
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -158,11 +170,11 @@ public:
 | 
						|
             Base::os_->Put('\n');
 | 
						|
             WriteIndent();
 | 
						|
         }
 | 
						|
-        bool ret = Base::WriteEndArray();
 | 
						|
+        bool ret = Base::EndValue(Base::WriteEndArray());
 | 
						|
         (void)ret;
 | 
						|
         RAPIDJSON_ASSERT(ret == true);
 | 
						|
         if (Base::level_stack_.Empty()) // end of json text
 | 
						|
-            Base::os_->Flush();
 | 
						|
+            Base::Flush();
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -189,7 +201,7 @@ public:
 | 
						|
     bool RawValue(const Ch* json, size_t length, Type type) {
 | 
						|
         RAPIDJSON_ASSERT(json != 0);
 | 
						|
         PrettyPrefix(type);
 | 
						|
-        return Base::WriteRawValue(json, length);
 | 
						|
+        return Base::EndValue(Base::WriteRawValue(json, length));
 | 
						|
     }
 | 
						|
 
 | 
						|
 protected:
 | 
						|
@@ -239,7 +251,7 @@ protected:
 | 
						|
 
 | 
						|
     void WriteIndent()  {
 | 
						|
         size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
 | 
						|
-        PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
 | 
						|
+        PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
 | 
						|
     }
 | 
						|
 
 | 
						|
     Ch indentChar_;
 | 
						|
@@ -254,6 +266,10 @@ private:
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
+#if defined(__clang__)
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #ifdef __GNUC__
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/rapidjson.h b/src/common/thirdparty/rapidjson/rapidjson.h
 | 
						|
index d5b7630b5..5ea694795 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/rapidjson.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/rapidjson.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_RAPIDJSON_H_
 | 
						|
@@ -17,7 +17,7 @@
 | 
						|
 
 | 
						|
 /*!\file rapidjson.h
 | 
						|
     \brief common definitions and configuration
 | 
						|
-    
 | 
						|
+
 | 
						|
     \see RAPIDJSON_CONFIG
 | 
						|
  */
 | 
						|
 
 | 
						|
@@ -26,7 +26,7 @@
 | 
						|
 
 | 
						|
     Some RapidJSON features are configurable to adapt the library to a wide
 | 
						|
     variety of platforms, environments and usage scenarios.  Most of the
 | 
						|
-    features can be configured in terms of overriden or predefined
 | 
						|
+    features can be configured in terms of overridden or predefined
 | 
						|
     preprocessor macros at compile-time.
 | 
						|
 
 | 
						|
     Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
 | 
						|
@@ -49,6 +49,11 @@
 | 
						|
 // token stringification
 | 
						|
 #define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
 | 
						|
 #define RAPIDJSON_DO_STRINGIFY(x) #x
 | 
						|
+
 | 
						|
+// token concatenation
 | 
						|
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
 | 
						|
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
 | 
						|
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
 | 
						|
 //!@endcond
 | 
						|
 
 | 
						|
 /*! \def RAPIDJSON_MAJOR_VERSION
 | 
						|
@@ -119,6 +124,19 @@
 | 
						|
 #define RAPIDJSON_NAMESPACE_END }
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// __cplusplus macro
 | 
						|
+
 | 
						|
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER)
 | 
						|
+#define RAPIDJSON_CPLUSPLUS _MSVC_LANG
 | 
						|
+#else
 | 
						|
+#define RAPIDJSON_CPLUSPLUS __cplusplus
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+//!@endcond
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_HAS_STDSTRING
 | 
						|
 
 | 
						|
@@ -144,6 +162,24 @@
 | 
						|
 #include <string>
 | 
						|
 #endif // RAPIDJSON_HAS_STDSTRING
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief Enable RapidJSON support for object members handling in a \c std::multimap
 | 
						|
+
 | 
						|
+    By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
 | 
						|
+    members are stored in a \c std::multimap for faster lookup and deletion times, a
 | 
						|
+    trade off with a slightly slower insertion time and a small object allocat(or)ed
 | 
						|
+    memory overhead.
 | 
						|
+
 | 
						|
+    \hideinitializer
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_USE_MEMBERSMAP
 | 
						|
+#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_NO_INT64DEFINE
 | 
						|
 
 | 
						|
@@ -159,7 +195,7 @@
 | 
						|
 */
 | 
						|
 #ifndef RAPIDJSON_NO_INT64DEFINE
 | 
						|
 //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
-#if defined(_MSC_VER) && (_MSC_VER < 1800)	// Visual Studio 2013
 | 
						|
+#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
 | 
						|
 #include "msinttypes/stdint.h"
 | 
						|
 #include "msinttypes/inttypes.h"
 | 
						|
 #else
 | 
						|
@@ -214,7 +250,7 @@
 | 
						|
 #    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 | 
						|
 #      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
						|
 #    else
 | 
						|
-#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
 | 
						|
+#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
						|
 #    endif // __BYTE_ORDER__
 | 
						|
 // Detect with GLIBC's endian.h
 | 
						|
 #  elif defined(__GLIBC__)
 | 
						|
@@ -224,7 +260,7 @@
 | 
						|
 #    elif (__BYTE_ORDER == __BIG_ENDIAN)
 | 
						|
 #      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
						|
 #    else
 | 
						|
-#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
 | 
						|
+#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
						|
 #   endif // __GLIBC__
 | 
						|
 // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
 | 
						|
 #  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
 | 
						|
@@ -236,14 +272,12 @@
 | 
						|
 #    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__)
 | 
						|
 #    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
						|
-#  elif defined(_MSC_VER) && defined(_M_ARM)
 | 
						|
-#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
						|
-#  elif defined(_MSC_VER) && defined(_M_ARM64)
 | 
						|
+#  elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
 | 
						|
 #    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
						|
 #  elif defined(RAPIDJSON_DOXYGEN_RUNNING)
 | 
						|
 #    define RAPIDJSON_ENDIAN
 | 
						|
 #  else
 | 
						|
-#    error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.   
 | 
						|
+#    error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
						|
 #  endif
 | 
						|
 #endif // RAPIDJSON_ENDIAN
 | 
						|
 
 | 
						|
@@ -266,16 +300,11 @@
 | 
						|
 /*! \ingroup RAPIDJSON_CONFIG
 | 
						|
     \param x pointer to align
 | 
						|
 
 | 
						|
-    Some machines require strict data alignment. Currently the default uses 4 bytes
 | 
						|
-    alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
 | 
						|
+    Some machines require strict data alignment. The default is 8 bytes.
 | 
						|
     User can customize by defining the RAPIDJSON_ALIGN function macro.
 | 
						|
 */
 | 
						|
 #ifndef RAPIDJSON_ALIGN
 | 
						|
-#if RAPIDJSON_64BIT == 1
 | 
						|
-#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
 | 
						|
-#else
 | 
						|
-#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
 | 
						|
-#endif
 | 
						|
+#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
@@ -322,17 +351,17 @@
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
-// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
 | 
						|
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
 | 
						|
 
 | 
						|
 /*! \def RAPIDJSON_SIMD
 | 
						|
     \ingroup RAPIDJSON_CONFIG
 | 
						|
-    \brief Enable SSE2/SSE4.2 optimization.
 | 
						|
+    \brief Enable SSE2/SSE4.2/Neon optimization.
 | 
						|
 
 | 
						|
     RapidJSON supports optimized implementations for some parsing operations
 | 
						|
-    based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
 | 
						|
-    processors.
 | 
						|
+    based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
 | 
						|
+    or ARM compatible processors.
 | 
						|
 
 | 
						|
-    To enable these optimizations, two different symbols can be defined;
 | 
						|
+    To enable these optimizations, three different symbols can be defined;
 | 
						|
     \code
 | 
						|
     // Enable SSE2 optimization.
 | 
						|
     #define RAPIDJSON_SSE2
 | 
						|
@@ -341,13 +370,17 @@
 | 
						|
     #define RAPIDJSON_SSE42
 | 
						|
     \endcode
 | 
						|
 
 | 
						|
-    \c RAPIDJSON_SSE42 takes precedence, if both are defined.
 | 
						|
+    // Enable ARM Neon optimization.
 | 
						|
+    #define RAPIDJSON_NEON
 | 
						|
+    \endcode
 | 
						|
+
 | 
						|
+    \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
 | 
						|
 
 | 
						|
     If any of these symbols is defined, RapidJSON defines the macro
 | 
						|
     \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
 | 
						|
 */
 | 
						|
 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
 | 
						|
-    || defined(RAPIDJSON_DOXYGEN_RUNNING)
 | 
						|
+    || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
 | 
						|
 #define RAPIDJSON_SIMD
 | 
						|
 #endif
 | 
						|
 
 | 
						|
@@ -407,7 +440,15 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_STATIC_ASSERT
 | 
						|
 
 | 
						|
-// Adopt from boost
 | 
						|
+// Prefer C++11 static_assert, if available
 | 
						|
+#ifndef RAPIDJSON_STATIC_ASSERT
 | 
						|
+#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
 | 
						|
+#define RAPIDJSON_STATIC_ASSERT(x) \
 | 
						|
+   static_assert(x, RAPIDJSON_STRINGIFY(x))
 | 
						|
+#endif // C++11
 | 
						|
+#endif // RAPIDJSON_STATIC_ASSERT
 | 
						|
+
 | 
						|
+// Adopt C++03 implementation from boost
 | 
						|
 #ifndef RAPIDJSON_STATIC_ASSERT
 | 
						|
 #ifndef __clang__
 | 
						|
 //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
@@ -415,14 +456,10 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 template <bool x> struct STATIC_ASSERTION_FAILURE;
 | 
						|
 template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
 | 
						|
-template<int x> struct StaticAssertTest {};
 | 
						|
+template <size_t x> struct StaticAssertTest {};
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
-#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
 | 
						|
-#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
 | 
						|
-#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
 | 
						|
-
 | 
						|
-#if defined(__GNUC__)
 | 
						|
+#if defined(__GNUC__) || defined(__clang__)
 | 
						|
 #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
 | 
						|
 #else
 | 
						|
 #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 
 | 
						|
@@ -440,7 +477,7 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
     typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
 | 
						|
       sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
 | 
						|
     RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
 | 
						|
-#endif
 | 
						|
+#endif // RAPIDJSON_STATIC_ASSERT
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
 | 
						|
@@ -476,7 +513,7 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
 //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
 
 | 
						|
-#define RAPIDJSON_MULTILINEMACRO_BEGIN do {  
 | 
						|
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
 | 
						|
 #define RAPIDJSON_MULTILINEMACRO_END \
 | 
						|
 } while((void)0, 0)
 | 
						|
 
 | 
						|
@@ -484,6 +521,12 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 #define RAPIDJSON_VERSION_CODE(x,y,z) \
 | 
						|
   (((x)*100000) + ((y)*100) + (z))
 | 
						|
 
 | 
						|
+#if defined(__has_builtin)
 | 
						|
+#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
 | 
						|
+#else
 | 
						|
+#define RAPIDJSON_HAS_BUILTIN(x) 0
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
 | 
						|
 
 | 
						|
@@ -529,16 +572,23 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // C++11 features
 | 
						|
 
 | 
						|
+#ifndef RAPIDJSON_HAS_CXX11
 | 
						|
+#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
-#if defined(__clang__)
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
						|
+#elif defined(__clang__)
 | 
						|
 #if __has_feature(cxx_rvalue_references) && \
 | 
						|
-    (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
 | 
						|
+    (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
						|
 #else
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
 | 
						|
 #endif
 | 
						|
 #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__))
 | 
						|
 
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
						|
 #else
 | 
						|
@@ -546,46 +596,120 @@ RAPIDJSON_NAMESPACE_END
 | 
						|
 #endif
 | 
						|
 #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
 
 | 
						|
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
						|
+#include <utility> // std::move
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 #ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
						|
-#if defined(__clang__)
 | 
						|
+#if RAPIDJSON_HAS_CXX11
 | 
						|
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
 | 
						|
+#elif defined(__clang__)
 | 
						|
 #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__))
 | 
						|
-//    (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
 | 
						|
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
						|
+    (defined(_MSC_VER) && _MSC_VER >= 1900) || \
 | 
						|
+    (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
 | 
						|
 #define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
 | 
						|
 #else
 | 
						|
 #define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
 | 
						|
 #endif
 | 
						|
 #endif
 | 
						|
+#ifndef RAPIDJSON_NOEXCEPT
 | 
						|
 #if RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
						|
 #define RAPIDJSON_NOEXCEPT noexcept
 | 
						|
 #else
 | 
						|
-#define RAPIDJSON_NOEXCEPT /* noexcept */
 | 
						|
+#define RAPIDJSON_NOEXCEPT throw()
 | 
						|
 #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 // no automatic detection, yet
 | 
						|
 #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
 | 
						|
+#if (defined(_MSC_VER) && _MSC_VER >= 1700)
 | 
						|
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1
 | 
						|
+#else
 | 
						|
 #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
 | 
						|
 #endif
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
 | 
						|
 #if defined(__clang__)
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
 | 
						|
-#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
						|
-      (defined(_MSC_VER) && _MSC_VER >= 1700)
 | 
						|
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
						|
+      (defined(_MSC_VER) && _MSC_VER >= 1700) || \
 | 
						|
+      (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
 | 
						|
 #else
 | 
						|
 #define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
 | 
						|
 #endif
 | 
						|
 #endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// C++17 features
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_HAS_CXX17
 | 
						|
+#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_CXX17
 | 
						|
+# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
 | 
						|
+#elif defined(__has_cpp_attribute)
 | 
						|
+# if __has_cpp_attribute(clang::fallthrough)
 | 
						|
+#  define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
 | 
						|
+# elif __has_cpp_attribute(fallthrough)
 | 
						|
+#  define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
 | 
						|
+# else
 | 
						|
+#  define RAPIDJSON_DELIBERATE_FALLTHROUGH
 | 
						|
+# endif
 | 
						|
+#else
 | 
						|
+# define RAPIDJSON_DELIBERATE_FALLTHROUGH
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 //!@endcond
 | 
						|
 
 | 
						|
+//! Assertion (in non-throwing contexts).
 | 
						|
+ /*! \ingroup RAPIDJSON_CONFIG
 | 
						|
+    Some functions provide a \c noexcept guarantee, if the compiler supports it.
 | 
						|
+    In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
 | 
						|
+    throw an exception.  This macro adds a separate customization point for
 | 
						|
+    such cases.
 | 
						|
+
 | 
						|
+    Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is
 | 
						|
+    supported, and to \ref RAPIDJSON_ASSERT otherwise.
 | 
						|
+ */
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// RAPIDJSON_NOEXCEPT_ASSERT
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_NOEXCEPT_ASSERT
 | 
						|
+#ifdef RAPIDJSON_ASSERT_THROWS
 | 
						|
+#include <cassert>
 | 
						|
+#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
 | 
						|
+#else
 | 
						|
+#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
 | 
						|
+#endif // RAPIDJSON_ASSERT_THROWS
 | 
						|
+#endif // RAPIDJSON_NOEXCEPT_ASSERT
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// malloc/realloc/free
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_MALLOC
 | 
						|
+///! customization point for global \c malloc
 | 
						|
+#define RAPIDJSON_MALLOC(size) std::malloc(size)
 | 
						|
+#endif
 | 
						|
+#ifndef RAPIDJSON_REALLOC
 | 
						|
+///! customization point for global \c realloc
 | 
						|
+#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
 | 
						|
+#endif
 | 
						|
+#ifndef RAPIDJSON_FREE
 | 
						|
+///! customization point for global \c free
 | 
						|
+#define RAPIDJSON_FREE(ptr) std::free(ptr)
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // new/delete
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_NEW
 | 
						|
 ///! customization point for global \c new
 | 
						|
-#define RAPIDJSON_NEW(x) new x
 | 
						|
+#define RAPIDJSON_NEW(TypeName) new TypeName
 | 
						|
 #endif
 | 
						|
 #ifndef RAPIDJSON_DELETE
 | 
						|
 ///! customization point for global \c delete
 | 
						|
@@ -607,7 +731,7 @@ enum Type {
 | 
						|
     kFalseType = 1,     //!< false
 | 
						|
     kTrueType = 2,      //!< true
 | 
						|
     kObjectType = 3,    //!< object
 | 
						|
-    kArrayType = 4,     //!< array 
 | 
						|
+    kArrayType = 4,     //!< array
 | 
						|
     kStringType = 5,    //!< string
 | 
						|
     kNumberType = 6     //!< number
 | 
						|
 };
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/reader.h b/src/common/thirdparty/rapidjson/reader.h
 | 
						|
index 19f8849b1..55546601e 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/reader.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/reader.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 //
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -20,6 +20,7 @@
 | 
						|
 #include "allocators.h"
 | 
						|
 #include "stream.h"
 | 
						|
 #include "encodedstream.h"
 | 
						|
+#include "internal/clzll.h"
 | 
						|
 #include "internal/meta.h"
 | 
						|
 #include "internal/stack.h"
 | 
						|
 #include "internal/strtod.h"
 | 
						|
@@ -33,12 +34,8 @@
 | 
						|
 #include <nmmintrin.h>
 | 
						|
 #elif defined(RAPIDJSON_SSE2)
 | 
						|
 #include <emmintrin.h>
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_PUSH
 | 
						|
-RAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant
 | 
						|
-RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
						|
+#elif defined(RAPIDJSON_NEON)
 | 
						|
+#include <arm_neon.h>
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
@@ -46,6 +43,10 @@ RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(old-style-cast)
 | 
						|
 RAPIDJSON_DIAG_OFF(padded)
 | 
						|
 RAPIDJSON_DIAG_OFF(switch-enum)
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant
 | 
						|
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #ifdef __GNUC__
 | 
						|
@@ -153,6 +154,7 @@ enum ParseFlag {
 | 
						|
     kParseNumbersAsStringsFlag = 64,    //!< Parse all numbers (ints/doubles) as strings.
 | 
						|
     kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
 | 
						|
     kParseNanAndInfFlag = 256,      //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
 | 
						|
+    kParseEscapedApostropheFlag = 512,  //!< Allow escaped apostrophe in strings.
 | 
						|
     kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS  //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
 | 
						|
 };
 | 
						|
 
 | 
						|
@@ -299,16 +301,9 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
 | 
						|
 
 | 
						|
     for (;; p += 16) {
 | 
						|
         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
-        const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
 | 
						|
-        if (r != 0) {   // some of characters is non-whitespace
 | 
						|
-#ifdef _MSC_VER         // Find the index of first non-whitespace
 | 
						|
-            unsigned long offset;
 | 
						|
-            _BitScanForward(&offset, r);
 | 
						|
-            return p + offset;
 | 
						|
-#else
 | 
						|
-            return p + __builtin_ffs(r) - 1;
 | 
						|
-#endif
 | 
						|
-        }
 | 
						|
+        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
 | 
						|
+            return p + r;
 | 
						|
     }
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -325,16 +320,9 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
 | 
						|
 
 | 
						|
     for (; p <= end - 16; p += 16) {
 | 
						|
         const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
-        const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
 | 
						|
-        if (r != 0) {   // some of characters is non-whitespace
 | 
						|
-#ifdef _MSC_VER         // Find the index of first non-whitespace
 | 
						|
-            unsigned long offset;
 | 
						|
-            _BitScanForward(&offset, r);
 | 
						|
-            return p + offset;
 | 
						|
-#else
 | 
						|
-            return p + __builtin_ffs(r) - 1;
 | 
						|
-#endif
 | 
						|
-        }
 | 
						|
+        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
 | 
						|
+            return p + r;
 | 
						|
     }
 | 
						|
 
 | 
						|
     return SkipWhitespace(p, end);
 | 
						|
@@ -425,7 +413,92 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
 | 
						|
     return SkipWhitespace(p, end);
 | 
						|
 }
 | 
						|
 
 | 
						|
-#endif // RAPIDJSON_SSE2
 | 
						|
+#elif defined(RAPIDJSON_NEON)
 | 
						|
+
 | 
						|
+//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.
 | 
						|
+inline const char *SkipWhitespace_SIMD(const char* p) {
 | 
						|
+    // Fast return for single non-whitespace
 | 
						|
+    if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
 | 
						|
+        ++p;
 | 
						|
+    else
 | 
						|
+        return p;
 | 
						|
+
 | 
						|
+    // 16-byte align to the next boundary
 | 
						|
+    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
 | 
						|
+    while (p != nextAligned)
 | 
						|
+        if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
 | 
						|
+            ++p;
 | 
						|
+        else
 | 
						|
+            return p;
 | 
						|
+
 | 
						|
+    const uint8x16_t w0 = vmovq_n_u8(' ');
 | 
						|
+    const uint8x16_t w1 = vmovq_n_u8('\n');
 | 
						|
+    const uint8x16_t w2 = vmovq_n_u8('\r');
 | 
						|
+    const uint8x16_t w3 = vmovq_n_u8('\t');
 | 
						|
+
 | 
						|
+    for (;; p += 16) {
 | 
						|
+        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
 | 
						|
+        uint8x16_t x = vceqq_u8(s, w0);
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w1));
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w2));
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w3));
 | 
						|
+
 | 
						|
+        x = vmvnq_u8(x);                       // Negate
 | 
						|
+        x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+        uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+        uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+        if (low == 0) {
 | 
						|
+            if (high != 0) {
 | 
						|
+                uint32_t lz = internal::clzll(high);
 | 
						|
+                return p + 8 + (lz >> 3);
 | 
						|
+            }
 | 
						|
+        } else {
 | 
						|
+            uint32_t lz = internal::clzll(low);
 | 
						|
+            return p + (lz >> 3);
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
 | 
						|
+    // Fast return for single non-whitespace
 | 
						|
+    if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
 | 
						|
+        ++p;
 | 
						|
+    else
 | 
						|
+        return p;
 | 
						|
+
 | 
						|
+    const uint8x16_t w0 = vmovq_n_u8(' ');
 | 
						|
+    const uint8x16_t w1 = vmovq_n_u8('\n');
 | 
						|
+    const uint8x16_t w2 = vmovq_n_u8('\r');
 | 
						|
+    const uint8x16_t w3 = vmovq_n_u8('\t');
 | 
						|
+
 | 
						|
+    for (; p <= end - 16; p += 16) {
 | 
						|
+        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
 | 
						|
+        uint8x16_t x = vceqq_u8(s, w0);
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w1));
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w2));
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, w3));
 | 
						|
+
 | 
						|
+        x = vmvnq_u8(x);                       // Negate
 | 
						|
+        x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+        uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+        uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+        if (low == 0) {
 | 
						|
+            if (high != 0) {
 | 
						|
+                uint32_t lz = internal::clzll(high);
 | 
						|
+                return p + 8 + (lz >> 3);
 | 
						|
+            }
 | 
						|
+        } else {
 | 
						|
+            uint32_t lz = internal::clzll(low);
 | 
						|
+            return p + (lz >> 3);
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    return SkipWhitespace(p, end);
 | 
						|
+}
 | 
						|
+
 | 
						|
+#endif // RAPIDJSON_NEON
 | 
						|
 
 | 
						|
 #ifdef RAPIDJSON_SIMD
 | 
						|
 //! Template function specialization for InsituStringStream
 | 
						|
@@ -471,7 +544,8 @@ public:
 | 
						|
     /*! \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)
 | 
						|
     */
 | 
						|
-    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
 | 
						|
+    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :
 | 
						|
+        stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
 | 
						|
 
 | 
						|
     //! Parse JSON text.
 | 
						|
     /*! \tparam parseFlags Combination of \ref ParseFlag.
 | 
						|
@@ -527,7 +601,84 @@ public:
 | 
						|
         return Parse<kParseDefaultFlags>(is, handler);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    //! Whether a parse error has occured in the last parsing.
 | 
						|
+    //! Initialize JSON text token-by-token parsing
 | 
						|
+    /*!
 | 
						|
+     */
 | 
						|
+    void IterativeParseInit() {
 | 
						|
+        parseResult_.Clear();
 | 
						|
+        state_ = IterativeParsingStartState;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Parse one token from JSON text
 | 
						|
+    /*! \tparam InputStream Type of input stream, implementing Stream concept
 | 
						|
+        \tparam Handler Type of handler, implementing Handler concept.
 | 
						|
+        \param is Input stream to be parsed.
 | 
						|
+        \param handler The handler to receive events.
 | 
						|
+        \return Whether the parsing is successful.
 | 
						|
+     */
 | 
						|
+    template <unsigned parseFlags, typename InputStream, typename Handler>
 | 
						|
+    bool IterativeParseNext(InputStream& is, Handler& handler) {
 | 
						|
+        while (RAPIDJSON_LIKELY(is.Peek() != '\0')) {
 | 
						|
+            SkipWhitespaceAndComments<parseFlags>(is);
 | 
						|
+
 | 
						|
+            Token t = Tokenize(is.Peek());
 | 
						|
+            IterativeParsingState n = Predict(state_, t);
 | 
						|
+            IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
 | 
						|
+
 | 
						|
+            // If we've finished or hit an error...
 | 
						|
+            if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {
 | 
						|
+                // Report errors.
 | 
						|
+                if (d == IterativeParsingErrorState) {
 | 
						|
+                    HandleError(state_, is);
 | 
						|
+                    return false;
 | 
						|
+                }
 | 
						|
+
 | 
						|
+                // Transition to the finish state.
 | 
						|
+                RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
 | 
						|
+                state_ = d;
 | 
						|
+
 | 
						|
+                // If StopWhenDone is not set...
 | 
						|
+                if (!(parseFlags & kParseStopWhenDoneFlag)) {
 | 
						|
+                    // ... and extra non-whitespace data is found...
 | 
						|
+                    SkipWhitespaceAndComments<parseFlags>(is);
 | 
						|
+                    if (is.Peek() != '\0') {
 | 
						|
+                        // ... this is considered an error.
 | 
						|
+                        HandleError(state_, is);
 | 
						|
+                        return false;
 | 
						|
+                    }
 | 
						|
+                }
 | 
						|
+
 | 
						|
+                // Success! We are done!
 | 
						|
+                return true;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            // Transition to the new state.
 | 
						|
+            state_ = d;
 | 
						|
+
 | 
						|
+            // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
 | 
						|
+            if (!IsIterativeParsingDelimiterState(n))
 | 
						|
+                return true;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        // We reached the end of file.
 | 
						|
+        stack_.Clear();
 | 
						|
+
 | 
						|
+        if (state_ != IterativeParsingFinishState) {
 | 
						|
+            HandleError(state_, is);
 | 
						|
+            return false;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Check if token-by-token parsing JSON text is complete
 | 
						|
+    /*! \return Whether the JSON has been fully decoded.
 | 
						|
+     */
 | 
						|
+    RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const {
 | 
						|
+        return IsIterativeParsingCompleteState(state_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Whether a parse error has occurred in the last parsing.
 | 
						|
     bool HasParseError() const { return parseResult_.IsError(); }
 | 
						|
 
 | 
						|
     //! Get the \ref ParseErrorCode of last parsing.
 | 
						|
@@ -575,7 +726,7 @@ private:
 | 
						|
                     }
 | 
						|
                 }
 | 
						|
                 else if (RAPIDJSON_LIKELY(Consume(is, '/')))
 | 
						|
-                    while (is.Peek() != '\0' && is.Take() != '\n');
 | 
						|
+                    while (is.Peek() != '\0' && is.Take() != '\n') {}
 | 
						|
                 else
 | 
						|
                     RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
 | 
						|
 
 | 
						|
@@ -750,7 +901,7 @@ private:
 | 
						|
             return false;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
 | 
						|
+    // Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
 | 
						|
     template<typename InputStream>
 | 
						|
     unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
 | 
						|
         unsigned codepoint = 0;
 | 
						|
@@ -841,7 +992,7 @@ private:
 | 
						|
 //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 | 
						|
         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,
 | 
						|
             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,
 | 
						|
@@ -857,26 +1008,38 @@ private:
 | 
						|
 
 | 
						|
             Ch c = is.Peek();
 | 
						|
             if (RAPIDJSON_UNLIKELY(c == '\\')) {    // Escape
 | 
						|
-                size_t escapeOffset = is.Tell();    // For invalid escaping, report the inital '\\' as error offset
 | 
						|
+                size_t escapeOffset = is.Tell();    // For invalid escaping, report the initial '\\' as error offset
 | 
						|
                 is.Take();
 | 
						|
                 Ch e = is.Peek();
 | 
						|
                 if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
 | 
						|
                     is.Take();
 | 
						|
                     os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
 | 
						|
                 }
 | 
						|
+                else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe
 | 
						|
+                    is.Take();
 | 
						|
+                    os.Put('\'');
 | 
						|
+                }
 | 
						|
                 else if (RAPIDJSON_LIKELY(e == 'u')) {    // Unicode
 | 
						|
                     is.Take();
 | 
						|
                     unsigned codepoint = ParseHex4(is, escapeOffset);
 | 
						|
                     RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
 | 
						|
-                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
 | 
						|
-                        // Handle UTF-16 surrogate pair
 | 
						|
-                        if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
 | 
						|
-                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
 | 
						|
-                        unsigned codepoint2 = ParseHex4(is, escapeOffset);
 | 
						|
-                        RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
 | 
						|
-                        if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
 | 
						|
+                    if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
 | 
						|
+                        // high surrogate, check if followed by valid low surrogate
 | 
						|
+                        if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) {
 | 
						|
+                            // Handle UTF-16 surrogate pair
 | 
						|
+                            if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
 | 
						|
+                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
 | 
						|
+                            unsigned codepoint2 = ParseHex4(is, escapeOffset);
 | 
						|
+                            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
 | 
						|
+                            if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
 | 
						|
+                                RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
 | 
						|
+                            codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
 | 
						|
+                        }
 | 
						|
+                        // single low surrogate
 | 
						|
+                        else
 | 
						|
+                        {
 | 
						|
                             RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
 | 
						|
-                        codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
 | 
						|
+                        }
 | 
						|
                     }
 | 
						|
                     TEncoding::Encode(os, codepoint);
 | 
						|
                 }
 | 
						|
@@ -892,7 +1055,7 @@ private:
 | 
						|
                 if (c == '\0')
 | 
						|
                     RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
 | 
						|
                 else
 | 
						|
-                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
 | 
						|
+                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
 | 
						|
             }
 | 
						|
             else {
 | 
						|
                 size_t offset = is.Tell();
 | 
						|
@@ -927,7 +1090,7 @@ private:
 | 
						|
         // The rest of string using SIMD
 | 
						|
         static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
 | 
						|
         static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
 | 
						|
-        static const char space[16]  = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
 | 
						|
+        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 bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
 | 
						|
         const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
 | 
						|
@@ -936,7 +1099,7 @@ private:
 | 
						|
             const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
             const __m128i t1 = _mm_cmpeq_epi8(s, dq);
 | 
						|
             const __m128i t2 = _mm_cmpeq_epi8(s, bs);
 | 
						|
-            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
 | 
						|
+            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
 | 
						|
             const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
 | 
						|
             unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
 | 
						|
             if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
 | 
						|
@@ -948,11 +1111,13 @@ private:
 | 
						|
     #else
 | 
						|
                 length = static_cast<SizeType>(__builtin_ffs(r) - 1);
 | 
						|
     #endif
 | 
						|
-                char* q = reinterpret_cast<char*>(os.Push(length));
 | 
						|
-                for (size_t i = 0; i < length; i++)
 | 
						|
-                    q[i] = p[i];
 | 
						|
+                if (length != 0) {
 | 
						|
+                    char* q = reinterpret_cast<char*>(os.Push(length));
 | 
						|
+                    for (size_t i = 0; i < length; i++)
 | 
						|
+                        q[i] = p[i];
 | 
						|
 
 | 
						|
-                p += length;
 | 
						|
+                    p += length;
 | 
						|
+                }
 | 
						|
                 break;
 | 
						|
             }
 | 
						|
             _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
 | 
						|
@@ -988,7 +1153,7 @@ private:
 | 
						|
         // The rest of string using SIMD
 | 
						|
         static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
 | 
						|
         static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
 | 
						|
-        static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
 | 
						|
+        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 bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
 | 
						|
         const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
 | 
						|
@@ -997,7 +1162,7 @@ private:
 | 
						|
             const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
             const __m128i t1 = _mm_cmpeq_epi8(s, dq);
 | 
						|
             const __m128i t2 = _mm_cmpeq_epi8(s, bs);
 | 
						|
-            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
 | 
						|
+            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
 | 
						|
             const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
 | 
						|
             unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
 | 
						|
             if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
 | 
						|
@@ -1036,7 +1201,7 @@ private:
 | 
						|
         // The rest of string using SIMD
 | 
						|
         static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
 | 
						|
         static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
 | 
						|
-        static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
 | 
						|
+        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 bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
 | 
						|
         const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
 | 
						|
@@ -1045,7 +1210,7 @@ private:
 | 
						|
             const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
             const __m128i t1 = _mm_cmpeq_epi8(s, dq);
 | 
						|
             const __m128i t2 = _mm_cmpeq_epi8(s, bs);
 | 
						|
-            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
 | 
						|
+            const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
 | 
						|
             const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
 | 
						|
             unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
 | 
						|
             if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
 | 
						|
@@ -1064,27 +1229,199 @@ private:
 | 
						|
 
 | 
						|
         is.src_ = is.dst_ = p;
 | 
						|
     }
 | 
						|
-#endif
 | 
						|
+#elif defined(RAPIDJSON_NEON)
 | 
						|
+    // StringStream -> StackStream<char>
 | 
						|
+    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
 | 
						|
+        const char* p = is.src_;
 | 
						|
+
 | 
						|
+        // 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));
 | 
						|
+        while (p != nextAligned)
 | 
						|
+            if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
 | 
						|
+                is.src_ = p;
 | 
						|
+                return;
 | 
						|
+            }
 | 
						|
+            else
 | 
						|
+                os.Put(*p++);
 | 
						|
 
 | 
						|
-    template<typename InputStream, bool backup, bool pushOnTake>
 | 
						|
+        // The rest of string using SIMD
 | 
						|
+        const uint8x16_t s0 = vmovq_n_u8('"');
 | 
						|
+        const uint8x16_t s1 = vmovq_n_u8('\\');
 | 
						|
+        const uint8x16_t s2 = vmovq_n_u8('\b');
 | 
						|
+        const uint8x16_t s3 = vmovq_n_u8(32);
 | 
						|
+
 | 
						|
+        for (;; p += 16) {
 | 
						|
+            const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
 | 
						|
+            uint8x16_t x = vceqq_u8(s, s0);
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s1));
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s2));
 | 
						|
+            x = vorrq_u8(x, vcltq_u8(s, s3));
 | 
						|
+
 | 
						|
+            x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+            uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+            uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+            SizeType length = 0;
 | 
						|
+            bool escaped = false;
 | 
						|
+            if (low == 0) {
 | 
						|
+                if (high != 0) {
 | 
						|
+                    uint32_t lz = internal::clzll(high);
 | 
						|
+                    length = 8 + (lz >> 3);
 | 
						|
+                    escaped = true;
 | 
						|
+                }
 | 
						|
+            } else {
 | 
						|
+                uint32_t lz = internal::clzll(low);
 | 
						|
+                length = lz >> 3;
 | 
						|
+                escaped = true;
 | 
						|
+            }
 | 
						|
+            if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
 | 
						|
+                if (length != 0) {
 | 
						|
+                    char* q = reinterpret_cast<char*>(os.Push(length));
 | 
						|
+                    for (size_t i = 0; i < length; i++)
 | 
						|
+                        q[i] = p[i];
 | 
						|
+
 | 
						|
+                    p += length;
 | 
						|
+                }
 | 
						|
+                break;
 | 
						|
+            }
 | 
						|
+            vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        is.src_ = p;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // InsituStringStream -> InsituStringStream
 | 
						|
+    static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
 | 
						|
+        RAPIDJSON_ASSERT(&is == &os);
 | 
						|
+        (void)os;
 | 
						|
+
 | 
						|
+        if (is.src_ == is.dst_) {
 | 
						|
+            SkipUnescapedString(is);
 | 
						|
+            return;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        char* p = is.src_;
 | 
						|
+        char *q = is.dst_;
 | 
						|
+
 | 
						|
+        // 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));
 | 
						|
+        while (p != nextAligned)
 | 
						|
+            if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
 | 
						|
+                is.src_ = p;
 | 
						|
+                is.dst_ = q;
 | 
						|
+                return;
 | 
						|
+            }
 | 
						|
+            else
 | 
						|
+                *q++ = *p++;
 | 
						|
+
 | 
						|
+        // The rest of string using SIMD
 | 
						|
+        const uint8x16_t s0 = vmovq_n_u8('"');
 | 
						|
+        const uint8x16_t s1 = vmovq_n_u8('\\');
 | 
						|
+        const uint8x16_t s2 = vmovq_n_u8('\b');
 | 
						|
+        const uint8x16_t s3 = vmovq_n_u8(32);
 | 
						|
+
 | 
						|
+        for (;; p += 16, q += 16) {
 | 
						|
+            const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
 | 
						|
+            uint8x16_t x = vceqq_u8(s, s0);
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s1));
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s2));
 | 
						|
+            x = vorrq_u8(x, vcltq_u8(s, s3));
 | 
						|
+
 | 
						|
+            x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+            uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+            uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+            SizeType length = 0;
 | 
						|
+            bool escaped = false;
 | 
						|
+            if (low == 0) {
 | 
						|
+                if (high != 0) {
 | 
						|
+                    uint32_t lz = internal::clzll(high);
 | 
						|
+                    length = 8 + (lz >> 3);
 | 
						|
+                    escaped = true;
 | 
						|
+                }
 | 
						|
+            } else {
 | 
						|
+                uint32_t lz = internal::clzll(low);
 | 
						|
+                length = lz >> 3;
 | 
						|
+                escaped = true;
 | 
						|
+            }
 | 
						|
+            if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
 | 
						|
+                for (const char* pend = p + length; p != pend; ) {
 | 
						|
+                    *q++ = *p++;
 | 
						|
+                }
 | 
						|
+                break;
 | 
						|
+            }
 | 
						|
+            vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        is.src_ = p;
 | 
						|
+        is.dst_ = q;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // When read/write pointers are the same for insitu stream, just skip unescaped characters
 | 
						|
+    static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
 | 
						|
+        RAPIDJSON_ASSERT(is.src_ == is.dst_);
 | 
						|
+        char* p = is.src_;
 | 
						|
+
 | 
						|
+        // 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));
 | 
						|
+        for (; p != nextAligned; p++)
 | 
						|
+            if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
 | 
						|
+                is.src_ = is.dst_ = p;
 | 
						|
+                return;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+        // The rest of string using SIMD
 | 
						|
+        const uint8x16_t s0 = vmovq_n_u8('"');
 | 
						|
+        const uint8x16_t s1 = vmovq_n_u8('\\');
 | 
						|
+        const uint8x16_t s2 = vmovq_n_u8('\b');
 | 
						|
+        const uint8x16_t s3 = vmovq_n_u8(32);
 | 
						|
+
 | 
						|
+        for (;; p += 16) {
 | 
						|
+            const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
 | 
						|
+            uint8x16_t x = vceqq_u8(s, s0);
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s1));
 | 
						|
+            x = vorrq_u8(x, vceqq_u8(s, s2));
 | 
						|
+            x = vorrq_u8(x, vcltq_u8(s, s3));
 | 
						|
+
 | 
						|
+            x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+            uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+            uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+            if (low == 0) {
 | 
						|
+                if (high != 0) {
 | 
						|
+                    uint32_t lz = internal::clzll(high);
 | 
						|
+                    p += 8 + (lz >> 3);
 | 
						|
+                    break;
 | 
						|
+                }
 | 
						|
+            } else {
 | 
						|
+                uint32_t lz = internal::clzll(low);
 | 
						|
+                p += lz >> 3;
 | 
						|
+                break;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        is.src_ = is.dst_ = p;
 | 
						|
+    }
 | 
						|
+#endif // RAPIDJSON_NEON
 | 
						|
+
 | 
						|
+    template<typename InputStream, typename StackCharacter, bool backup, bool pushOnTake>
 | 
						|
     class NumberStream;
 | 
						|
 
 | 
						|
-    template<typename InputStream>
 | 
						|
-    class NumberStream<InputStream, false, false> {
 | 
						|
+    template<typename InputStream, typename StackCharacter>
 | 
						|
+    class NumberStream<InputStream, StackCharacter, false, false> {
 | 
						|
     public:
 | 
						|
         typedef typename InputStream::Ch Ch;
 | 
						|
 
 | 
						|
         NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader;  }
 | 
						|
-        ~NumberStream() {}
 | 
						|
 
 | 
						|
         RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
 | 
						|
         RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
 | 
						|
         RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
 | 
						|
-		  RAPIDJSON_FORCEINLINE void Push(char) {}
 | 
						|
+        RAPIDJSON_FORCEINLINE void Push(char) {}
 | 
						|
 
 | 
						|
         size_t Tell() { return is.Tell(); }
 | 
						|
         size_t Length() { return 0; }
 | 
						|
-        const char* Pop() { return 0; }
 | 
						|
+        const StackCharacter* Pop() { return 0; }
 | 
						|
 
 | 
						|
     protected:
 | 
						|
         NumberStream& operator=(const NumberStream&);
 | 
						|
@@ -1092,47 +1429,47 @@ private:
 | 
						|
         InputStream& is;
 | 
						|
     };
 | 
						|
 
 | 
						|
-    template<typename InputStream>
 | 
						|
-    class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
 | 
						|
-        typedef NumberStream<InputStream, false, false> Base;
 | 
						|
+    template<typename InputStream, typename StackCharacter>
 | 
						|
+    class NumberStream<InputStream, StackCharacter, true, false> : public NumberStream<InputStream, StackCharacter, false, false> {
 | 
						|
+        typedef NumberStream<InputStream, StackCharacter, false, false> Base;
 | 
						|
     public:
 | 
						|
-        NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
 | 
						|
-        ~NumberStream() {}
 | 
						|
+        NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {}
 | 
						|
 
 | 
						|
         RAPIDJSON_FORCEINLINE Ch TakePush() {
 | 
						|
-            stackStream.Put(static_cast<char>(Base::is.Peek()));
 | 
						|
+            stackStream.Put(static_cast<StackCharacter>(Base::is.Peek()));
 | 
						|
             return Base::is.Take();
 | 
						|
         }
 | 
						|
 
 | 
						|
-        RAPIDJSON_FORCEINLINE void Push(char c) {
 | 
						|
+        RAPIDJSON_FORCEINLINE void Push(StackCharacter c) {
 | 
						|
             stackStream.Put(c);
 | 
						|
         }
 | 
						|
 
 | 
						|
         size_t Length() { return stackStream.Length(); }
 | 
						|
 
 | 
						|
-        const char* Pop() {
 | 
						|
+        const StackCharacter* Pop() {
 | 
						|
             stackStream.Put('\0');
 | 
						|
             return stackStream.Pop();
 | 
						|
         }
 | 
						|
 
 | 
						|
     private:
 | 
						|
-        StackStream<char> stackStream;
 | 
						|
+        StackStream<StackCharacter> stackStream;
 | 
						|
     };
 | 
						|
 
 | 
						|
-    template<typename InputStream>
 | 
						|
-    class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
 | 
						|
-        typedef NumberStream<InputStream, true, false> Base;
 | 
						|
+    template<typename InputStream, typename StackCharacter>
 | 
						|
+    class NumberStream<InputStream, StackCharacter, true, true> : public NumberStream<InputStream, StackCharacter, true, false> {
 | 
						|
+        typedef NumberStream<InputStream, StackCharacter, true, false> Base;
 | 
						|
     public:
 | 
						|
-        NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
 | 
						|
-        ~NumberStream() {}
 | 
						|
+        NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {}
 | 
						|
 
 | 
						|
         RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
 | 
						|
     };
 | 
						|
 
 | 
						|
     template<unsigned parseFlags, typename InputStream, typename Handler>
 | 
						|
     void ParseNumber(InputStream& is, Handler& handler) {
 | 
						|
+        typedef typename internal::SelectIf<internal::BoolType<(parseFlags & kParseNumbersAsStringsFlag) != 0>, typename TargetEncoding::Ch, char>::Type NumberCharacter;
 | 
						|
+
 | 
						|
         internal::StreamLocalCopy<InputStream> copy(is);
 | 
						|
-        NumberStream<InputStream,
 | 
						|
+        NumberStream<InputStream, NumberCharacter,
 | 
						|
             ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
 | 
						|
                 ((parseFlags & kParseInsituFlag) == 0) :
 | 
						|
                 ((parseFlags & kParseFullPrecisionFlag) != 0),
 | 
						|
@@ -1185,18 +1522,27 @@ private:
 | 
						|
         }
 | 
						|
         // Parse NaN or Infinity here
 | 
						|
         else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
 | 
						|
-            useNanOrInf = true;
 | 
						|
-            if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
 | 
						|
-                d = std::numeric_limits<double>::quiet_NaN();
 | 
						|
+            if (Consume(s, 'N')) {
 | 
						|
+                if (Consume(s, 'a') && Consume(s, 'N')) {
 | 
						|
+                    d = std::numeric_limits<double>::quiet_NaN();
 | 
						|
+                    useNanOrInf = true;
 | 
						|
+                }
 | 
						|
             }
 | 
						|
-            else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
 | 
						|
-                d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
 | 
						|
-                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());
 | 
						|
+            else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) {
 | 
						|
+                if (Consume(s, 'n') && Consume(s, 'f')) {
 | 
						|
+                    d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
 | 
						|
+                    useNanOrInf = true;
 | 
						|
+
 | 
						|
+                    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());
 | 
						|
+                    }
 | 
						|
+                }
 | 
						|
             }
 | 
						|
-            else
 | 
						|
+
 | 
						|
+            if (RAPIDJSON_UNLIKELY(!useNanOrInf)) {
 | 
						|
                 RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
 | 
						|
+            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
             RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
 | 
						|
@@ -1231,8 +1577,6 @@ private:
 | 
						|
         // Force double for big integer
 | 
						|
         if (useDouble) {
 | 
						|
             while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
 | 
						|
-                if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
 | 
						|
-                    RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
 | 
						|
                 d = d * 10 + (s.TakePush() - '0');
 | 
						|
             }
 | 
						|
         }
 | 
						|
@@ -1302,9 +1646,18 @@ private:
 | 
						|
             if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
 | 
						|
                 exp = static_cast<int>(s.Take() - '0');
 | 
						|
                 if (expMinus) {
 | 
						|
+                    // (exp + expFrac) must not underflow int => we're detecting when -exp gets
 | 
						|
+                    // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into
 | 
						|
+                    // underflow territory):
 | 
						|
+                    //
 | 
						|
+                    //        -(exp * 10 + 9) + expFrac >= INT_MIN
 | 
						|
+                    //   <=>  exp <= (expFrac - INT_MIN - 9) / 10
 | 
						|
+                    RAPIDJSON_ASSERT(expFrac <= 0);
 | 
						|
+                    int maxExp = (expFrac + 2147483639) / 10;
 | 
						|
+
 | 
						|
                     while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
 | 
						|
                         exp = exp * 10 + static_cast<int>(s.Take() - '0');
 | 
						|
-                        if (exp >= 214748364) {                         // Issue #313: prevent overflow exponent
 | 
						|
+                        if (RAPIDJSON_UNLIKELY(exp > maxExp)) {
 | 
						|
                             while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9'))  // Consume the rest of exponent
 | 
						|
                                 s.Take();
 | 
						|
                         }
 | 
						|
@@ -1341,10 +1694,10 @@ private:
 | 
						|
             }
 | 
						|
             else {
 | 
						|
                 SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
 | 
						|
-                StringStream srcStream(s.Pop());
 | 
						|
+                GenericStringStream<UTF8<NumberCharacter> > srcStream(s.Pop());
 | 
						|
                 StackStream<typename TargetEncoding::Ch> dstStream(stack_);
 | 
						|
                 while (numCharsToCopy--) {
 | 
						|
-                    Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
 | 
						|
+                    Transcoder<UTF8<typename TargetEncoding::Ch>, TargetEncoding>::Transcode(srcStream, dstStream);
 | 
						|
                 }
 | 
						|
                 dstStream.Put('\0');
 | 
						|
                 const typename TargetEncoding::Ch* str = dstStream.Pop();
 | 
						|
@@ -1354,7 +1707,7 @@ private:
 | 
						|
         }
 | 
						|
         else {
 | 
						|
            size_t length = s.Length();
 | 
						|
-           const char* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
 | 
						|
+           const NumberCharacter* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
 | 
						|
 
 | 
						|
            if (useDouble) {
 | 
						|
                int p = exp + expFrac;
 | 
						|
@@ -1363,6 +1716,13 @@ private:
 | 
						|
                else
 | 
						|
                    d = internal::StrtodNormalPrecision(d, p);
 | 
						|
 
 | 
						|
+               // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
 | 
						|
+               if (d > (std::numeric_limits<double>::max)()) {
 | 
						|
+                   // Overflow
 | 
						|
+                   // TODO: internal::StrtodX should report overflow (or underflow)
 | 
						|
+                   RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
 | 
						|
+               }
 | 
						|
+
 | 
						|
                cont = handler.Double(minus ? -d : d);
 | 
						|
            }
 | 
						|
            else if (useNanOrInf) {
 | 
						|
@@ -1408,29 +1768,31 @@ private:
 | 
						|
 
 | 
						|
     // States
 | 
						|
     enum IterativeParsingState {
 | 
						|
-        IterativeParsingStartState = 0,
 | 
						|
-        IterativeParsingFinishState,
 | 
						|
-        IterativeParsingErrorState,
 | 
						|
+        IterativeParsingFinishState = 0, // sink states at top
 | 
						|
+        IterativeParsingErrorState,      // sink states at top
 | 
						|
+        IterativeParsingStartState,
 | 
						|
 
 | 
						|
         // Object states
 | 
						|
         IterativeParsingObjectInitialState,
 | 
						|
         IterativeParsingMemberKeyState,
 | 
						|
-        IterativeParsingKeyValueDelimiterState,
 | 
						|
         IterativeParsingMemberValueState,
 | 
						|
-        IterativeParsingMemberDelimiterState,
 | 
						|
         IterativeParsingObjectFinishState,
 | 
						|
 
 | 
						|
         // Array states
 | 
						|
         IterativeParsingArrayInitialState,
 | 
						|
         IterativeParsingElementState,
 | 
						|
-        IterativeParsingElementDelimiterState,
 | 
						|
         IterativeParsingArrayFinishState,
 | 
						|
 
 | 
						|
         // Single value state
 | 
						|
-        IterativeParsingValueState
 | 
						|
-    };
 | 
						|
+        IterativeParsingValueState,
 | 
						|
+
 | 
						|
+        // Delimiter states (at bottom)
 | 
						|
+        IterativeParsingElementDelimiterState,
 | 
						|
+        IterativeParsingMemberDelimiterState,
 | 
						|
+        IterativeParsingKeyValueDelimiterState,
 | 
						|
 
 | 
						|
-    enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
 | 
						|
+        cIterativeParsingStateCount
 | 
						|
+    };
 | 
						|
 
 | 
						|
     // Tokens
 | 
						|
     enum Token {
 | 
						|
@@ -1452,7 +1814,7 @@ private:
 | 
						|
         kTokenCount
 | 
						|
     };
 | 
						|
 
 | 
						|
-    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
 | 
						|
+    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const {
 | 
						|
 
 | 
						|
 //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
						|
 #define N NumberToken
 | 
						|
@@ -1479,9 +1841,21 @@ private:
 | 
						|
             return NumberToken;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
 | 
						|
+    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const {
 | 
						|
         // current state x one lookahead token -> new state
 | 
						|
         static const char G[cIterativeParsingStateCount][kTokenCount] = {
 | 
						|
+            // Finish(sink state)
 | 
						|
+            {
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState
 | 
						|
+            },
 | 
						|
+            // Error(sink state)
 | 
						|
+            {
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState
 | 
						|
+            },
 | 
						|
             // Start
 | 
						|
             {
 | 
						|
                 IterativeParsingArrayInitialState,  // Left bracket
 | 
						|
@@ -1496,18 +1870,6 @@ private:
 | 
						|
                 IterativeParsingValueState,         // Null
 | 
						|
                 IterativeParsingValueState          // Number
 | 
						|
             },
 | 
						|
-            // Finish(sink state)
 | 
						|
-            {
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState
 | 
						|
-            },
 | 
						|
-            // Error(sink state)
 | 
						|
-            {
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState
 | 
						|
-            },
 | 
						|
             // ObjectInitial
 | 
						|
             {
 | 
						|
                 IterativeParsingErrorState,         // Left bracket
 | 
						|
@@ -1536,20 +1898,6 @@ private:
 | 
						|
                 IterativeParsingErrorState,             // Null
 | 
						|
                 IterativeParsingErrorState              // Number
 | 
						|
             },
 | 
						|
-            // KeyValueDelimiter
 | 
						|
-            {
 | 
						|
-                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
 | 
						|
-                IterativeParsingErrorState,             // Right bracket
 | 
						|
-                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
 | 
						|
-                IterativeParsingErrorState,             // Right curly bracket
 | 
						|
-                IterativeParsingErrorState,             // Comma
 | 
						|
-                IterativeParsingErrorState,             // Colon
 | 
						|
-                IterativeParsingMemberValueState,       // String
 | 
						|
-                IterativeParsingMemberValueState,       // False
 | 
						|
-                IterativeParsingMemberValueState,       // True
 | 
						|
-                IterativeParsingMemberValueState,       // Null
 | 
						|
-                IterativeParsingMemberValueState        // Number
 | 
						|
-            },
 | 
						|
             // MemberValue
 | 
						|
             {
 | 
						|
                 IterativeParsingErrorState,             // Left bracket
 | 
						|
@@ -1564,20 +1912,6 @@ private:
 | 
						|
                 IterativeParsingErrorState,             // Null
 | 
						|
                 IterativeParsingErrorState              // Number
 | 
						|
             },
 | 
						|
-            // MemberDelimiter
 | 
						|
-            {
 | 
						|
-                IterativeParsingErrorState,         // Left bracket
 | 
						|
-                IterativeParsingErrorState,         // Right bracket
 | 
						|
-                IterativeParsingErrorState,         // Left curly bracket
 | 
						|
-                IterativeParsingObjectFinishState,  // Right curly bracket
 | 
						|
-                IterativeParsingErrorState,         // Comma
 | 
						|
-                IterativeParsingErrorState,         // Colon
 | 
						|
-                IterativeParsingMemberKeyState,     // String
 | 
						|
-                IterativeParsingErrorState,         // False
 | 
						|
-                IterativeParsingErrorState,         // True
 | 
						|
-                IterativeParsingErrorState,         // Null
 | 
						|
-                IterativeParsingErrorState          // Number
 | 
						|
-            },
 | 
						|
             // ObjectFinish(sink state)
 | 
						|
             {
 | 
						|
                 IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
@@ -1612,6 +1946,18 @@ private:
 | 
						|
                 IterativeParsingErrorState,             // Null
 | 
						|
                 IterativeParsingErrorState              // Number
 | 
						|
             },
 | 
						|
+            // ArrayFinish(sink state)
 | 
						|
+            {
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState
 | 
						|
+            },
 | 
						|
+            // Single Value (sink state)
 | 
						|
+            {
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
+                IterativeParsingErrorState
 | 
						|
+            },
 | 
						|
             // ElementDelimiter
 | 
						|
             {
 | 
						|
                 IterativeParsingArrayInitialState,      // Left bracket(push Element state)
 | 
						|
@@ -1626,18 +1972,34 @@ private:
 | 
						|
                 IterativeParsingElementState,           // Null
 | 
						|
                 IterativeParsingElementState            // Number
 | 
						|
             },
 | 
						|
-            // ArrayFinish(sink state)
 | 
						|
+            // MemberDelimiter
 | 
						|
             {
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState
 | 
						|
+                IterativeParsingErrorState,         // Left bracket
 | 
						|
+                IterativeParsingErrorState,         // Right bracket
 | 
						|
+                IterativeParsingErrorState,         // Left curly bracket
 | 
						|
+                IterativeParsingObjectFinishState,  // Right curly bracket
 | 
						|
+                IterativeParsingErrorState,         // Comma
 | 
						|
+                IterativeParsingErrorState,         // Colon
 | 
						|
+                IterativeParsingMemberKeyState,     // String
 | 
						|
+                IterativeParsingErrorState,         // False
 | 
						|
+                IterativeParsingErrorState,         // True
 | 
						|
+                IterativeParsingErrorState,         // Null
 | 
						|
+                IterativeParsingErrorState          // Number
 | 
						|
             },
 | 
						|
-            // Single Value (sink state)
 | 
						|
+            // KeyValueDelimiter
 | 
						|
             {
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
 | 
						|
-                IterativeParsingErrorState
 | 
						|
-            }
 | 
						|
+                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
 | 
						|
+                IterativeParsingErrorState,             // Right bracket
 | 
						|
+                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
 | 
						|
+                IterativeParsingErrorState,             // Right curly bracket
 | 
						|
+                IterativeParsingErrorState,             // Comma
 | 
						|
+                IterativeParsingErrorState,             // Colon
 | 
						|
+                IterativeParsingMemberValueState,       // String
 | 
						|
+                IterativeParsingMemberValueState,       // False
 | 
						|
+                IterativeParsingMemberValueState,       // True
 | 
						|
+                IterativeParsingMemberValueState,       // Null
 | 
						|
+                IterativeParsingMemberValueState        // Number
 | 
						|
+            },
 | 
						|
         }; // End of G
 | 
						|
 
 | 
						|
         return static_cast<IterativeParsingState>(G[state][token]);
 | 
						|
@@ -1818,6 +2180,14 @@ private:
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
+    RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const {
 | 
						|
+        return s >= IterativeParsingElementDelimiterState;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const {
 | 
						|
+        return s <= IterativeParsingErrorState;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     template <unsigned parseFlags, typename InputStream, typename Handler>
 | 
						|
     ParseResult IterativeParse(InputStream& is, Handler& handler) {
 | 
						|
         parseResult_.Clear();
 | 
						|
@@ -1856,6 +2226,7 @@ private:
 | 
						|
     static const size_t kDefaultStackCapacity = 256;    //!< Default stack capacity in bytes for storing a single decoded string.
 | 
						|
     internal::Stack<StackAllocator> stack_;  //!< A stack for storing decoded string temporarily during non-destructive parsing.
 | 
						|
     ParseResult parseResult_;
 | 
						|
+    IterativeParsingState state_;
 | 
						|
 }; // class GenericReader
 | 
						|
 
 | 
						|
 //! Reader with UTF8 encoding and default allocator.
 | 
						|
@@ -1863,7 +2234,7 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_END
 | 
						|
 
 | 
						|
-#ifdef __clang__
 | 
						|
+#if defined(__clang__) || defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
@@ -1872,8 +2243,4 @@ RAPIDJSON_DIAG_POP
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_POP
 | 
						|
-#endif
 | 
						|
-
 | 
						|
 #endif // RAPIDJSON_READER_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/schema.h b/src/common/thirdparty/rapidjson/schema.h
 | 
						|
index 8497d3031..439133fa6 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/schema.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/schema.h
 | 
						|
@@ -1,5 +1,5 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available->
 | 
						|
-// 
 | 
						|
+//
 | 
						|
 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
@@ -7,9 +7,9 @@
 | 
						|
 //
 | 
						|
 // http://opensource->org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied-> See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied-> See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License->
 | 
						|
 
 | 
						|
 #ifndef RAPIDJSON_SCHEMA_H_
 | 
						|
@@ -17,6 +17,9 @@
 | 
						|
 
 | 
						|
 #include "document.h"
 | 
						|
 #include "pointer.h"
 | 
						|
+#include "stringbuffer.h"
 | 
						|
+#include "error/en.h"
 | 
						|
+#include "uri.h"
 | 
						|
 #include <cmath> // abs, floor
 | 
						|
 
 | 
						|
 #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
 | 
						|
@@ -25,7 +28,7 @@
 | 
						|
 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
 | 
						|
 #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
 | 
						|
 #else
 | 
						|
 #define RAPIDJSON_SCHEMA_USE_STDREGEX 0
 | 
						|
@@ -47,10 +50,6 @@
 | 
						|
 #define RAPIDJSON_SCHEMA_VERBOSE 0
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-#include "stringbuffer.h"
 | 
						|
-#endif
 | 
						|
-
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 
 | 
						|
 #if defined(__GNUC__)
 | 
						|
@@ -62,9 +61,7 @@ RAPIDJSON_DIAG_OFF(weak-vtables)
 | 
						|
 RAPIDJSON_DIAG_OFF(exit-time-destructors)
 | 
						|
 RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
 | 
						|
 RAPIDJSON_DIAG_OFF(variadic-macros)
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
 #endif
 | 
						|
 
 | 
						|
@@ -77,50 +74,163 @@ RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
 
 | 
						|
 namespace internal {
 | 
						|
 
 | 
						|
-inline void PrintInvalidKeyword(const char* keyword) {
 | 
						|
-    printf("Fail keyword: %s\n", keyword);
 | 
						|
+inline void PrintInvalidKeywordData(const char* keyword) {
 | 
						|
+    printf("    Fail keyword: '%s'\n", keyword);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintInvalidKeywordData(const wchar_t* keyword) {
 | 
						|
+    wprintf(L"    Fail keyword: '%ls'\n", keyword);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintInvalidDocumentData(const char* document) {
 | 
						|
+    printf("    Fail document: '%s'\n", document);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintInvalidDocumentData(const wchar_t* document) {
 | 
						|
+    wprintf(L"    Fail document: '%ls'\n", document);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintValidatorPointersData(const char* s, const char* d, unsigned depth) {
 | 
						|
+    printf("    Sch: %*s'%s'\n    Doc: %*s'%s'\n", depth * 4, " ", s, depth * 4, " ", d);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintValidatorPointersData(const wchar_t* s, const wchar_t* d, unsigned depth) {
 | 
						|
+    wprintf(L"    Sch: %*ls'%ls'\n    Doc: %*ls'%ls'\n", depth * 4, L" ", s, depth * 4, L" ", d);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintSchemaIdsData(const char* base, const char* local, const char* resolved) {
 | 
						|
+    printf("    Resolving id: Base: '%s', Local: '%s', Resolved: '%s'\n", base, local, resolved);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintSchemaIdsData(const wchar_t* base, const wchar_t* local, const wchar_t* resolved) {
 | 
						|
+    wprintf(L"    Resolving id: Base: '%ls', Local: '%ls', Resolved: '%ls'\n", base, local, resolved);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintMethodData(const char* method) {
 | 
						|
+    printf("%s\n", method);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintMethodData(const char* method, bool b) {
 | 
						|
+    printf("%s, Data: '%s'\n", method, b ? "true" : "false");
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintMethodData(const char* method, int64_t i) {
 | 
						|
+    printf("%s, Data: '%" PRId64 "'\n", method, i);
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline void PrintInvalidKeyword(const wchar_t* keyword) {
 | 
						|
-    wprintf(L"Fail keyword: %ls\n", keyword);
 | 
						|
+inline void PrintMethodData(const char* method, uint64_t u) {
 | 
						|
+    printf("%s, Data: '%" PRIu64 "'\n", method, u);
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline void PrintInvalidDocument(const char* document) {
 | 
						|
-    printf("Fail document: %s\n\n", document);
 | 
						|
+inline void PrintMethodData(const char* method, double d) {
 | 
						|
+    printf("%s, Data: '%lf'\n", method, d);
 | 
						|
 }
 | 
						|
 
 | 
						|
-inline void PrintInvalidDocument(const wchar_t* document) {
 | 
						|
-    wprintf(L"Fail document: %ls\n\n", document);
 | 
						|
+inline void PrintMethodData(const char* method, const char* s) {
 | 
						|
+    printf("%s, Data: '%s'\n", method, s);
 | 
						|
 }
 | 
						|
 
 | 
						|
-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);
 | 
						|
+inline void PrintMethodData(const char* method, const wchar_t* s) {
 | 
						|
+    wprintf(L"%hs, Data: '%ls'\n", method, s);
 | 
						|
 }
 | 
						|
 
 | 
						|
-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);
 | 
						|
+inline void PrintMethodData(const char* method, const char* s1, const char* s2) {
 | 
						|
+    printf("%s, Data: '%s', '%s'\n", method, s1, s2);
 | 
						|
+}
 | 
						|
+
 | 
						|
+inline void PrintMethodData(const char* method, const wchar_t* s1, const wchar_t* s2) {
 | 
						|
+    wprintf(L"%hs, Data: '%ls', '%ls'\n", method, s1, s2);
 | 
						|
 }
 | 
						|
 
 | 
						|
 } // namespace internal
 | 
						|
 
 | 
						|
 #endif // RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
 
 | 
						|
-///////////////////////////////////////////////////////////////////////////////
 | 
						|
-// RAPIDJSON_INVALID_KEYWORD_RETURN
 | 
						|
-
 | 
						|
+#ifndef RAPIDJSON_SCHEMA_PRINT
 | 
						|
 #if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
 | 
						|
+#define RAPIDJSON_SCHEMA_PRINT(name, ...) internal::Print##name##Data(__VA_ARGS__)
 | 
						|
 #else
 | 
						|
-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
 | 
						|
+#define RAPIDJSON_SCHEMA_PRINT(name, ...)
 | 
						|
+#endif
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// RAPIDJSON_INVALID_KEYWORD_RETURN
 | 
						|
+
 | 
						|
+#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\
 | 
						|
 RAPIDJSON_MULTILINEMACRO_BEGIN\
 | 
						|
-    context.invalidKeyword = keyword.GetString();\
 | 
						|
-    RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
 | 
						|
+    context.invalidCode = code;\
 | 
						|
+    context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\
 | 
						|
+    RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, context.invalidKeyword);\
 | 
						|
     return false;\
 | 
						|
 RAPIDJSON_MULTILINEMACRO_END
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// ValidateFlag
 | 
						|
+
 | 
						|
+/*! \def RAPIDJSON_VALIDATE_DEFAULT_FLAGS
 | 
						|
+    \ingroup RAPIDJSON_CONFIG
 | 
						|
+    \brief User-defined kValidateDefaultFlags definition.
 | 
						|
+
 | 
						|
+    User can define this as any \c ValidateFlag combinations.
 | 
						|
+*/
 | 
						|
+#ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS
 | 
						|
+#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+//! Combination of validate flags
 | 
						|
+/*! \see
 | 
						|
+ */
 | 
						|
+enum ValidateFlag {
 | 
						|
+    kValidateNoFlags = 0,                                       //!< No flags are set.
 | 
						|
+    kValidateContinueOnErrorFlag = 1,                           //!< Don't stop after first validation error.
 | 
						|
+    kValidateReadFlag = 2,                                      //!< Validation is for a read semantic.
 | 
						|
+    kValidateWriteFlag = 4,                                     //!< Validation is for a write semantic.
 | 
						|
+    kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS    //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS
 | 
						|
+};
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// Specification
 | 
						|
+enum SchemaDraft {
 | 
						|
+    kDraftUnknown = -1,
 | 
						|
+    kDraftNone = 0,
 | 
						|
+    kDraft03 = 3,
 | 
						|
+    kDraftMin = 4,                       //!< Current minimum supported draft
 | 
						|
+    kDraft04 = 4,
 | 
						|
+    kDraft05 = 5,
 | 
						|
+    kDraftMax = 5,                       //!< Current maximum supported draft
 | 
						|
+    kDraft06 = 6,
 | 
						|
+    kDraft07 = 7,
 | 
						|
+    kDraft2019_09 = 8,
 | 
						|
+    kDraft2020_12 = 9
 | 
						|
+};
 | 
						|
+
 | 
						|
+enum OpenApiVersion {
 | 
						|
+    kVersionUnknown = -1,
 | 
						|
+    kVersionNone = 0,
 | 
						|
+    kVersionMin = 2,                      //!< Current minimum supported version
 | 
						|
+    kVersion20 = 2,
 | 
						|
+    kVersion30 = 3,
 | 
						|
+    kVersionMax = 3,                      //!< Current maximum supported version
 | 
						|
+    kVersion31 = 4,
 | 
						|
+};
 | 
						|
+
 | 
						|
+struct Specification {
 | 
						|
+    Specification(SchemaDraft d) : draft(d), oapi(kVersionNone) {}
 | 
						|
+    Specification(OpenApiVersion o) : oapi(o) {
 | 
						|
+        if (oapi == kVersion20) draft = kDraft04;
 | 
						|
+        else if (oapi == kVersion30) draft = kDraft05;
 | 
						|
+        else if (oapi == kVersion31) draft = kDraft2020_12;
 | 
						|
+        else draft = kDraft04;
 | 
						|
+    }
 | 
						|
+    ~Specification() {}
 | 
						|
+    bool IsSupported() const {
 | 
						|
+        return ((draft >= kDraftMin && draft <= kDraftMax) && ((oapi == kVersionNone) || (oapi >= kVersionMin && oapi <= kVersionMax)));
 | 
						|
+    }
 | 
						|
+    SchemaDraft draft;
 | 
						|
+    OpenApiVersion oapi;
 | 
						|
+};
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // Forward declarations
 | 
						|
 
 | 
						|
@@ -139,6 +249,8 @@ class ISchemaValidator {
 | 
						|
 public:
 | 
						|
     virtual ~ISchemaValidator() {}
 | 
						|
     virtual bool IsValid() const = 0;
 | 
						|
+    virtual void SetValidateFlags(unsigned flags) = 0;
 | 
						|
+    virtual unsigned GetValidateFlags() const = 0;
 | 
						|
 };
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
@@ -148,7 +260,7 @@ template <typename SchemaType>
 | 
						|
 class ISchemaStateFactory {
 | 
						|
 public:
 | 
						|
     virtual ~ISchemaStateFactory() {}
 | 
						|
-    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
 | 
						|
+    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0;
 | 
						|
     virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
 | 
						|
     virtual void* CreateHasher() = 0;
 | 
						|
     virtual uint64_t GetHashCode(void* hasher) = 0;
 | 
						|
@@ -157,6 +269,65 @@ public:
 | 
						|
     virtual void FreeState(void* p) = 0;
 | 
						|
 };
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// IValidationErrorHandler
 | 
						|
+
 | 
						|
+template <typename SchemaType>
 | 
						|
+class IValidationErrorHandler {
 | 
						|
+public:
 | 
						|
+    typedef typename SchemaType::Ch Ch;
 | 
						|
+    typedef typename SchemaType::SValue SValue;
 | 
						|
+
 | 
						|
+    virtual ~IValidationErrorHandler() {}
 | 
						|
+
 | 
						|
+    virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0;
 | 
						|
+    virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0;
 | 
						|
+    virtual void NotMultipleOf(double actual, const SValue& expected) = 0;
 | 
						|
+    virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+    virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+    virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+    virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+    virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+    virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0;
 | 
						|
+
 | 
						|
+    virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0;
 | 
						|
+    virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0;
 | 
						|
+    virtual void DoesNotMatch(const Ch* str, SizeType length) = 0;
 | 
						|
+
 | 
						|
+    virtual void DisallowedItem(SizeType index) = 0;
 | 
						|
+    virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;
 | 
						|
+    virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;
 | 
						|
+    virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;
 | 
						|
+
 | 
						|
+    virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;
 | 
						|
+    virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;
 | 
						|
+    virtual void StartMissingProperties() = 0;
 | 
						|
+    virtual void AddMissingProperty(const SValue& name) = 0;
 | 
						|
+    virtual bool EndMissingProperties() = 0;
 | 
						|
+    virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0;
 | 
						|
+    virtual void DisallowedProperty(const Ch* name, SizeType length) = 0;
 | 
						|
+
 | 
						|
+    virtual void StartDependencyErrors() = 0;
 | 
						|
+    virtual void StartMissingDependentProperties() = 0;
 | 
						|
+    virtual void AddMissingDependentProperty(const SValue& targetName) = 0;
 | 
						|
+    virtual void EndMissingDependentProperties(const SValue& sourceName) = 0;
 | 
						|
+    virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0;
 | 
						|
+    virtual bool EndDependencyErrors() = 0;
 | 
						|
+
 | 
						|
+    virtual void DisallowedValue(const ValidateErrorCode code) = 0;
 | 
						|
+    virtual void StartDisallowedType() = 0;
 | 
						|
+    virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0;
 | 
						|
+    virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0;
 | 
						|
+    virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0;
 | 
						|
+    virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
 | 
						|
+    virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
 | 
						|
+    virtual void MultipleOneOf(SizeType index1, SizeType index2) = 0;
 | 
						|
+    virtual void Disallowed() = 0;
 | 
						|
+    virtual void DisallowedWhenWriting() = 0;
 | 
						|
+    virtual void DisallowedWhenReading() = 0;
 | 
						|
+};
 | 
						|
+
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // Hasher
 | 
						|
 
 | 
						|
@@ -174,10 +345,10 @@ public:
 | 
						|
     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) { 
 | 
						|
-        Number n; 
 | 
						|
+    bool Double(double d) {
 | 
						|
+        Number n;
 | 
						|
         if (d < 0) 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;
 | 
						|
         return WriteNumber(n);
 | 
						|
     }
 | 
						|
@@ -261,6 +432,7 @@ template <typename SchemaDocumentType>
 | 
						|
 struct SchemaValidationContext {
 | 
						|
     typedef Schema<SchemaDocumentType> SchemaType;
 | 
						|
     typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
 | 
						|
+    typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
 | 
						|
     typedef typename SchemaType::ValueType ValueType;
 | 
						|
     typedef typename ValueType::Ch Ch;
 | 
						|
 
 | 
						|
@@ -270,11 +442,14 @@ struct SchemaValidationContext {
 | 
						|
         kPatternValidatorWithAdditionalProperty
 | 
						|
     };
 | 
						|
 
 | 
						|
-    SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
 | 
						|
+    SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s, unsigned fl = 0) :
 | 
						|
         factory(f),
 | 
						|
+        error_handler(eh),
 | 
						|
         schema(s),
 | 
						|
+        flags(fl),
 | 
						|
         valueSchema(),
 | 
						|
         invalidKeyword(),
 | 
						|
+        invalidCode(),
 | 
						|
         hasher(),
 | 
						|
         arrayElementHashCodes(),
 | 
						|
         validators(),
 | 
						|
@@ -295,13 +470,19 @@ struct SchemaValidationContext {
 | 
						|
         if (hasher)
 | 
						|
             factory.DestroryHasher(hasher);
 | 
						|
         if (validators) {
 | 
						|
-            for (SizeType i = 0; i < validatorCount; i++)
 | 
						|
-                factory.DestroySchemaValidator(validators[i]);
 | 
						|
+            for (SizeType i = 0; i < validatorCount; i++) {
 | 
						|
+                if (validators[i]) {
 | 
						|
+                    factory.DestroySchemaValidator(validators[i]);
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
             factory.FreeState(validators);
 | 
						|
         }
 | 
						|
         if (patternPropertiesValidators) {
 | 
						|
-            for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
 | 
						|
-                factory.DestroySchemaValidator(patternPropertiesValidators[i]);
 | 
						|
+            for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) {
 | 
						|
+                if (patternPropertiesValidators[i]) {
 | 
						|
+                    factory.DestroySchemaValidator(patternPropertiesValidators[i]);
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
             factory.FreeState(patternPropertiesValidators);
 | 
						|
         }
 | 
						|
         if (patternPropertiesSchemas)
 | 
						|
@@ -311,9 +492,12 @@ struct SchemaValidationContext {
 | 
						|
     }
 | 
						|
 
 | 
						|
     SchemaValidatorFactoryType& factory;
 | 
						|
+    ErrorHandlerType& error_handler;
 | 
						|
     const SchemaType* schema;
 | 
						|
+    unsigned flags;
 | 
						|
     const SchemaType* valueSchema;
 | 
						|
     const Ch* invalidKeyword;
 | 
						|
+    ValidateErrorCode invalidCode;
 | 
						|
     void* hasher; // Only validator access
 | 
						|
     void* arrayElementHashCodes; // Only validator access this
 | 
						|
     ISchemaValidator** validators;
 | 
						|
@@ -345,15 +529,23 @@ public:
 | 
						|
     typedef SchemaValidationContext<SchemaDocumentType> Context;
 | 
						|
     typedef Schema<SchemaDocumentType> SchemaType;
 | 
						|
     typedef GenericValue<EncodingType, AllocatorType> SValue;
 | 
						|
+    typedef IValidationErrorHandler<Schema> ErrorHandler;
 | 
						|
+    typedef GenericUri<ValueType, AllocatorType> UriType;
 | 
						|
     friend class GenericSchemaDocument<ValueType, AllocatorType>;
 | 
						|
 
 | 
						|
-    Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
 | 
						|
+    Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) :
 | 
						|
         allocator_(allocator),
 | 
						|
+        uri_(schemaDocument->GetURI(), *allocator),
 | 
						|
+        id_(id, allocator),
 | 
						|
+        spec_(schemaDocument->GetSpecification()),
 | 
						|
+        pointer_(p, allocator),
 | 
						|
+        typeless_(schemaDocument->GetTypeless()),
 | 
						|
         enum_(),
 | 
						|
         enumCount_(),
 | 
						|
         not_(),
 | 
						|
         type_((1 << kTotalSchemaType) - 1), // typeless
 | 
						|
         validatorCount_(),
 | 
						|
+        notValidatorIndex_(),
 | 
						|
         properties_(),
 | 
						|
         additionalPropertiesSchema_(),
 | 
						|
         patternProperties_(),
 | 
						|
@@ -377,15 +569,44 @@ public:
 | 
						|
         minLength_(0),
 | 
						|
         maxLength_(~SizeType(0)),
 | 
						|
         exclusiveMinimum_(false),
 | 
						|
-        exclusiveMaximum_(false)
 | 
						|
+        exclusiveMaximum_(false),
 | 
						|
+        defaultValueLength_(0),
 | 
						|
+        readOnly_(false),
 | 
						|
+        writeOnly_(false),
 | 
						|
+        nullable_(false)
 | 
						|
     {
 | 
						|
-        typedef typename SchemaDocumentType::ValueType ValueType;
 | 
						|
+        GenericStringBuffer<EncodingType> sb;
 | 
						|
+        p.StringifyUriFragment(sb);
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Schema", sb.GetString(), id.GetString());
 | 
						|
+
 | 
						|
         typedef typename ValueType::ConstValueIterator ConstValueIterator;
 | 
						|
         typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
 | 
						|
 
 | 
						|
+        // PR #1393
 | 
						|
+        // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite
 | 
						|
+        // recursion (with recursive schemas), since schemaDocument->getSchema() is always
 | 
						|
+        // checked before creating a new one. Don't cache typeless_, though.
 | 
						|
+        if (this != typeless_) {
 | 
						|
+          typedef typename SchemaDocumentType::SchemaEntry SchemaEntry;
 | 
						|
+          SchemaEntry *entry = schemaDocument->schemaMap_.template Push<SchemaEntry>();
 | 
						|
+          new (entry) SchemaEntry(pointer_, this, true, allocator_);
 | 
						|
+          schemaDocument->AddSchemaRefs(this);
 | 
						|
+        }
 | 
						|
+
 | 
						|
         if (!value.IsObject())
 | 
						|
             return;
 | 
						|
 
 | 
						|
+        // If we have an id property, resolve it with the in-scope id
 | 
						|
+        // Not supported for open api 2.0 or 3.0
 | 
						|
+        if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30)
 | 
						|
+        if (const ValueType* v = GetMember(value, GetIdString())) {
 | 
						|
+            if (v->IsString()) {
 | 
						|
+                UriType local(*v, allocator);
 | 
						|
+                id_ = local.Resolve(id_, allocator);
 | 
						|
+                    RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), v->GetString(), id_.GetString());
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+
 | 
						|
         if (const ValueType* v = GetMember(value, GetTypeString())) {
 | 
						|
             type_ = 0;
 | 
						|
             if (v->IsString())
 | 
						|
@@ -395,29 +616,33 @@ public:
 | 
						|
                     AddType(*itr);
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (const ValueType* v = GetMember(value, GetEnumString()))
 | 
						|
+        if (const ValueType* v = GetMember(value, GetEnumString())) {
 | 
						|
             if (v->IsArray() && v->Size() > 0) {
 | 
						|
                 enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
 | 
						|
                 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
 | 
						|
-                    typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
 | 
						|
-                    char buffer[256 + 24];
 | 
						|
-                    MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
 | 
						|
+                    typedef Hasher<EncodingType, MemoryPoolAllocator<AllocatorType> > EnumHasherType;
 | 
						|
+                    char buffer[256u + 24];
 | 
						|
+                    MemoryPoolAllocator<AllocatorType> hasherAllocator(buffer, sizeof(buffer));
 | 
						|
                     EnumHasherType h(&hasherAllocator, 256);
 | 
						|
                     itr->Accept(h);
 | 
						|
                     enum_[enumCount_++] = h.GetHashCode();
 | 
						|
                 }
 | 
						|
             }
 | 
						|
+        }
 | 
						|
 
 | 
						|
-        if (schemaDocument) {
 | 
						|
+        if (schemaDocument)
 | 
						|
             AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
 | 
						|
+
 | 
						|
+        // AnyOf, OneOf, Not not supported for open api 2.0
 | 
						|
+        if (schemaDocument && spec_.oapi != kVersion20) {
 | 
						|
             AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
 | 
						|
             AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
 | 
						|
-        }
 | 
						|
 
 | 
						|
-        if (const ValueType* v = GetMember(value, GetNotString())) {
 | 
						|
-            schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document);
 | 
						|
-            notValidatorIndex_ = validatorCount_;
 | 
						|
-            validatorCount_++;
 | 
						|
+            if (const ValueType* v = GetMember(value, GetNotString())) {
 | 
						|
+                schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_);
 | 
						|
+                notValidatorIndex_ = validatorCount_;
 | 
						|
+                validatorCount_++;
 | 
						|
+            }
 | 
						|
         }
 | 
						|
 
 | 
						|
         // Object
 | 
						|
@@ -432,12 +657,14 @@ public:
 | 
						|
             if (properties && properties->IsObject())
 | 
						|
                 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
 | 
						|
                     AddUniqueElement(allProperties, itr->name);
 | 
						|
-            
 | 
						|
+
 | 
						|
             if (required && required->IsArray())
 | 
						|
                 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
 | 
						|
                     if (itr->IsString())
 | 
						|
                         AddUniqueElement(allProperties, *itr);
 | 
						|
 
 | 
						|
+            // Dependencies not supported for open api 2.0 and 3.0
 | 
						|
+            if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30)
 | 
						|
             if (dependencies && dependencies->IsObject())
 | 
						|
                 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
 | 
						|
                     AddUniqueElement(allProperties, itr->name);
 | 
						|
@@ -453,7 +680,7 @@ public:
 | 
						|
                 for (SizeType i = 0; i < propertyCount_; i++) {
 | 
						|
                     new (&properties_[i]) Property();
 | 
						|
                     properties_[i].name = allProperties[i];
 | 
						|
-                    properties_[i].schema = GetTypeless();
 | 
						|
+                    properties_[i].schema = typeless_;
 | 
						|
                 }
 | 
						|
             }
 | 
						|
         }
 | 
						|
@@ -463,10 +690,12 @@ public:
 | 
						|
             for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
 | 
						|
                 SizeType index;
 | 
						|
                 if (FindPropertyIndex(itr->name, &index))
 | 
						|
-                    schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
 | 
						|
+                    schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
 | 
						|
             }
 | 
						|
         }
 | 
						|
 
 | 
						|
+        // PatternProperties not supported for open api 2.0 and 3.0
 | 
						|
+        if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30)
 | 
						|
         if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
 | 
						|
             PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
 | 
						|
             patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
 | 
						|
@@ -474,8 +703,9 @@ public:
 | 
						|
 
 | 
						|
             for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
 | 
						|
                 new (&patternProperties_[patternPropertyCount_]) PatternProperty();
 | 
						|
-                patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
 | 
						|
-                schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
 | 
						|
+                PointerType r = q.Append(itr->name, allocator_);
 | 
						|
+                patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name, schemaDocument, r);
 | 
						|
+                schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, r, itr->value, document, id_);
 | 
						|
                 patternPropertyCount_++;
 | 
						|
             }
 | 
						|
         }
 | 
						|
@@ -490,6 +720,8 @@ public:
 | 
						|
                     }
 | 
						|
                 }
 | 
						|
 
 | 
						|
+        // Dependencies not supported for open api 2.0 and 3.0
 | 
						|
+        if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30)
 | 
						|
         if (dependencies && dependencies->IsObject()) {
 | 
						|
             PointerType q = p.Append(GetDependenciesString(), allocator_);
 | 
						|
             hasDependencies_ = true;
 | 
						|
@@ -507,7 +739,7 @@ public:
 | 
						|
                     }
 | 
						|
                     else if (itr->value.IsObject()) {
 | 
						|
                         hasSchemaDependencies_ = true;
 | 
						|
-                        schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
 | 
						|
+                        schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_);
 | 
						|
                         properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
 | 
						|
                         validatorCount_++;
 | 
						|
                     }
 | 
						|
@@ -519,7 +751,7 @@ public:
 | 
						|
             if (v->IsBool())
 | 
						|
                 additionalProperties_ = v->GetBool();
 | 
						|
             else if (v->IsObject())
 | 
						|
-                schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
 | 
						|
+                schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_);
 | 
						|
         }
 | 
						|
 
 | 
						|
         AssignIfExist(minProperties_, value, GetMinPropertiesString());
 | 
						|
@@ -529,23 +761,25 @@ public:
 | 
						|
         if (const ValueType* v = GetMember(value, GetItemsString())) {
 | 
						|
             PointerType q = p.Append(GetItemsString(), allocator_);
 | 
						|
             if (v->IsObject()) // List validation
 | 
						|
-                schemaDocument->CreateSchema(&itemsList_, q, *v, document);
 | 
						|
+                schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_);
 | 
						|
             else if (v->IsArray()) { // Tuple validation
 | 
						|
                 itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
 | 
						|
                 SizeType index = 0;
 | 
						|
                 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
 | 
						|
-                    schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
 | 
						|
+                    schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_);
 | 
						|
             }
 | 
						|
         }
 | 
						|
 
 | 
						|
         AssignIfExist(minItems_, value, GetMinItemsString());
 | 
						|
         AssignIfExist(maxItems_, value, GetMaxItemsString());
 | 
						|
 
 | 
						|
+        // AdditionalItems not supported for openapi 2.0 and 3.0
 | 
						|
+        if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30)
 | 
						|
         if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
 | 
						|
             if (v->IsBool())
 | 
						|
                 additionalItems_ = v->GetBool();
 | 
						|
             else if (v->IsObject())
 | 
						|
-                schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
 | 
						|
+                schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_);
 | 
						|
         }
 | 
						|
 
 | 
						|
         AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
 | 
						|
@@ -555,7 +789,7 @@ public:
 | 
						|
         AssignIfExist(maxLength_, value, GetMaxLengthString());
 | 
						|
 
 | 
						|
         if (const ValueType* v = GetMember(value, GetPatternString()))
 | 
						|
-            pattern_ = CreatePattern(*v);
 | 
						|
+            pattern_ = CreatePattern(*v, schemaDocument, p.Append(GetPatternString(), allocator_));
 | 
						|
 
 | 
						|
         // Number
 | 
						|
         if (const ValueType* v = GetMember(value, GetMinimumString()))
 | 
						|
@@ -572,12 +806,33 @@ public:
 | 
						|
         if (const ValueType* v = GetMember(value, GetMultipleOfString()))
 | 
						|
             if (v->IsNumber() && v->GetDouble() > 0.0)
 | 
						|
                 multipleOf_.CopyFrom(*v, *allocator_);
 | 
						|
+
 | 
						|
+        // Default
 | 
						|
+        if (const ValueType* v = GetMember(value, GetDefaultValueString()))
 | 
						|
+            if (v->IsString())
 | 
						|
+                defaultValueLength_ = v->GetStringLength();
 | 
						|
+
 | 
						|
+        // ReadOnly - open api only (until draft 7 supported)
 | 
						|
+        // WriteOnly - open api 3 only (until draft 7 supported)
 | 
						|
+        // Both can't be true
 | 
						|
+        if (spec_.oapi != kVersionNone)
 | 
						|
+            AssignIfExist(readOnly_, value, GetReadOnlyString());
 | 
						|
+        if (spec_.oapi >= kVersion30)
 | 
						|
+            AssignIfExist(writeOnly_, value, GetWriteOnlyString());
 | 
						|
+        if (readOnly_ && writeOnly_)
 | 
						|
+            schemaDocument->SchemaError(kSchemaErrorReadOnlyAndWriteOnly, p);
 | 
						|
+
 | 
						|
+        // Nullable - open api 3 only
 | 
						|
+        // If true add 'null' as allowable type
 | 
						|
+        if (spec_.oapi >= kVersion30) {
 | 
						|
+            AssignIfExist(nullable_, value, GetNullableString());
 | 
						|
+            if (nullable_)
 | 
						|
+                AddType(GetNullString());
 | 
						|
+        }
 | 
						|
     }
 | 
						|
 
 | 
						|
     ~Schema() {
 | 
						|
-        if (allocator_) {
 | 
						|
-            allocator_->Free(enum_);
 | 
						|
-        }
 | 
						|
+        AllocatorType::Free(enum_);
 | 
						|
         if (properties_) {
 | 
						|
             for (SizeType i = 0; i < propertyCount_; i++)
 | 
						|
                 properties_[i].~Property();
 | 
						|
@@ -592,12 +847,29 @@ public:
 | 
						|
 #if RAPIDJSON_SCHEMA_HAS_REGEX
 | 
						|
         if (pattern_) {
 | 
						|
             pattern_->~RegexType();
 | 
						|
-            allocator_->Free(pattern_);
 | 
						|
+            AllocatorType::Free(pattern_);
 | 
						|
         }
 | 
						|
 #endif
 | 
						|
     }
 | 
						|
 
 | 
						|
+    const SValue& GetURI() const {
 | 
						|
+        return uri_;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    const UriType& GetId() const {
 | 
						|
+        return id_;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    const Specification& GetSpecification() const {
 | 
						|
+        return spec_;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    const PointerType& GetPointer() const {
 | 
						|
+        return pointer_;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     bool BeginValue(Context& context) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::BeginValue");
 | 
						|
         if (context.inArray) {
 | 
						|
             if (uniqueItems_)
 | 
						|
                 context.valueUniqueness = true;
 | 
						|
@@ -610,12 +882,18 @@ public:
 | 
						|
                 else if (additionalItemsSchema_)
 | 
						|
                     context.valueSchema = additionalItemsSchema_;
 | 
						|
                 else if (additionalItems_)
 | 
						|
-                    context.valueSchema = GetTypeless();
 | 
						|
-                else
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
 | 
						|
+                    context.valueSchema = typeless_;
 | 
						|
+                else {
 | 
						|
+                    context.error_handler.DisallowedItem(context.arrayElementIndex);
 | 
						|
+                    // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error
 | 
						|
+                    context.valueSchema = typeless_;
 | 
						|
+                    // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set
 | 
						|
+                    context.arrayElementIndex++;
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalItems);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else
 | 
						|
-                context.valueSchema = GetTypeless();
 | 
						|
+                context.valueSchema = typeless_;
 | 
						|
 
 | 
						|
             context.arrayElementIndex++;
 | 
						|
         }
 | 
						|
@@ -623,6 +901,8 @@ public:
 | 
						|
     }
 | 
						|
 
 | 
						|
     RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndValue");
 | 
						|
+        // Only check pattern properties if we have validators
 | 
						|
         if (context.patternPropertiesValidatorCount > 0) {
 | 
						|
             bool otherValid = false;
 | 
						|
             SizeType count = context.patternPropertiesValidatorCount;
 | 
						|
@@ -637,133 +917,178 @@ public:
 | 
						|
                 }
 | 
						|
 
 | 
						|
             if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
 | 
						|
-                if (!patternValid)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 | 
						|
+                if (!patternValid) {
 | 
						|
+                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
 | 
						|
-                if (!patternValid || !otherValid)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 | 
						|
+                if (!patternValid || !otherValid) {
 | 
						|
+                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties);
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
+            else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty)
 | 
						|
+                context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties);
 | 
						|
             }
 | 
						|
-            else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
 | 
						|
-                RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (enum_) {
 | 
						|
+        // For enums only check if we have a hasher
 | 
						|
+        if (enum_ && context.hasher) {
 | 
						|
             const uint64_t h = context.factory.GetHashCode(context.hasher);
 | 
						|
             for (SizeType i = 0; i < enumCount_; i++)
 | 
						|
                 if (enum_[i] == h)
 | 
						|
                     goto foundEnum;
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
 | 
						|
+            context.error_handler.DisallowedValue(kValidateErrorEnum);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorEnum);
 | 
						|
             foundEnum:;
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (allOf_.schemas)
 | 
						|
-            for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
 | 
						|
-                if (!context.validators[i]->IsValid())
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
 | 
						|
-        
 | 
						|
-        if (anyOf_.schemas) {
 | 
						|
-            for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
 | 
						|
-                if (context.validators[i]->IsValid())
 | 
						|
-                    goto foundAny;
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
 | 
						|
-            foundAny:;
 | 
						|
-        }
 | 
						|
-
 | 
						|
-        if (oneOf_.schemas) {
 | 
						|
-            bool oneValid = false;
 | 
						|
-            for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
 | 
						|
-                if (context.validators[i]->IsValid()) {
 | 
						|
-                    if (oneValid)
 | 
						|
-                        RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
 | 
						|
-                    else
 | 
						|
-                        oneValid = true;
 | 
						|
+        // Only check allOf etc if we have validators
 | 
						|
+        if (context.validatorCount > 0) {
 | 
						|
+            if (allOf_.schemas)
 | 
						|
+                for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
 | 
						|
+                    if (!context.validators[i]->IsValid()) {
 | 
						|
+                        context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
 | 
						|
+                        RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf);
 | 
						|
+                    }
 | 
						|
+
 | 
						|
+            if (anyOf_.schemas) {
 | 
						|
+                for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
 | 
						|
+                    if (context.validators[i]->IsValid())
 | 
						|
+                        goto foundAny;
 | 
						|
+                context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf);
 | 
						|
+                foundAny:;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            if (oneOf_.schemas) {
 | 
						|
+                bool oneValid = false;
 | 
						|
+                SizeType firstMatch = 0;
 | 
						|
+                for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
 | 
						|
+                    if (context.validators[i]->IsValid()) {
 | 
						|
+                        if (oneValid) {
 | 
						|
+                            context.error_handler.MultipleOneOf(firstMatch, i - oneOf_.begin);
 | 
						|
+                            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
 | 
						|
+                        } else {
 | 
						|
+                            oneValid = true;
 | 
						|
+                            firstMatch = i - oneOf_.begin;
 | 
						|
+                        }
 | 
						|
+                    }
 | 
						|
+                if (!oneValid) {
 | 
						|
+                    context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf);
 | 
						|
                 }
 | 
						|
-            if (!oneValid)
 | 
						|
-                RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
 | 
						|
-        }
 | 
						|
+            }
 | 
						|
 
 | 
						|
-        if (not_ && context.validators[notValidatorIndex_]->IsValid())
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
 | 
						|
+            if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
 | 
						|
+                context.error_handler.Disallowed();
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot);
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
 
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    bool Null(Context& context) const { 
 | 
						|
-        if (!(type_ & (1 << kNullSchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+    bool Null(Context& context) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Null");
 | 
						|
+        if (!(type_ & (1 << kNullSchemaType))) {
 | 
						|
+            DisallowedType(context, GetNullString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
-    
 | 
						|
-    bool Bool(Context& context, bool) const { 
 | 
						|
-        if (!(type_ & (1 << kBooleanSchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+
 | 
						|
+    bool Bool(Context& context, bool b) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Bool", b);
 | 
						|
+        if (!CheckBool(context, b))
 | 
						|
+            return false;
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool Int(Context& context, int i) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int", (int64_t)i);
 | 
						|
         if (!CheckInt(context, i))
 | 
						|
             return false;
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool Uint(Context& context, unsigned u) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint", (uint64_t)u);
 | 
						|
         if (!CheckUint(context, u))
 | 
						|
             return false;
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool Int64(Context& context, int64_t i) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int64", i);
 | 
						|
         if (!CheckInt(context, i))
 | 
						|
             return false;
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool Uint64(Context& context, uint64_t u) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint64", u);
 | 
						|
         if (!CheckUint(context, u))
 | 
						|
             return false;
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool Double(Context& context, double d) const {
 | 
						|
-        if (!(type_ & (1 << kNumberSchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Double", d);
 | 
						|
+        if (!(type_ & (1 << kNumberSchemaType))) {
 | 
						|
+            DisallowedType(context, GetNumberString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
 | 
						|
             return false;
 | 
						|
 
 | 
						|
         if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
 | 
						|
             return false;
 | 
						|
-        
 | 
						|
+
 | 
						|
         if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
 | 
						|
             return false;
 | 
						|
-        
 | 
						|
+
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
-    
 | 
						|
+
 | 
						|
     bool String(Context& context, const Ch* str, SizeType length, bool) const {
 | 
						|
-        if (!(type_ & (1 << kStringSchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::String", str);
 | 
						|
+        if (!(type_ & (1 << kStringSchemaType))) {
 | 
						|
+            DisallowedType(context, GetStringString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
 | 
						|
             SizeType count;
 | 
						|
             if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
 | 
						|
-                if (count < minLength_)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
 | 
						|
-                if (count > maxLength_)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
 | 
						|
+                if (count < minLength_) {
 | 
						|
+                    context.error_handler.TooShort(str, length, minLength_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinLength);
 | 
						|
+                }
 | 
						|
+                if (count > maxLength_) {
 | 
						|
+                    context.error_handler.TooLong(str, length, maxLength_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxLength);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (pattern_ && !IsPatternMatch(pattern_, str, length))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
 | 
						|
+        if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
 | 
						|
+            context.error_handler.DoesNotMatch(str, length);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPattern);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    bool StartObject(Context& context) const { 
 | 
						|
-        if (!(type_ & (1 << kObjectSchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+    bool StartObject(Context& context) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartObject");
 | 
						|
+        if (!(type_ & (1 << kObjectSchemaType))) {
 | 
						|
+            DisallowedType(context, GetObjectString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (hasDependencies_ || hasRequired_) {
 | 
						|
             context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
 | 
						|
@@ -779,20 +1104,24 @@ public:
 | 
						|
 
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
-    
 | 
						|
+
 | 
						|
     bool Key(Context& context, const Ch* str, SizeType len, bool) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Key", str);
 | 
						|
+
 | 
						|
         if (patternProperties_) {
 | 
						|
             context.patternPropertiesSchemaCount = 0;
 | 
						|
             for (SizeType i = 0; i < patternPropertyCount_; i++)
 | 
						|
-                if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len))
 | 
						|
+                if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
 | 
						|
                     context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
 | 
						|
+                    context.valueSchema = typeless_;
 | 
						|
+                }
 | 
						|
         }
 | 
						|
 
 | 
						|
-        SizeType index;
 | 
						|
+        SizeType index  = 0;
 | 
						|
         if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
 | 
						|
             if (context.patternPropertiesSchemaCount > 0) {
 | 
						|
                 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
 | 
						|
-                context.valueSchema = GetTypeless();
 | 
						|
+                context.valueSchema = typeless_;
 | 
						|
                 context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
 | 
						|
             }
 | 
						|
             else
 | 
						|
@@ -805,9 +1134,9 @@ public:
 | 
						|
         }
 | 
						|
 
 | 
						|
         if (additionalPropertiesSchema_) {
 | 
						|
-            if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
 | 
						|
+            if (context.patternPropertiesSchemaCount > 0) {
 | 
						|
                 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
 | 
						|
-                context.valueSchema = GetTypeless();
 | 
						|
+                context.valueSchema = typeless_;
 | 
						|
                 context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
 | 
						|
             }
 | 
						|
             else
 | 
						|
@@ -815,73 +1144,144 @@ public:
 | 
						|
             return true;
 | 
						|
         }
 | 
						|
         else if (additionalProperties_) {
 | 
						|
-            context.valueSchema = GetTypeless();
 | 
						|
+            context.valueSchema = typeless_;
 | 
						|
             return true;
 | 
						|
         }
 | 
						|
 
 | 
						|
-        if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
 | 
						|
+        if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties
 | 
						|
+            // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error
 | 
						|
+            context.valueSchema = typeless_;
 | 
						|
+            context.error_handler.DisallowedProperty(str, len);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalProperties);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool EndObject(Context& context, SizeType memberCount) const {
 | 
						|
-        if (hasRequired_)
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndObject");
 | 
						|
+        if (hasRequired_) {
 | 
						|
+            context.error_handler.StartMissingProperties();
 | 
						|
             for (SizeType index = 0; index < propertyCount_; index++)
 | 
						|
-                if (properties_[index].required)
 | 
						|
-                    if (!context.propertyExist[index])
 | 
						|
-                        RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
 | 
						|
+                if (properties_[index].required && !context.propertyExist[index])
 | 
						|
+                    if (properties_[index].schema->defaultValueLength_ == 0 )
 | 
						|
+                        context.error_handler.AddMissingProperty(properties_[index].name);
 | 
						|
+            if (context.error_handler.EndMissingProperties())
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired);
 | 
						|
+        }
 | 
						|
 
 | 
						|
-        if (memberCount < minProperties_)
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
 | 
						|
+        if (memberCount < minProperties_) {
 | 
						|
+            context.error_handler.TooFewProperties(memberCount, minProperties_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinProperties);
 | 
						|
+        }
 | 
						|
 
 | 
						|
-        if (memberCount > maxProperties_)
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
 | 
						|
+        if (memberCount > maxProperties_) {
 | 
						|
+            context.error_handler.TooManyProperties(memberCount, maxProperties_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxProperties);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (hasDependencies_) {
 | 
						|
-            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
 | 
						|
+            context.error_handler.StartDependencyErrors();
 | 
						|
+            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
 | 
						|
+                const Property& source = properties_[sourceIndex];
 | 
						|
                 if (context.propertyExist[sourceIndex]) {
 | 
						|
-                    if (properties_[sourceIndex].dependencies) {
 | 
						|
+                    if (source.dependencies) {
 | 
						|
+                        context.error_handler.StartMissingDependentProperties();
 | 
						|
                         for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
 | 
						|
-                            if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
 | 
						|
-                                RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
 | 
						|
+                            if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
 | 
						|
+                                context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
 | 
						|
+                        context.error_handler.EndMissingDependentProperties(source.name);
 | 
						|
+                    }
 | 
						|
+                    else if (source.dependenciesSchema) {
 | 
						|
+                        ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
 | 
						|
+                        if (!dependenciesValidator->IsValid())
 | 
						|
+                            context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
 | 
						|
                     }
 | 
						|
-                    else if (properties_[sourceIndex].dependenciesSchema)
 | 
						|
-                        if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
 | 
						|
-                            RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
 | 
						|
                 }
 | 
						|
+            }
 | 
						|
+            if (context.error_handler.EndDependencyErrors())
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies);
 | 
						|
         }
 | 
						|
 
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    bool StartArray(Context& context) const { 
 | 
						|
-        if (!(type_ & (1 << kArraySchemaType)))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
-
 | 
						|
+    bool StartArray(Context& context) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartArray");
 | 
						|
         context.arrayElementIndex = 0;
 | 
						|
-        context.inArray = true;
 | 
						|
+        context.inArray = true;  // Ensure we note that we are in an array
 | 
						|
+
 | 
						|
+        if (!(type_ & (1 << kArraySchemaType))) {
 | 
						|
+            DisallowedType(context, GetArrayString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         return CreateParallelValidator(context);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    bool EndArray(Context& context, SizeType elementCount) const { 
 | 
						|
+    bool EndArray(Context& context, SizeType elementCount) const {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndArray");
 | 
						|
         context.inArray = false;
 | 
						|
-        
 | 
						|
-        if (elementCount < minItems_)
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
 | 
						|
-        
 | 
						|
-        if (elementCount > maxItems_)
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
 | 
						|
+
 | 
						|
+        if (elementCount < minItems_) {
 | 
						|
+            context.error_handler.TooFewItems(elementCount, minItems_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems);
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        if (elementCount > maxItems_) {
 | 
						|
+            context.error_handler.TooManyItems(elementCount, maxItems_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
 | 
						|
+        switch (validateErrorCode) {
 | 
						|
+            case kValidateErrorMultipleOf:              return GetMultipleOfString();
 | 
						|
+            case kValidateErrorMaximum:                 return GetMaximumString();
 | 
						|
+            case kValidateErrorExclusiveMaximum:        return GetMaximumString(); // Same
 | 
						|
+            case kValidateErrorMinimum:                 return GetMinimumString();
 | 
						|
+            case kValidateErrorExclusiveMinimum:        return GetMinimumString(); // Same
 | 
						|
+
 | 
						|
+            case kValidateErrorMaxLength:               return GetMaxLengthString();
 | 
						|
+            case kValidateErrorMinLength:               return GetMinLengthString();
 | 
						|
+            case kValidateErrorPattern:                 return GetPatternString();
 | 
						|
+
 | 
						|
+            case kValidateErrorMaxItems:                return GetMaxItemsString();
 | 
						|
+            case kValidateErrorMinItems:                return GetMinItemsString();
 | 
						|
+            case kValidateErrorUniqueItems:             return GetUniqueItemsString();
 | 
						|
+            case kValidateErrorAdditionalItems:         return GetAdditionalItemsString();
 | 
						|
+
 | 
						|
+            case kValidateErrorMaxProperties:           return GetMaxPropertiesString();
 | 
						|
+            case kValidateErrorMinProperties:           return GetMinPropertiesString();
 | 
						|
+            case kValidateErrorRequired:                return GetRequiredString();
 | 
						|
+            case kValidateErrorAdditionalProperties:    return GetAdditionalPropertiesString();
 | 
						|
+            case kValidateErrorPatternProperties:       return GetPatternPropertiesString();
 | 
						|
+            case kValidateErrorDependencies:            return GetDependenciesString();
 | 
						|
+
 | 
						|
+            case kValidateErrorEnum:                    return GetEnumString();
 | 
						|
+            case kValidateErrorType:                    return GetTypeString();
 | 
						|
+
 | 
						|
+            case kValidateErrorOneOf:                   return GetOneOfString();
 | 
						|
+            case kValidateErrorOneOfMatch:              return GetOneOfString(); // Same
 | 
						|
+            case kValidateErrorAllOf:                   return GetAllOfString();
 | 
						|
+            case kValidateErrorAnyOf:                   return GetAnyOfString();
 | 
						|
+            case kValidateErrorNot:                     return GetNotString();
 | 
						|
+
 | 
						|
+            case kValidateErrorReadOnly:                return GetReadOnlyString();
 | 
						|
+            case kValidateErrorWriteOnly:               return GetWriteOnlyString();
 | 
						|
+
 | 
						|
+            default:                                    return GetNullString();
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+
 | 
						|
     // Generate functions for string literal according to Ch
 | 
						|
 #define RAPIDJSON_STRING_(name, ...) \
 | 
						|
     static const ValueType& Get##name##String() {\
 | 
						|
         static const Ch s[] = { __VA_ARGS__, '\0' };\
 | 
						|
-        static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\
 | 
						|
+        static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
 | 
						|
         return v;\
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -918,6 +1318,15 @@ public:
 | 
						|
     RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
 | 
						|
     RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
 | 
						|
     RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
 | 
						|
+    RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't')
 | 
						|
+    RAPIDJSON_STRING_(Schema, '$', 's', 'c', 'h', 'e', 'm', 'a')
 | 
						|
+    RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f')
 | 
						|
+    RAPIDJSON_STRING_(Id, 'i', 'd')
 | 
						|
+    RAPIDJSON_STRING_(Swagger, 's', 'w', 'a', 'g', 'g', 'e', 'r')
 | 
						|
+    RAPIDJSON_STRING_(OpenApi, 'o', 'p', 'e', 'n', 'a', 'p', 'i')
 | 
						|
+    RAPIDJSON_STRING_(ReadOnly, 'r', 'e', 'a', 'd', 'O', 'n', 'l', 'y')
 | 
						|
+    RAPIDJSON_STRING_(WriteOnly, 'w', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y')
 | 
						|
+    RAPIDJSON_STRING_(Nullable, 'n', 'u', 'l', 'l', 'a', 'b', 'l', 'e')
 | 
						|
 
 | 
						|
 #undef RAPIDJSON_STRING_
 | 
						|
 
 | 
						|
@@ -934,7 +1343,7 @@ private:
 | 
						|
     };
 | 
						|
 
 | 
						|
 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
 | 
						|
-        typedef internal::GenericRegex<EncodingType> RegexType;
 | 
						|
+        typedef internal::GenericRegex<EncodingType, AllocatorType> RegexType;
 | 
						|
 #elif RAPIDJSON_SCHEMA_USE_STDREGEX
 | 
						|
         typedef std::basic_regex<Ch> RegexType;
 | 
						|
 #else
 | 
						|
@@ -949,11 +1358,6 @@ private:
 | 
						|
         SizeType count;
 | 
						|
     };
 | 
						|
 
 | 
						|
-    static const SchemaType* GetTypeless() {
 | 
						|
-        static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
 | 
						|
-        return &typeless;
 | 
						|
-    }
 | 
						|
-
 | 
						|
     template <typename V1, typename V2>
 | 
						|
     void AddUniqueElement(V1& a, const V2& v) {
 | 
						|
         for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
 | 
						|
@@ -988,7 +1392,7 @@ private:
 | 
						|
                 out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
 | 
						|
                 memset(out.schemas, 0, sizeof(Schema*)* out.count);
 | 
						|
                 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, id_);
 | 
						|
                 out.begin = validatorCount_;
 | 
						|
                 validatorCount_ += out.count;
 | 
						|
             }
 | 
						|
@@ -997,10 +1401,11 @@ private:
 | 
						|
 
 | 
						|
 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
 | 
						|
     template <typename ValueType>
 | 
						|
-    RegexType* CreatePattern(const ValueType& value) {
 | 
						|
+    RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) {
 | 
						|
         if (value.IsString()) {
 | 
						|
-            RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
 | 
						|
+            RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_);
 | 
						|
             if (!r->IsValid()) {
 | 
						|
+                sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength());
 | 
						|
                 r->~RegexType();
 | 
						|
                 AllocatorType::Free(r);
 | 
						|
                 r = 0;
 | 
						|
@@ -1011,17 +1416,22 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
 | 
						|
-        return pattern->Search(str);
 | 
						|
+        GenericRegexSearch<RegexType> rs(*pattern);
 | 
						|
+        return rs.Search(str);
 | 
						|
     }
 | 
						|
 #elif RAPIDJSON_SCHEMA_USE_STDREGEX
 | 
						|
     template <typename ValueType>
 | 
						|
-    RegexType* CreatePattern(const ValueType& value) {
 | 
						|
-        if (value.IsString())
 | 
						|
+    RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) {
 | 
						|
+        if (value.IsString()) {
 | 
						|
+            RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
 | 
						|
             try {
 | 
						|
-                return new (allocator_->Malloc(sizeof(RegexType))) 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);
 | 
						|
             }
 | 
						|
-            catch (const std::regex_error&) {
 | 
						|
+            catch (const std::regex_error& e) {
 | 
						|
+                sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength());
 | 
						|
+                AllocatorType::Free(r);
 | 
						|
             }
 | 
						|
+        }
 | 
						|
         return 0;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -1031,7 +1441,9 @@ private:
 | 
						|
     }
 | 
						|
 #else
 | 
						|
     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; }
 | 
						|
 #endif // RAPIDJSON_SCHEMA_USE_STDREGEX
 | 
						|
@@ -1046,6 +1458,9 @@ private:
 | 
						|
         else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
 | 
						|
     }
 | 
						|
 
 | 
						|
+    // Creates parallel validators for allOf, anyOf, oneOf, not and schema dependencies, if required.
 | 
						|
+    // Also creates a hasher for enums and array uniqueness, if required.
 | 
						|
+    // Also a useful place to add type-independent error checks.
 | 
						|
     bool CreateParallelValidator(Context& context) const {
 | 
						|
         if (enum_ || context.arrayUniqueness)
 | 
						|
             context.hasher = context.factory.CreateHasher();
 | 
						|
@@ -1053,33 +1468,45 @@ private:
 | 
						|
         if (validatorCount_) {
 | 
						|
             RAPIDJSON_ASSERT(context.validators == 0);
 | 
						|
             context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
 | 
						|
+            std::memset(context.validators, 0, sizeof(ISchemaValidator*) * validatorCount_);
 | 
						|
             context.validatorCount = validatorCount_;
 | 
						|
 
 | 
						|
+            // Always return after first failure for these sub-validators
 | 
						|
             if (allOf_.schemas)
 | 
						|
-                CreateSchemaValidators(context, allOf_);
 | 
						|
+                CreateSchemaValidators(context, allOf_, false);
 | 
						|
 
 | 
						|
             if (anyOf_.schemas)
 | 
						|
-                CreateSchemaValidators(context, anyOf_);
 | 
						|
-            
 | 
						|
+                CreateSchemaValidators(context, anyOf_, false);
 | 
						|
+
 | 
						|
             if (oneOf_.schemas)
 | 
						|
-                CreateSchemaValidators(context, oneOf_);
 | 
						|
-            
 | 
						|
+                CreateSchemaValidators(context, oneOf_, false);
 | 
						|
+
 | 
						|
             if (not_)
 | 
						|
-                context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
 | 
						|
-            
 | 
						|
+                context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false);
 | 
						|
+
 | 
						|
             if (hasSchemaDependencies_) {
 | 
						|
                 for (SizeType i = 0; i < propertyCount_; i++)
 | 
						|
                     if (properties_[i].dependenciesSchema)
 | 
						|
-                        context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
 | 
						|
+                        context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false);
 | 
						|
             }
 | 
						|
         }
 | 
						|
 
 | 
						|
+        // Add any other type-independent checks here
 | 
						|
+        if (readOnly_ && (context.flags & kValidateWriteFlag)) {
 | 
						|
+            context.error_handler.DisallowedWhenWriting();
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorReadOnly);
 | 
						|
+        }
 | 
						|
+        if (writeOnly_ && (context.flags & kValidateReadFlag)) {
 | 
						|
+            context.error_handler.DisallowedWhenReading();
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorWriteOnly);
 | 
						|
+        }
 | 
						|
+
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
 | 
						|
+    void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const {
 | 
						|
         for (SizeType i = 0; i < schemas.count; i++)
 | 
						|
-            context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
 | 
						|
+            context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors);
 | 
						|
     }
 | 
						|
 
 | 
						|
     // O(n)
 | 
						|
@@ -1087,7 +1514,7 @@ private:
 | 
						|
         SizeType len = name.GetStringLength();
 | 
						|
         const Ch* str = name.GetString();
 | 
						|
         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))
 | 
						|
             {
 | 
						|
                 *outIndex = index;
 | 
						|
@@ -1096,17 +1523,30 @@ private:
 | 
						|
         return false;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    bool CheckBool(Context& context, bool) const {
 | 
						|
+        if (!(type_ & (1 << kBooleanSchemaType))) {
 | 
						|
+            DisallowedType(context, GetBooleanString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     bool CheckInt(Context& context, int64_t i) const {
 | 
						|
-        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
 | 
						|
+            DisallowedType(context, GetIntegerString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (!minimum_.IsNull()) {
 | 
						|
             if (minimum_.IsInt64()) {
 | 
						|
-                if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 | 
						|
+                if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
 | 
						|
+                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else if (minimum_.IsUint64()) {
 | 
						|
-                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
 | 
						|
+                context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64()
 | 
						|
             }
 | 
						|
             else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
 | 
						|
                 return false;
 | 
						|
@@ -1114,19 +1554,23 @@ private:
 | 
						|
 
 | 
						|
         if (!maximum_.IsNull()) {
 | 
						|
             if (maximum_.IsInt64()) {
 | 
						|
-                if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 | 
						|
+                if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
 | 
						|
+                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
-            else if (maximum_.IsUint64())
 | 
						|
-                /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64()
 | 
						|
+            else if (maximum_.IsUint64()) { }
 | 
						|
+                /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
 | 
						|
             else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
 | 
						|
                 return false;
 | 
						|
         }
 | 
						|
 
 | 
						|
         if (!multipleOf_.IsNull()) {
 | 
						|
             if (multipleOf_.IsUint64()) {
 | 
						|
-                if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 | 
						|
+                if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
 | 
						|
+                    context.error_handler.NotMultipleOf(i, multipleOf_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
 | 
						|
                 return false;
 | 
						|
@@ -1136,13 +1580,17 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool CheckUint(Context& context, uint64_t i) const {
 | 
						|
-        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 | 
						|
+        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
 | 
						|
+            DisallowedType(context, GetIntegerString());
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType);
 | 
						|
+        }
 | 
						|
 
 | 
						|
         if (!minimum_.IsNull()) {
 | 
						|
             if (minimum_.IsUint64()) {
 | 
						|
-                if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 | 
						|
+                if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
 | 
						|
+                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else if (minimum_.IsInt64())
 | 
						|
                 /* do nothing */; // i >= 0 > minimum.Getint64()
 | 
						|
@@ -1152,19 +1600,25 @@ private:
 | 
						|
 
 | 
						|
         if (!maximum_.IsNull()) {
 | 
						|
             if (maximum_.IsUint64()) {
 | 
						|
-                if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 | 
						|
+                if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
 | 
						|
+                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
+            else if (maximum_.IsInt64()) {
 | 
						|
+                context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 | 
						|
+                RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); // i >= 0 > maximum_
 | 
						|
             }
 | 
						|
-            else if (maximum_.IsInt64())
 | 
						|
-                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
 | 
						|
             else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
 | 
						|
                 return false;
 | 
						|
         }
 | 
						|
 
 | 
						|
         if (!multipleOf_.IsNull()) {
 | 
						|
             if (multipleOf_.IsUint64()) {
 | 
						|
-                if (i % multipleOf_.GetUint64() != 0)
 | 
						|
-                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 | 
						|
+                if (i % multipleOf_.GetUint64() != 0) {
 | 
						|
+                    context.error_handler.NotMultipleOf(i, multipleOf_);
 | 
						|
+                    RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf);
 | 
						|
+                }
 | 
						|
             }
 | 
						|
             else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
 | 
						|
                 return false;
 | 
						|
@@ -1174,14 +1628,18 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool CheckDoubleMinimum(Context& context, double d) const {
 | 
						|
-        if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 | 
						|
+        if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
 | 
						|
+            context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum);
 | 
						|
+        }
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool CheckDoubleMaximum(Context& context, double d) const {
 | 
						|
-        if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 | 
						|
+        if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
 | 
						|
+            context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
 | 
						|
+        }
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -1189,11 +1647,29 @@ private:
 | 
						|
         double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
 | 
						|
         double q = std::floor(a / b);
 | 
						|
         double r = a - q * b;
 | 
						|
-        if (r > 0.0)
 | 
						|
-            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 | 
						|
+        if (r > 0.0) {
 | 
						|
+            context.error_handler.NotMultipleOf(d, multipleOf_);
 | 
						|
+            RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf);
 | 
						|
+        }
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    void DisallowedType(Context& context, const ValueType& actualType) const {
 | 
						|
+        ErrorHandler& eh = context.error_handler;
 | 
						|
+        eh.StartDisallowedType();
 | 
						|
+
 | 
						|
+        if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
 | 
						|
+        if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
 | 
						|
+        if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
 | 
						|
+        if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
 | 
						|
+        if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
 | 
						|
+
 | 
						|
+        if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
 | 
						|
+        else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
 | 
						|
+
 | 
						|
+        eh.EndDisallowedType(actualType);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     struct Property {
 | 
						|
         Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
 | 
						|
         ~Property() { AllocatorType::Free(dependencies); }
 | 
						|
@@ -1207,7 +1683,7 @@ private:
 | 
						|
 
 | 
						|
     struct PatternProperty {
 | 
						|
         PatternProperty() : schema(), pattern() {}
 | 
						|
-        ~PatternProperty() { 
 | 
						|
+        ~PatternProperty() {
 | 
						|
             if (pattern) {
 | 
						|
                 pattern->~RegexType();
 | 
						|
                 AllocatorType::Free(pattern);
 | 
						|
@@ -1218,6 +1694,11 @@ private:
 | 
						|
     };
 | 
						|
 
 | 
						|
     AllocatorType* allocator_;
 | 
						|
+    SValue uri_;
 | 
						|
+    UriType id_;
 | 
						|
+    Specification spec_;
 | 
						|
+    PointerType pointer_;
 | 
						|
+    const SchemaType* typeless_;
 | 
						|
     uint64_t* enum_;
 | 
						|
     SizeType enumCount_;
 | 
						|
     SchemaArray allOf_;
 | 
						|
@@ -1258,6 +1739,12 @@ private:
 | 
						|
     SValue multipleOf_;
 | 
						|
     bool exclusiveMinimum_;
 | 
						|
     bool exclusiveMaximum_;
 | 
						|
+
 | 
						|
+    SizeType defaultValueLength_;
 | 
						|
+
 | 
						|
+    bool readOnly_;
 | 
						|
+    bool writeOnly_;
 | 
						|
+    bool nullable_;
 | 
						|
 };
 | 
						|
 
 | 
						|
 template<typename Stack, typename Ch>
 | 
						|
@@ -1267,7 +1754,7 @@ struct TokenHelper {
 | 
						|
         char buffer[21];
 | 
						|
         size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
 | 
						|
         for (size_t i = 0; i < length; i++)
 | 
						|
-            *documentStack.template Push<Ch>() = buffer[i];
 | 
						|
+            *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
 | 
						|
     }
 | 
						|
 };
 | 
						|
 
 | 
						|
@@ -1299,9 +1786,18 @@ template <typename SchemaDocumentType>
 | 
						|
 class IGenericRemoteSchemaDocumentProvider {
 | 
						|
 public:
 | 
						|
     typedef typename SchemaDocumentType::Ch Ch;
 | 
						|
+    typedef typename SchemaDocumentType::ValueType ValueType;
 | 
						|
+    typedef typename SchemaDocumentType::AllocatorType AllocatorType;
 | 
						|
 
 | 
						|
     virtual ~IGenericRemoteSchemaDocumentProvider() {}
 | 
						|
     virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
 | 
						|
+    virtual const SchemaDocumentType* GetRemoteDocument(const GenericUri<ValueType, AllocatorType> uri, Specification& spec) {
 | 
						|
+        // Default implementation just calls through for compatibility
 | 
						|
+        // Following line suppresses unused parameter warning
 | 
						|
+        (void)spec;
 | 
						|
+        // printf("GetRemoteDocument: %d %d\n", spec.draft, spec.oapi);
 | 
						|
+        return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength());
 | 
						|
+    }
 | 
						|
 };
 | 
						|
 
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
@@ -1326,6 +1822,9 @@ public:
 | 
						|
     typedef typename EncodingType::Ch Ch;
 | 
						|
     typedef internal::Schema<GenericSchemaDocument> SchemaType;
 | 
						|
     typedef GenericPointer<ValueType, Allocator> PointerType;
 | 
						|
+    typedef GenericValue<EncodingType, AllocatorType> GValue;
 | 
						|
+    typedef GenericUri<ValueType, Allocator> UriType;
 | 
						|
+    typedef GenericStringRef<Ch> StringRefType;
 | 
						|
     friend class internal::Schema<GenericSchemaDocument>;
 | 
						|
     template <typename, typename, typename>
 | 
						|
     friend class GenericSchemaValidator;
 | 
						|
@@ -1335,37 +1834,57 @@ public:
 | 
						|
         Compile a JSON document into schema document.
 | 
						|
 
 | 
						|
         \param document A JSON document as source.
 | 
						|
+        \param uri The base URI of this schema document for purposes of violation reporting.
 | 
						|
+        \param uriLength Length of \c name, in code points.
 | 
						|
         \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
 | 
						|
         \param allocator An optional allocator instance for allocating memory. Can be null.
 | 
						|
+        \param pointer An optional JSON pointer to the start of the schema document
 | 
						|
+        \param spec Optional schema draft or OpenAPI version. Used if no specification in document. Defaults to draft-04.
 | 
						|
     */
 | 
						|
-    explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
 | 
						|
+    explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
 | 
						|
+        IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0,
 | 
						|
+        const PointerType& pointer = PointerType(), // PR #1393
 | 
						|
+        const Specification& spec = Specification(kDraft04)) :
 | 
						|
         remoteProvider_(remoteProvider),
 | 
						|
         allocator_(allocator),
 | 
						|
         ownAllocator_(),
 | 
						|
         root_(),
 | 
						|
+        typeless_(),
 | 
						|
         schemaMap_(allocator, kInitialSchemaMapSize),
 | 
						|
-        schemaRef_(allocator, kInitialSchemaRefSize)
 | 
						|
+        schemaRef_(allocator, kInitialSchemaRefSize),
 | 
						|
+        spec_(spec),
 | 
						|
+        error_(kObjectType),
 | 
						|
+        currentError_()
 | 
						|
     {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::GenericSchemaDocument");
 | 
						|
         if (!allocator_)
 | 
						|
-            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
 | 
						|
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
 
 | 
						|
-        // Generate root schema, it will call CreateSchema() to create sub-schemas,
 | 
						|
-        // And call AddRefSchema() if there are $ref.
 | 
						|
-        CreateSchemaRecursive(&root_, PointerType(), document, document);
 | 
						|
+        Ch noUri[1] = {0};
 | 
						|
+        uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
 | 
						|
+        docId_ = UriType(uri_, allocator_);
 | 
						|
 
 | 
						|
-        // Resolve $ref
 | 
						|
-        while (!schemaRef_.Empty()) {
 | 
						|
-            SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
 | 
						|
-            if (const SchemaType* s = GetSchema(refEntry->target)) {
 | 
						|
-                if (refEntry->schema)
 | 
						|
-                    *refEntry->schema = s;
 | 
						|
-
 | 
						|
-                // Create entry in map if not exist
 | 
						|
-                if (!GetSchema(refEntry->source)) {
 | 
						|
-                    new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
 | 
						|
-                }
 | 
						|
-            }
 | 
						|
-            refEntry->~SchemaRefEntry();
 | 
						|
+        typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
 | 
						|
+        new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_);
 | 
						|
+
 | 
						|
+        // Establish the schema draft or open api version.
 | 
						|
+        // We only ever look for '$schema' or 'swagger' or 'openapi' at the root of the document.
 | 
						|
+        SetSchemaSpecification(document);
 | 
						|
+
 | 
						|
+        // Generate root schema, it will call CreateSchema() to create sub-schemas,
 | 
						|
+        // And call HandleRefSchema() if there are $ref.
 | 
						|
+        // PR #1393 use input pointer if supplied
 | 
						|
+        root_ = typeless_;
 | 
						|
+        if (pointer.GetTokenCount() == 0) {
 | 
						|
+            CreateSchemaRecursive(&root_, pointer, document, document, docId_);
 | 
						|
+        }
 | 
						|
+        else if (const ValueType* v = pointer.Get(document)) {
 | 
						|
+            CreateSchema(&root_, pointer, *v, document, docId_);
 | 
						|
+        }
 | 
						|
+        else {
 | 
						|
+            GenericStringBuffer<EncodingType> sb;
 | 
						|
+            pointer.StringifyUriFragment(sb);
 | 
						|
+            SchemaErrorValue(kSchemaErrorStartUnknown, PointerType(), sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)));
 | 
						|
         }
 | 
						|
 
 | 
						|
         RAPIDJSON_ASSERT(root_ != 0);
 | 
						|
@@ -1380,12 +1899,19 @@ public:
 | 
						|
         allocator_(rhs.allocator_),
 | 
						|
         ownAllocator_(rhs.ownAllocator_),
 | 
						|
         root_(rhs.root_),
 | 
						|
+        typeless_(rhs.typeless_),
 | 
						|
         schemaMap_(std::move(rhs.schemaMap_)),
 | 
						|
-        schemaRef_(std::move(rhs.schemaRef_))
 | 
						|
+        schemaRef_(std::move(rhs.schemaRef_)),
 | 
						|
+        uri_(std::move(rhs.uri_)),
 | 
						|
+        docId_(std::move(rhs.docId_)),
 | 
						|
+        spec_(rhs.spec_),
 | 
						|
+        error_(std::move(rhs.error_)),
 | 
						|
+        currentError_(std::move(rhs.currentError_))
 | 
						|
     {
 | 
						|
         rhs.remoteProvider_ = 0;
 | 
						|
         rhs.allocator_ = 0;
 | 
						|
         rhs.ownAllocator_ = 0;
 | 
						|
+        rhs.typeless_ = 0;
 | 
						|
     }
 | 
						|
 #endif
 | 
						|
 
 | 
						|
@@ -1394,24 +1920,92 @@ public:
 | 
						|
         while (!schemaMap_.Empty())
 | 
						|
             schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
 | 
						|
 
 | 
						|
+        if (typeless_) {
 | 
						|
+            typeless_->~SchemaType();
 | 
						|
+            Allocator::Free(typeless_);
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        // these may contain some allocator data so clear before deleting ownAllocator_
 | 
						|
+        uri_.SetNull();
 | 
						|
+        error_.SetNull();
 | 
						|
+        currentError_.SetNull();
 | 
						|
+
 | 
						|
         RAPIDJSON_DELETE(ownAllocator_);
 | 
						|
     }
 | 
						|
 
 | 
						|
+    const GValue& GetURI() const { return uri_; }
 | 
						|
+
 | 
						|
+    const Specification& GetSpecification() const { return spec_; }
 | 
						|
+    bool IsSupportedSpecification() const { return spec_.IsSupported(); }
 | 
						|
+
 | 
						|
+    //! Static method to get the specification of any schema document
 | 
						|
+    //  Returns kDraftNone if document is silent
 | 
						|
+    static const Specification GetSpecification(const ValueType& document) {
 | 
						|
+      SchemaDraft draft = GetSchemaDraft(document);
 | 
						|
+      if (draft != kDraftNone)
 | 
						|
+        return Specification(draft);
 | 
						|
+      else {
 | 
						|
+        OpenApiVersion oapi = GetOpenApiVersion(document);
 | 
						|
+        if (oapi != kVersionNone)
 | 
						|
+          return Specification(oapi);
 | 
						|
+      }
 | 
						|
+      return Specification(kDraftNone);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     //! Get the root schema.
 | 
						|
     const SchemaType& GetRoot() const { return *root_; }
 | 
						|
 
 | 
						|
-private:
 | 
						|
+    //! Gets the error object.
 | 
						|
+    GValue& GetError() { return error_; }
 | 
						|
+    const GValue& GetError() const { return error_; }
 | 
						|
+
 | 
						|
+    static const StringRefType& GetSchemaErrorKeyword(SchemaErrorCode schemaErrorCode) {
 | 
						|
+        switch (schemaErrorCode) {
 | 
						|
+            case kSchemaErrorStartUnknown:             return GetStartUnknownString();
 | 
						|
+            case kSchemaErrorRefPlainName:             return GetRefPlainNameString();
 | 
						|
+            case kSchemaErrorRefInvalid:               return GetRefInvalidString();
 | 
						|
+            case kSchemaErrorRefPointerInvalid:        return GetRefPointerInvalidString();
 | 
						|
+            case kSchemaErrorRefUnknown:               return GetRefUnknownString();
 | 
						|
+            case kSchemaErrorRefCyclical:              return GetRefCyclicalString();
 | 
						|
+            case kSchemaErrorRefNoRemoteProvider:      return GetRefNoRemoteProviderString();
 | 
						|
+            case kSchemaErrorRefNoRemoteSchema:        return GetRefNoRemoteSchemaString();
 | 
						|
+            case kSchemaErrorRegexInvalid:             return GetRegexInvalidString();
 | 
						|
+            case kSchemaErrorSpecUnknown:              return GetSpecUnknownString();
 | 
						|
+            case kSchemaErrorSpecUnsupported:          return GetSpecUnsupportedString();
 | 
						|
+            case kSchemaErrorSpecIllegal:              return GetSpecIllegalString();
 | 
						|
+            case kSchemaErrorReadOnlyAndWriteOnly:     return GetReadOnlyAndWriteOnlyString();
 | 
						|
+            default:                                   return GetNullString();
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Default error method
 | 
						|
+    void SchemaError(const SchemaErrorCode code, const PointerType& location) {
 | 
						|
+      currentError_ = GValue(kObjectType);
 | 
						|
+      AddCurrentError(code, location);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Method for error with single string value insert
 | 
						|
+    void SchemaErrorValue(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length) {
 | 
						|
+      currentError_ = GValue(kObjectType);
 | 
						|
+      currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_);
 | 
						|
+      AddCurrentError(code, location);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Method for error with invalid pointer
 | 
						|
+    void SchemaErrorPointer(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length, const PointerType& pointer) {
 | 
						|
+      currentError_ = GValue(kObjectType);
 | 
						|
+      currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_);
 | 
						|
+      currentError_.AddMember(GetOffsetString(), static_cast<SizeType>(pointer.GetParseErrorOffset() / sizeof(Ch)), *allocator_);
 | 
						|
+      AddCurrentError(code, location);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+  private:
 | 
						|
     //! Prohibit copying
 | 
						|
     GenericSchemaDocument(const GenericSchemaDocument&);
 | 
						|
     //! Prohibit assignment
 | 
						|
     GenericSchemaDocument& operator=(const GenericSchemaDocument&);
 | 
						|
 
 | 
						|
-    struct SchemaRefEntry {
 | 
						|
-        SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
 | 
						|
-        PointerType source;
 | 
						|
-        PointerType target;
 | 
						|
-        const SchemaType** schema;
 | 
						|
-    };
 | 
						|
+    typedef const PointerType* SchemaRefPtr; // PR #1393
 | 
						|
 
 | 
						|
     struct SchemaEntry {
 | 
						|
         SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
 | 
						|
@@ -1426,78 +2020,361 @@ private:
 | 
						|
         bool owned;
 | 
						|
     };
 | 
						|
 
 | 
						|
-    void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
 | 
						|
-        if (schema)
 | 
						|
-            *schema = SchemaType::GetTypeless();
 | 
						|
+    void AddErrorInstanceLocation(GValue& result, const PointerType& location) {
 | 
						|
+      GenericStringBuffer<EncodingType> sb;
 | 
						|
+      location.StringifyUriFragment(sb);
 | 
						|
+      GValue instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)), *allocator_);
 | 
						|
+      result.AddMember(GetInstanceRefString(), instanceRef, *allocator_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddError(GValue& keyword, GValue& error) {
 | 
						|
+      typename GValue::MemberIterator member = error_.FindMember(keyword);
 | 
						|
+      if (member == error_.MemberEnd())
 | 
						|
+        error_.AddMember(keyword, error, *allocator_);
 | 
						|
+      else {
 | 
						|
+        if (member->value.IsObject()) {
 | 
						|
+          GValue errors(kArrayType);
 | 
						|
+          errors.PushBack(member->value, *allocator_);
 | 
						|
+          member->value = errors;
 | 
						|
+        }
 | 
						|
+        member->value.PushBack(error, *allocator_);
 | 
						|
+      }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddCurrentError(const SchemaErrorCode code, const PointerType& location) {
 | 
						|
+      RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, GetSchemaErrorKeyword(code));
 | 
						|
+      currentError_.AddMember(GetErrorCodeString(), code, *allocator_);
 | 
						|
+      AddErrorInstanceLocation(currentError_, location);
 | 
						|
+      AddError(GValue(GetSchemaErrorKeyword(code)).Move(), currentError_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#define RAPIDJSON_STRING_(name, ...) \
 | 
						|
+    static const StringRefType& Get##name##String() {\
 | 
						|
+        static const Ch s[] = { __VA_ARGS__, '\0' };\
 | 
						|
+        static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
 | 
						|
+        return v;\
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
 | 
						|
+    RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e')
 | 
						|
+    RAPIDJSON_STRING_(Value, 'v', 'a', 'l', 'u', 'e')
 | 
						|
+    RAPIDJSON_STRING_(Offset, 'o', 'f', 'f', 's', 'e', 't')
 | 
						|
+
 | 
						|
+    RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
 | 
						|
+    RAPIDJSON_STRING_(SpecUnknown, 'S', 'p', 'e', 'c', 'U', 'n', 'k', 'n', 'o', 'w', 'n')
 | 
						|
+    RAPIDJSON_STRING_(SpecUnsupported, 'S', 'p', 'e', 'c', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd')
 | 
						|
+    RAPIDJSON_STRING_(SpecIllegal, 'S', 'p', 'e', 'c', 'I', 'l', 'l', 'e', 'g', 'a', 'l')
 | 
						|
+    RAPIDJSON_STRING_(StartUnknown, 'S', 't', 'a', 'r', 't', 'U', 'n', 'k', 'n', 'o', 'w', 'n')
 | 
						|
+    RAPIDJSON_STRING_(RefPlainName, 'R', 'e', 'f', 'P', 'l', 'a', 'i', 'n', 'N', 'a', 'm', 'e')
 | 
						|
+    RAPIDJSON_STRING_(RefInvalid, 'R', 'e', 'f', 'I', 'n', 'v', 'a', 'l', 'i', 'd')
 | 
						|
+    RAPIDJSON_STRING_(RefPointerInvalid, 'R', 'e', 'f', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'I', 'n', 'v', 'a', 'l', 'i', 'd')
 | 
						|
+    RAPIDJSON_STRING_(RefUnknown, 'R', 'e', 'f', 'U', 'n', 'k', 'n', 'o', 'w', 'n')
 | 
						|
+    RAPIDJSON_STRING_(RefCyclical, 'R', 'e', 'f', 'C', 'y', 'c', 'l', 'i', 'c', 'a', 'l')
 | 
						|
+    RAPIDJSON_STRING_(RefNoRemoteProvider, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r')
 | 
						|
+    RAPIDJSON_STRING_(RefNoRemoteSchema, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'S', 'c', 'h', 'e', 'm', 'a')
 | 
						|
+    RAPIDJSON_STRING_(ReadOnlyAndWriteOnly, 'R', 'e', 'a', 'd', 'O', 'n', 'l', 'y', 'A', 'n', 'd', 'W', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y')
 | 
						|
+    RAPIDJSON_STRING_(RegexInvalid, 'R', 'e', 'g', 'e', 'x', 'I', 'n', 'v', 'a', 'l', 'i', 'd')
 | 
						|
 
 | 
						|
+#undef RAPIDJSON_STRING_
 | 
						|
+
 | 
						|
+    // Static method to get schema draft of any schema document
 | 
						|
+    static SchemaDraft GetSchemaDraft(const ValueType& document) {
 | 
						|
+        static const Ch kDraft03String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '3', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' };
 | 
						|
+        static const Ch kDraft04String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '4', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' };
 | 
						|
+        static const Ch kDraft05String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '5', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' };
 | 
						|
+        static const Ch kDraft06String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '6', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' };
 | 
						|
+        static const Ch kDraft07String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '7', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' };
 | 
						|
+        static const Ch kDraft2019_09String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '1', '9', '-', '0', '9', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' };
 | 
						|
+        static const Ch kDraft2020_12String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '2', '0', '-', '1', '2', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' };
 | 
						|
+
 | 
						|
+        if (!document.IsObject()) {
 | 
						|
+            return kDraftNone;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        // Get the schema draft from the $schema keyword at the supplied location
 | 
						|
+        typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSchemaString());
 | 
						|
+        if (itr != document.MemberEnd()) {
 | 
						|
+            if (!itr->value.IsString()) return kDraftUnknown;
 | 
						|
+            const UriType draftUri(itr->value);
 | 
						|
+            // Check base uri for match
 | 
						|
+            if (draftUri.Match(UriType(kDraft04String), false)) return kDraft04;
 | 
						|
+            if (draftUri.Match(UriType(kDraft05String), false)) return kDraft05;
 | 
						|
+            if (draftUri.Match(UriType(kDraft06String), false)) return kDraft06;
 | 
						|
+            if (draftUri.Match(UriType(kDraft07String), false)) return kDraft07;
 | 
						|
+            if (draftUri.Match(UriType(kDraft03String), false)) return kDraft03;
 | 
						|
+            if (draftUri.Match(UriType(kDraft2019_09String), false)) return kDraft2019_09;
 | 
						|
+            if (draftUri.Match(UriType(kDraft2020_12String), false)) return kDraft2020_12;
 | 
						|
+            return kDraftUnknown;
 | 
						|
+        }
 | 
						|
+        // $schema not found
 | 
						|
+        return kDraftNone;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+
 | 
						|
+    // Get open api version of any schema document
 | 
						|
+    static OpenApiVersion GetOpenApiVersion(const ValueType& document) {
 | 
						|
+        static const Ch kVersion20String[] = { '2', '.', '0', '\0' };
 | 
						|
+        static const Ch kVersion30String[] = { '3', '.', '0', '.', '\0' }; // ignore patch level
 | 
						|
+        static const Ch kVersion31String[] = { '3', '.', '1', '.', '\0' }; // ignore patch level
 | 
						|
+        static SizeType len = internal::StrLen<Ch>(kVersion30String);
 | 
						|
+
 | 
						|
+        if (!document.IsObject()) {
 | 
						|
+            return kVersionNone;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        // Get the open api version from the swagger / openapi keyword at the supplied location
 | 
						|
+        typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSwaggerString());
 | 
						|
+        if (itr == document.MemberEnd()) itr = document.FindMember(SchemaType::GetOpenApiString());
 | 
						|
+        if (itr != document.MemberEnd()) {
 | 
						|
+            if (!itr->value.IsString()) return kVersionUnknown;
 | 
						|
+            const ValueType kVersion20Value(kVersion20String);
 | 
						|
+            if (kVersion20Value == itr->value) return kVersion20; // must match 2.0 exactly
 | 
						|
+            const ValueType kVersion30Value(kVersion30String);
 | 
						|
+            if (itr->value.GetStringLength() > len && kVersion30Value == ValueType(itr->value.GetString(), len)) return kVersion30; // must match 3.0.x
 | 
						|
+            const ValueType kVersion31Value(kVersion31String);
 | 
						|
+            if (itr->value.GetStringLength() > len && kVersion31Value == ValueType(itr->value.GetString(), len)) return kVersion31; // must match 3.1.x
 | 
						|
+            return kVersionUnknown;
 | 
						|
+        }
 | 
						|
+        // swagger or openapi not found
 | 
						|
+        return kVersionNone;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Get the draft of the schema or the open api version (which implies the draft).
 | 
						|
+    // Report an error if schema draft or open api version not supported or not recognized, or both in document, and carry on.
 | 
						|
+    void SetSchemaSpecification(const ValueType& document) {
 | 
						|
+        // Look for '$schema', 'swagger' or 'openapi' keyword at document root
 | 
						|
+        SchemaDraft docDraft = GetSchemaDraft(document);
 | 
						|
+        OpenApiVersion docOapi = GetOpenApiVersion(document);
 | 
						|
+        // Error if both in document
 | 
						|
+        if (docDraft != kDraftNone && docOapi != kVersionNone)
 | 
						|
+          SchemaError(kSchemaErrorSpecIllegal, PointerType());
 | 
						|
+        // Use document draft or open api version if present or use spec from constructor
 | 
						|
+        if (docDraft != kDraftNone)
 | 
						|
+            spec_ = Specification(docDraft);
 | 
						|
+        else if (docOapi != kVersionNone)
 | 
						|
+            spec_ = Specification(docOapi);
 | 
						|
+        // Error if draft or version unknown
 | 
						|
+        if (spec_.draft == kDraftUnknown || spec_.oapi == kVersionUnknown)
 | 
						|
+          SchemaError(kSchemaErrorSpecUnknown, PointerType());
 | 
						|
+        else if (!spec_.IsSupported())
 | 
						|
+            SchemaError(kSchemaErrorSpecUnsupported, PointerType());
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Changed by PR #1393
 | 
						|
+    void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) {
 | 
						|
         if (v.GetType() == kObjectType) {
 | 
						|
-            const SchemaType* s = GetSchema(pointer);
 | 
						|
-            if (!s)
 | 
						|
-                CreateSchema(schema, pointer, v, document);
 | 
						|
+            UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_);
 | 
						|
 
 | 
						|
             for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
 | 
						|
-                CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
 | 
						|
+                CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid);
 | 
						|
         }
 | 
						|
         else if (v.GetType() == kArrayType)
 | 
						|
             for (SizeType i = 0; i < v.Size(); i++)
 | 
						|
-                CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
 | 
						|
+                CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id);
 | 
						|
     }
 | 
						|
 
 | 
						|
-    void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
 | 
						|
+    // Changed by PR #1393
 | 
						|
+    const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) {
 | 
						|
         RAPIDJSON_ASSERT(pointer.IsValid());
 | 
						|
+        GenericStringBuffer<EncodingType> sb;
 | 
						|
+        pointer.StringifyUriFragment(sb);
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::CreateSchema", sb.GetString(), id.GetString());
 | 
						|
         if (v.IsObject()) {
 | 
						|
-            if (!HandleRefSchema(pointer, schema, v, document)) {
 | 
						|
-                SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
 | 
						|
-                new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
 | 
						|
+            if (const SchemaType* sc = GetSchema(pointer)) {
 | 
						|
+                if (schema)
 | 
						|
+                    *schema = sc;
 | 
						|
+                AddSchemaRefs(const_cast<SchemaType*>(sc));
 | 
						|
+            }
 | 
						|
+            else if (!HandleRefSchema(pointer, schema, v, document, id)) {
 | 
						|
+                // The new schema constructor adds itself and its $ref(s) to schemaMap_
 | 
						|
+                SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id);
 | 
						|
                 if (schema)
 | 
						|
                     *schema = s;
 | 
						|
+                return s->GetId();
 | 
						|
             }
 | 
						|
         }
 | 
						|
+        else {
 | 
						|
+            if (schema)
 | 
						|
+                *schema = typeless_;
 | 
						|
+            AddSchemaRefs(typeless_);
 | 
						|
+        }
 | 
						|
+        return id;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
 | 
						|
-        static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
 | 
						|
-        static const ValueType kRefValue(kRefString, 4);
 | 
						|
-
 | 
						|
-        typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
 | 
						|
+    // Changed by PR #1393
 | 
						|
+    // TODO should this return a UriType& ?
 | 
						|
+    bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) {
 | 
						|
+        typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString());
 | 
						|
         if (itr == v.MemberEnd())
 | 
						|
             return false;
 | 
						|
 
 | 
						|
+        GenericStringBuffer<EncodingType> sb;
 | 
						|
+        source.StringifyUriFragment(sb);
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::HandleRefSchema", sb.GetString(), id.GetString());
 | 
						|
+        // Resolve the source pointer to the $ref'ed schema (finally)
 | 
						|
+        new (schemaRef_.template Push<SchemaRefPtr>()) SchemaRefPtr(&source);
 | 
						|
+
 | 
						|
         if (itr->value.IsString()) {
 | 
						|
             SizeType len = itr->value.GetStringLength();
 | 
						|
-            if (len > 0) {
 | 
						|
-                const Ch* s = itr->value.GetString();
 | 
						|
-                SizeType i = 0;
 | 
						|
-                while (i < len && s[i] != '#') // Find the first #
 | 
						|
-                    i++;
 | 
						|
-
 | 
						|
-                if (i > 0) { // Remote reference, resolve immediately
 | 
						|
-                    if (remoteProvider_) {
 | 
						|
-                        if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) {
 | 
						|
-                            PointerType pointer(&s[i], len - i, allocator_);
 | 
						|
-                            if (pointer.IsValid()) {
 | 
						|
-                                if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
 | 
						|
-                                    if (schema)
 | 
						|
-                                        *schema = sc;
 | 
						|
+            if (len == 0)
 | 
						|
+                SchemaError(kSchemaErrorRefInvalid, source);
 | 
						|
+            else {
 | 
						|
+                // First resolve $ref against the in-scope id
 | 
						|
+                UriType scopeId = UriType(id, allocator_);
 | 
						|
+                UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_);
 | 
						|
+                RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), itr->value.GetString(), ref.GetString());
 | 
						|
+                // See if the resolved $ref minus the fragment matches a resolved id in this document
 | 
						|
+                // Search from the root. Returns the subschema in the document and its absolute JSON pointer.
 | 
						|
+                PointerType basePointer = PointerType();
 | 
						|
+                const ValueType *base = FindId(document, ref, basePointer, docId_, false);
 | 
						|
+                if (!base) {
 | 
						|
+                    // Remote reference - call the remote document provider
 | 
						|
+                    if (!remoteProvider_)
 | 
						|
+                        SchemaError(kSchemaErrorRefNoRemoteProvider, source);
 | 
						|
+                    else {
 | 
						|
+                        if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref, spec_)) {
 | 
						|
+                            const Ch* s = ref.GetFragString();
 | 
						|
+                            len = ref.GetFragStringLength();
 | 
						|
+                            if (len <= 1 || s[1] == '/') {
 | 
						|
+                                // JSON pointer fragment, absolute in the remote schema
 | 
						|
+                                const PointerType pointer(s, len, allocator_);
 | 
						|
+                                if (!pointer.IsValid())
 | 
						|
+                                    SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, pointer);
 | 
						|
+                                else {
 | 
						|
+                                    // Get the subschema
 | 
						|
+                                    if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) {
 | 
						|
+                                        if (schema)
 | 
						|
+                                            *schema = sc;
 | 
						|
+                                        AddSchemaRefs(const_cast<SchemaType *>(sc));
 | 
						|
+                                        return true;
 | 
						|
+                                    } else
 | 
						|
+                                        SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength());
 | 
						|
+                                }
 | 
						|
+                            } else
 | 
						|
+                                // Plain name fragment, not allowed in remote schema
 | 
						|
+                                SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len);
 | 
						|
+                        } else
 | 
						|
+                          SchemaErrorValue(kSchemaErrorRefNoRemoteSchema, source, ref.GetString(), ref.GetStringLength());
 | 
						|
+                    }
 | 
						|
+                }
 | 
						|
+                else { // Local reference
 | 
						|
+                    const Ch* s = ref.GetFragString();
 | 
						|
+                    len = ref.GetFragStringLength();
 | 
						|
+                    if (len <= 1 || s[1] == '/') {
 | 
						|
+                        // JSON pointer fragment, relative to the resolved URI
 | 
						|
+                        const PointerType relPointer(s, len, allocator_);
 | 
						|
+                        if (!relPointer.IsValid())
 | 
						|
+                            SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, relPointer);
 | 
						|
+                        else {
 | 
						|
+                            // Get the subschema
 | 
						|
+                            if (const ValueType *pv = relPointer.Get(*base)) {
 | 
						|
+                                // Now get the absolute JSON pointer by adding relative to base
 | 
						|
+                                PointerType pointer(basePointer, allocator_);
 | 
						|
+                                for (SizeType i = 0; i < relPointer.GetTokenCount(); i++)
 | 
						|
+                                    pointer = pointer.Append(relPointer.GetTokens()[i], allocator_);
 | 
						|
+                                if (IsCyclicRef(pointer))
 | 
						|
+                                    SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength());
 | 
						|
+                                else {
 | 
						|
+                                    // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
 | 
						|
+                                    // TODO: cache pointer <-> id mapping
 | 
						|
+                                    size_t unresolvedTokenIndex;
 | 
						|
+                                    scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
 | 
						|
+                                    CreateSchema(schema, pointer, *pv, document, scopeId);
 | 
						|
                                     return true;
 | 
						|
                                 }
 | 
						|
-                            }
 | 
						|
+                            } else
 | 
						|
+                                SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength());
 | 
						|
                         }
 | 
						|
+                    } else {
 | 
						|
+                        // Plain name fragment, relative to the resolved URI
 | 
						|
+                        // Not supported in open api 2.0 and 3.0
 | 
						|
+                        PointerType pointer(allocator_);
 | 
						|
+                        if (spec_.oapi == kVersion20 || spec_.oapi == kVersion30)
 | 
						|
+                            SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len);
 | 
						|
+                        // See if the fragment matches an id in this document.
 | 
						|
+                        // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer.
 | 
						|
+                        else if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) {
 | 
						|
+                            if (IsCyclicRef(pointer))
 | 
						|
+                                SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength());
 | 
						|
+                            else {
 | 
						|
+                                // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
 | 
						|
+                                // TODO: cache pointer <-> id mapping
 | 
						|
+                                size_t unresolvedTokenIndex;
 | 
						|
+                                scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
 | 
						|
+                                CreateSchema(schema, pointer, *pv, document, scopeId);
 | 
						|
+                                return true;
 | 
						|
+                            }
 | 
						|
+                        } else
 | 
						|
+                            SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength());
 | 
						|
                     }
 | 
						|
                 }
 | 
						|
-                else if (s[i] == '#') { // Local reference, defer resolution
 | 
						|
-                    PointerType pointer(&s[i], len - i, allocator_);
 | 
						|
-                    if (pointer.IsValid()) {
 | 
						|
-                        if (const ValueType* nv = pointer.Get(document))
 | 
						|
-                            if (HandleRefSchema(source, schema, *nv, document))
 | 
						|
-                                return true;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
 
 | 
						|
-                        new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
 | 
						|
-                        return true;
 | 
						|
-                    }
 | 
						|
+        // Invalid/Unknown $ref
 | 
						|
+        if (schema)
 | 
						|
+            *schema = typeless_;
 | 
						|
+        AddSchemaRefs(typeless_);
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Find the first subschema with a resolved 'id' that matches the specified URI.
 | 
						|
+    // If full specified use all URI else ignore fragment.
 | 
						|
+    // If found, return a pointer to the subschema and its JSON pointer.
 | 
						|
+    // TODO cache pointer <-> id mapping
 | 
						|
+    ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const {
 | 
						|
+        SizeType i = 0;
 | 
						|
+        ValueType* resval = 0;
 | 
						|
+        UriType tempuri = UriType(finduri, allocator_);
 | 
						|
+        UriType localuri = UriType(baseuri, allocator_);
 | 
						|
+        if (doc.GetType() == kObjectType) {
 | 
						|
+            // Establish the base URI of this object
 | 
						|
+            typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString());
 | 
						|
+            if (m != doc.MemberEnd() && m->value.GetType() == kStringType) {
 | 
						|
+                localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_);
 | 
						|
+            }
 | 
						|
+            // See if it matches
 | 
						|
+            if (localuri.Match(finduri, full)) {
 | 
						|
+                RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::FindId (match)", full ? localuri.GetString() : localuri.GetBaseString());
 | 
						|
+                resval = const_cast<ValueType *>(&doc);
 | 
						|
+                resptr = here;
 | 
						|
+                return resval;
 | 
						|
+            }
 | 
						|
+            // No match, continue looking
 | 
						|
+            for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) {
 | 
						|
+                if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) {
 | 
						|
+                    resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_));
 | 
						|
+                }
 | 
						|
+                if (resval) break;
 | 
						|
+            }
 | 
						|
+        } else if (doc.GetType() == kArrayType) {
 | 
						|
+            // Continue looking
 | 
						|
+            for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) {
 | 
						|
+                if (v->GetType() == kObjectType || v->GetType() == kArrayType) {
 | 
						|
+                    resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_));
 | 
						|
                 }
 | 
						|
+                if (resval) break;
 | 
						|
+                i++;
 | 
						|
             }
 | 
						|
         }
 | 
						|
+        return resval;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Added by PR #1393
 | 
						|
+    void AddSchemaRefs(SchemaType* schema) {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::AddSchemaRefs");
 | 
						|
+        while (!schemaRef_.Empty()) {
 | 
						|
+            SchemaRefPtr *ref = schemaRef_.template Pop<SchemaRefPtr>(1);
 | 
						|
+            SchemaEntry *entry = schemaMap_.template Push<SchemaEntry>();
 | 
						|
+            new (entry) SchemaEntry(**ref, schema, false, allocator_);
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Added by PR #1393
 | 
						|
+    bool IsCyclicRef(const PointerType& pointer) const {
 | 
						|
+        for (const SchemaRefPtr* ref = schemaRef_.template Bottom<SchemaRefPtr>(); ref != schemaRef_.template End<SchemaRefPtr>(); ++ref)
 | 
						|
+            if (pointer == **ref)
 | 
						|
+                return true;
 | 
						|
         return false;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -1515,6 +2392,8 @@ private:
 | 
						|
         return PointerType();
 | 
						|
     }
 | 
						|
 
 | 
						|
+    const SchemaType* GetTypeless() const { return typeless_; }
 | 
						|
+
 | 
						|
     static const size_t kInitialSchemaMapSize = 64;
 | 
						|
     static const size_t kInitialSchemaRefSize = 64;
 | 
						|
 
 | 
						|
@@ -1522,8 +2401,14 @@ private:
 | 
						|
     Allocator *allocator_;
 | 
						|
     Allocator *ownAllocator_;
 | 
						|
     const SchemaType* root_;                //!< Root schema.
 | 
						|
+    SchemaType* typeless_;
 | 
						|
     internal::Stack<Allocator> schemaMap_;  // Stores created Pointer -> Schemas
 | 
						|
-    internal::Stack<Allocator> schemaRef_;  // Stores Pointer from $ref and schema which holds the $ref
 | 
						|
+    internal::Stack<Allocator> schemaRef_;  // Stores Pointer(s) from $ref(s) until resolved
 | 
						|
+    GValue uri_;                            // Schema document URI
 | 
						|
+    UriType docId_;
 | 
						|
+    Specification spec_;
 | 
						|
+    GValue error_;
 | 
						|
+    GValue currentError_;
 | 
						|
 };
 | 
						|
 
 | 
						|
 //! GenericSchemaDocument using Value type.
 | 
						|
@@ -1552,13 +2437,16 @@ template <
 | 
						|
     typename StateAllocator = CrtAllocator>
 | 
						|
 class GenericSchemaValidator :
 | 
						|
     public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, 
 | 
						|
-    public internal::ISchemaValidator
 | 
						|
-{
 | 
						|
+    public internal::ISchemaValidator,
 | 
						|
+    public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
 | 
						|
 public:
 | 
						|
     typedef typename SchemaDocumentType::SchemaType SchemaType;
 | 
						|
     typedef typename SchemaDocumentType::PointerType PointerType;
 | 
						|
     typedef typename SchemaType::EncodingType EncodingType;
 | 
						|
+    typedef typename SchemaType::SValue SValue;
 | 
						|
     typedef typename EncodingType::Ch Ch;
 | 
						|
+    typedef GenericStringRef<Ch> StringRefType;
 | 
						|
+    typedef GenericValue<EncodingType, StateAllocator> ValueType;
 | 
						|
 
 | 
						|
     //! Constructor without output handler.
 | 
						|
     /*!
 | 
						|
@@ -1575,16 +2463,19 @@ public:
 | 
						|
         :
 | 
						|
         schemaDocument_(&schemaDocument),
 | 
						|
         root_(schemaDocument.GetRoot()),
 | 
						|
-        outputHandler_(GetNullHandler()),
 | 
						|
         stateAllocator_(allocator),
 | 
						|
         ownStateAllocator_(0),
 | 
						|
         schemaStack_(allocator, schemaStackCapacity),
 | 
						|
         documentStack_(allocator, documentStackCapacity),
 | 
						|
-        valid_(true)
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-        , depth_(0)
 | 
						|
-#endif
 | 
						|
+        outputHandler_(0),
 | 
						|
+        error_(kObjectType),
 | 
						|
+        currentError_(),
 | 
						|
+        missingDependents_(),
 | 
						|
+        valid_(true),
 | 
						|
+        flags_(kValidateDefaultFlags),
 | 
						|
+        depth_(0)
 | 
						|
     {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator");
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Constructor with output handler.
 | 
						|
@@ -1603,16 +2494,19 @@ public:
 | 
						|
         :
 | 
						|
         schemaDocument_(&schemaDocument),
 | 
						|
         root_(schemaDocument.GetRoot()),
 | 
						|
-        outputHandler_(outputHandler),
 | 
						|
         stateAllocator_(allocator),
 | 
						|
         ownStateAllocator_(0),
 | 
						|
         schemaStack_(allocator, schemaStackCapacity),
 | 
						|
         documentStack_(allocator, documentStackCapacity),
 | 
						|
-        valid_(true)
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-        , depth_(0)
 | 
						|
-#endif
 | 
						|
+        outputHandler_(&outputHandler),
 | 
						|
+        error_(kObjectType),
 | 
						|
+        currentError_(),
 | 
						|
+        missingDependents_(),
 | 
						|
+        valid_(true),
 | 
						|
+        flags_(kValidateDefaultFlags),
 | 
						|
+        depth_(0)
 | 
						|
     {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (output handler)");
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Destructor.
 | 
						|
@@ -1626,44 +2520,291 @@ public:
 | 
						|
         while (!schemaStack_.Empty())
 | 
						|
             PopSchema();
 | 
						|
         documentStack_.Clear();
 | 
						|
+        ResetError();
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Reset the error state.
 | 
						|
+    void ResetError() {
 | 
						|
+        error_.SetObject();
 | 
						|
+        currentError_.SetNull();
 | 
						|
+        missingDependents_.SetNull();
 | 
						|
         valid_ = true;
 | 
						|
     }
 | 
						|
 
 | 
						|
-    //! Checks whether the current state is valid.
 | 
						|
-    // Implementation of ISchemaValidator
 | 
						|
-    virtual bool IsValid() const { return valid_; }
 | 
						|
+    //! Implementation of ISchemaValidator
 | 
						|
+    void SetValidateFlags(unsigned flags) {
 | 
						|
+        flags_ = flags;
 | 
						|
+    }
 | 
						|
+    virtual unsigned GetValidateFlags() const {
 | 
						|
+        return flags_;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    virtual bool IsValid() const {
 | 
						|
+        if (!valid_) return false;
 | 
						|
+        if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false;
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+    //! End of Implementation of ISchemaValidator
 | 
						|
+
 | 
						|
+    //! Gets the error object.
 | 
						|
+    ValueType& GetError() { return error_; }
 | 
						|
+    const ValueType& GetError() const { return error_; }
 | 
						|
 
 | 
						|
     //! Gets the JSON pointer pointed to the invalid schema.
 | 
						|
+    //  If reporting all errors, the stack will be empty.
 | 
						|
     PointerType GetInvalidSchemaPointer() const {
 | 
						|
-        return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
 | 
						|
+        return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Gets the keyword of invalid schema.
 | 
						|
+    //  If reporting all errors, the stack will be empty, so return "errors".
 | 
						|
     const Ch* GetInvalidSchemaKeyword() const {
 | 
						|
-        return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
 | 
						|
+        if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword;
 | 
						|
+        if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString();
 | 
						|
+        return 0;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Gets the error code of invalid schema.
 | 
						|
+    //  If reporting all errors, the stack will be empty, so return kValidateErrors.
 | 
						|
+    ValidateErrorCode GetInvalidSchemaCode() const {
 | 
						|
+        if (!schemaStack_.Empty()) return CurrentContext().invalidCode;
 | 
						|
+        if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors;
 | 
						|
+        return kValidateErrorNone;
 | 
						|
     }
 | 
						|
 
 | 
						|
     //! Gets the JSON pointer pointed to the invalid value.
 | 
						|
+    //  If reporting all errors, the stack will be empty.
 | 
						|
     PointerType GetInvalidDocumentPointer() const {
 | 
						|
-        return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
 | 
						|
+        if (documentStack_.Empty()) {
 | 
						|
+            return PointerType();
 | 
						|
+        }
 | 
						|
+        else {
 | 
						|
+            return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
 | 
						|
+        }
 | 
						|
     }
 | 
						|
 
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
 | 
						|
-RAPIDJSON_MULTILINEMACRO_BEGIN\
 | 
						|
-    *documentStack_.template Push<Ch>() = '\0';\
 | 
						|
-    documentStack_.template Pop<Ch>(1);\
 | 
						|
-    internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
 | 
						|
-RAPIDJSON_MULTILINEMACRO_END
 | 
						|
-#else
 | 
						|
-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
 | 
						|
-#endif
 | 
						|
+    void NotMultipleOf(int64_t actual, const SValue& expected) {
 | 
						|
+        AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
 | 
						|
+    }
 | 
						|
+    void NotMultipleOf(uint64_t actual, const SValue& expected) {
 | 
						|
+        AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
 | 
						|
+    }
 | 
						|
+    void NotMultipleOf(double actual, const SValue& expected) {
 | 
						|
+        AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
 | 
						|
+    }
 | 
						|
+    void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 | 
						|
+    }
 | 
						|
+    void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 | 
						|
+    }
 | 
						|
+    void AboveMaximum(double actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 | 
						|
+    }
 | 
						|
+    void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 | 
						|
+    }
 | 
						|
+    void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 | 
						|
+    }
 | 
						|
+    void BelowMinimum(double actual, const SValue& expected, bool exclusive) {
 | 
						|
+        AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
 | 
						|
+            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void TooLong(const Ch* str, SizeType length, SizeType expected) {
 | 
						|
+        AddNumberError(kValidateErrorMaxLength,
 | 
						|
+            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
 | 
						|
+    }
 | 
						|
+    void TooShort(const Ch* str, SizeType length, SizeType expected) {
 | 
						|
+        AddNumberError(kValidateErrorMinLength,
 | 
						|
+            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
 | 
						|
+    }
 | 
						|
+    void DoesNotMatch(const Ch* str, SizeType length) {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+        AddCurrentError(kValidateErrorPattern);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DisallowedItem(SizeType index) {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
 | 
						|
+        AddCurrentError(kValidateErrorAdditionalItems, true);
 | 
						|
+    }
 | 
						|
+    void TooFewItems(SizeType actualCount, SizeType expectedCount) {
 | 
						|
+        AddNumberError(kValidateErrorMinItems,
 | 
						|
+            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 | 
						|
+    }
 | 
						|
+    void TooManyItems(SizeType actualCount, SizeType expectedCount) {
 | 
						|
+        AddNumberError(kValidateErrorMaxItems,
 | 
						|
+            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 | 
						|
+    }
 | 
						|
+    void DuplicateItems(SizeType index1, SizeType index2) {
 | 
						|
+        ValueType duplicates(kArrayType);
 | 
						|
+        duplicates.PushBack(index1, GetStateAllocator());
 | 
						|
+        duplicates.PushBack(index2, GetStateAllocator());
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
 | 
						|
+        AddCurrentError(kValidateErrorUniqueItems, true);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void TooManyProperties(SizeType actualCount, SizeType expectedCount) {
 | 
						|
+        AddNumberError(kValidateErrorMaxProperties,
 | 
						|
+            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 | 
						|
+    }
 | 
						|
+    void TooFewProperties(SizeType actualCount, SizeType expectedCount) {
 | 
						|
+        AddNumberError(kValidateErrorMinProperties,
 | 
						|
+            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 | 
						|
+    }
 | 
						|
+    void StartMissingProperties() {
 | 
						|
+        currentError_.SetArray();
 | 
						|
+    }
 | 
						|
+    void AddMissingProperty(const SValue& name) {
 | 
						|
+        currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+    }
 | 
						|
+    bool EndMissingProperties() {
 | 
						|
+        if (currentError_.Empty())
 | 
						|
+            return false;
 | 
						|
+        ValueType error(kObjectType);
 | 
						|
+        error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
 | 
						|
+        currentError_ = error;
 | 
						|
+        AddCurrentError(kValidateErrorRequired);
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+    void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {
 | 
						|
+        for (SizeType i = 0; i < count; ++i)
 | 
						|
+            MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
 | 
						|
+    }
 | 
						|
+    void DisallowedProperty(const Ch* name, SizeType length) {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+        AddCurrentError(kValidateErrorAdditionalProperties, true);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void StartDependencyErrors() {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+    }
 | 
						|
+    void StartMissingDependentProperties() {
 | 
						|
+        missingDependents_.SetArray();
 | 
						|
+    }
 | 
						|
+    void AddMissingDependentProperty(const SValue& targetName) {
 | 
						|
+        missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+    }
 | 
						|
+    void EndMissingDependentProperties(const SValue& sourceName) {
 | 
						|
+        if (!missingDependents_.Empty()) {
 | 
						|
+            // Create equivalent 'required' error
 | 
						|
+            ValueType error(kObjectType);
 | 
						|
+            ValidateErrorCode code = kValidateErrorRequired;
 | 
						|
+            error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator());
 | 
						|
+            AddErrorCode(error, code);
 | 
						|
+            AddErrorInstanceLocation(error, false);
 | 
						|
+            // When appending to a pointer ensure its allocator is used
 | 
						|
+            PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator());
 | 
						|
+            AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator()));
 | 
						|
+            ValueType wrapper(kObjectType);
 | 
						|
+            wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator());
 | 
						|
+            currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator());
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+    void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) {
 | 
						|
+        currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
 | 
						|
+            static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
 | 
						|
+    }
 | 
						|
+    bool EndDependencyErrors() {
 | 
						|
+        if (currentError_.ObjectEmpty())
 | 
						|
+            return false;
 | 
						|
+        ValueType error(kObjectType);
 | 
						|
+        error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
 | 
						|
+        currentError_ = error;
 | 
						|
+        AddCurrentError(kValidateErrorDependencies);
 | 
						|
+        return true;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void DisallowedValue(const ValidateErrorCode code = kValidateErrorEnum) {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        AddCurrentError(code);
 | 
						|
+    }
 | 
						|
+    void StartDisallowedType() {
 | 
						|
+        currentError_.SetArray();
 | 
						|
+    }
 | 
						|
+    void AddExpectedType(const typename SchemaType::ValueType& expectedType) {
 | 
						|
+        currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+    }
 | 
						|
+    void EndDisallowedType(const typename SchemaType::ValueType& actualType) {
 | 
						|
+        ValueType error(kObjectType);
 | 
						|
+        error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
 | 
						|
+        error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+        currentError_ = error;
 | 
						|
+        AddCurrentError(kValidateErrorType);
 | 
						|
+    }
 | 
						|
+    void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {
 | 
						|
+        // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf
 | 
						|
+        AddErrorArray(kValidateErrorAllOf, subvalidators, count);
 | 
						|
+        //for (SizeType i = 0; i < count; ++i) {
 | 
						|
+        //    MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
 | 
						|
+        //}
 | 
						|
+    }
 | 
						|
+    void NoneOf(ISchemaValidator** subvalidators, SizeType count) {
 | 
						|
+        AddErrorArray(kValidateErrorAnyOf, subvalidators, count);
 | 
						|
+    }
 | 
						|
+    void NotOneOf(ISchemaValidator** subvalidators, SizeType count) {
 | 
						|
+        AddErrorArray(kValidateErrorOneOf, subvalidators, count);
 | 
						|
+    }
 | 
						|
+    void MultipleOneOf(SizeType index1, SizeType index2) {
 | 
						|
+        ValueType matches(kArrayType);
 | 
						|
+        matches.PushBack(index1, GetStateAllocator());
 | 
						|
+        matches.PushBack(index2, GetStateAllocator());
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetMatchesString(), matches, GetStateAllocator());
 | 
						|
+        AddCurrentError(kValidateErrorOneOfMatch);
 | 
						|
+    }
 | 
						|
+    void Disallowed() {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        AddCurrentError(kValidateErrorNot);
 | 
						|
+    }
 | 
						|
+    void DisallowedWhenWriting() {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        AddCurrentError(kValidateErrorReadOnly);
 | 
						|
+    }
 | 
						|
+    void DisallowedWhenReading() {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        AddCurrentError(kValidateErrorWriteOnly);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#define RAPIDJSON_STRING_(name, ...) \
 | 
						|
+    static const StringRefType& Get##name##String() {\
 | 
						|
+        static const Ch s[] = { __VA_ARGS__, '\0' };\
 | 
						|
+        static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
 | 
						|
+        return v;\
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
 | 
						|
+    RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
 | 
						|
+    RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
 | 
						|
+    RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
 | 
						|
+    RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
 | 
						|
+    RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
 | 
						|
+    RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
 | 
						|
+    RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e')
 | 
						|
+    RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e')
 | 
						|
+    RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
 | 
						|
+    RAPIDJSON_STRING_(Matches, 'm', 'a', 't', 'c', 'h', 'e', 's')
 | 
						|
+
 | 
						|
+#undef RAPIDJSON_STRING_
 | 
						|
 
 | 
						|
 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
 | 
						|
     if (!valid_) return false; \
 | 
						|
-    if (!BeginValue() || !CurrentSchema().method arg1) {\
 | 
						|
-        RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
 | 
						|
-        return valid_ = false;\
 | 
						|
+    if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\
 | 
						|
+        *documentStack_.template Push<Ch>() = '\0';\
 | 
						|
+        documentStack_.template Pop<Ch>(1);\
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(InvalidDocument, documentStack_.template Bottom<Ch>());\
 | 
						|
+        valid_ = false;\
 | 
						|
+        return valid_;\
 | 
						|
     }
 | 
						|
 
 | 
						|
 #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
 | 
						|
@@ -1679,14 +2820,15 @@ RAPIDJSON_MULTILINEMACRO_END
 | 
						|
     }
 | 
						|
 
 | 
						|
 #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
 | 
						|
-    return valid_ = EndValue() && outputHandler_.method arg2
 | 
						|
+    valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\
 | 
						|
+    return valid_;
 | 
						|
 
 | 
						|
 #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
 | 
						|
     RAPIDJSON_SCHEMA_HANDLE_BEGIN_   (method, arg1);\
 | 
						|
     RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(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 Int(int i)         { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int,    (CurrentContext(), i), (i)); }
 | 
						|
     bool Uint(unsigned u)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint,   (CurrentContext(), u), (u)); }
 | 
						|
@@ -1699,51 +2841,69 @@ RAPIDJSON_MULTILINEMACRO_END
 | 
						|
                                     { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
 | 
						|
 
 | 
						|
     bool StartObject() {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartObject");
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
 | 
						|
-        return valid_ = outputHandler_.StartObject();
 | 
						|
+        valid_ = !outputHandler_ || outputHandler_->StartObject();
 | 
						|
+        return valid_;
 | 
						|
     }
 | 
						|
     
 | 
						|
     bool Key(const Ch* str, SizeType len, bool copy) {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::Key", str);
 | 
						|
         if (!valid_) return false;
 | 
						|
         AppendToken(str, len);
 | 
						|
-        if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
 | 
						|
+        if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) {
 | 
						|
+            valid_ = false;
 | 
						|
+            return valid_;
 | 
						|
+        }
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
 | 
						|
-        return valid_ = outputHandler_.Key(str, len, copy);
 | 
						|
+        valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
 | 
						|
+        return valid_;
 | 
						|
     }
 | 
						|
     
 | 
						|
-    bool EndObject(SizeType memberCount) { 
 | 
						|
+    bool EndObject(SizeType memberCount) {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndObject");
 | 
						|
         if (!valid_) return false;
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
 | 
						|
-        if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
 | 
						|
+        if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) { 
 | 
						|
+            valid_ = false; 
 | 
						|
+            return valid_; 
 | 
						|
+        }
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool StartArray() {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartArray");
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
 | 
						|
-        return valid_ = outputHandler_.StartArray();
 | 
						|
+        valid_ = !outputHandler_ || outputHandler_->StartArray();
 | 
						|
+        return valid_;
 | 
						|
     }
 | 
						|
     
 | 
						|
     bool EndArray(SizeType elementCount) {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndArray");
 | 
						|
         if (!valid_) return false;
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
 | 
						|
-        if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
 | 
						|
+        if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) {
 | 
						|
+            valid_ = false;
 | 
						|
+            return valid_;
 | 
						|
+        }
 | 
						|
         RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
 | 
						|
     }
 | 
						|
 
 | 
						|
-#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
 | 
						|
 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
 | 
						|
 #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
 | 
						|
 #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
 | 
						|
 
 | 
						|
     // Implementation of ISchemaStateFactory<SchemaType>
 | 
						|
-    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
 | 
						|
-        return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
+    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) {
 | 
						|
+        *documentStack_.template Push<Ch>() = '\0';
 | 
						|
+        documentStack_.template Pop<Ch>(1);
 | 
						|
+        ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),
 | 
						|
         depth_ + 1,
 | 
						|
-#endif
 | 
						|
         &GetStateAllocator());
 | 
						|
+        sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag);
 | 
						|
+        return sv;
 | 
						|
     }
 | 
						|
 
 | 
						|
     virtual void DestroySchemaValidator(ISchemaValidator* validator) {
 | 
						|
@@ -1771,8 +2931,9 @@ RAPIDJSON_MULTILINEMACRO_END
 | 
						|
     }
 | 
						|
 
 | 
						|
     virtual void FreeState(void* p) {
 | 
						|
-        return StateAllocator::Free(p);
 | 
						|
+        StateAllocator::Free(p);
 | 
						|
     }
 | 
						|
+    // End of implementation of ISchemaStateFactory<SchemaType>
 | 
						|
 
 | 
						|
 private:
 | 
						|
     typedef typename SchemaType::Context Context;
 | 
						|
@@ -1782,57 +2943,67 @@ private:
 | 
						|
     GenericSchemaValidator( 
 | 
						|
         const SchemaDocumentType& schemaDocument,
 | 
						|
         const SchemaType& root,
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
+        const char* basePath, size_t basePathSize,
 | 
						|
         unsigned depth,
 | 
						|
-#endif
 | 
						|
         StateAllocator* allocator = 0,
 | 
						|
         size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
 | 
						|
         size_t documentStackCapacity = kDefaultDocumentStackCapacity)
 | 
						|
         :
 | 
						|
         schemaDocument_(&schemaDocument),
 | 
						|
         root_(root),
 | 
						|
-        outputHandler_(GetNullHandler()),
 | 
						|
         stateAllocator_(allocator),
 | 
						|
         ownStateAllocator_(0),
 | 
						|
         schemaStack_(allocator, schemaStackCapacity),
 | 
						|
         documentStack_(allocator, documentStackCapacity),
 | 
						|
-        valid_(true)
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
-        , depth_(depth)
 | 
						|
-#endif
 | 
						|
+        outputHandler_(0),
 | 
						|
+        error_(kObjectType),
 | 
						|
+        currentError_(),
 | 
						|
+        missingDependents_(),
 | 
						|
+        valid_(true),
 | 
						|
+        flags_(kValidateDefaultFlags),
 | 
						|
+        depth_(depth)
 | 
						|
     {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (internal)", basePath && basePathSize ? basePath : "");
 | 
						|
+        if (basePath && basePathSize)
 | 
						|
+            memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
 | 
						|
     }
 | 
						|
 
 | 
						|
     StateAllocator& GetStateAllocator() {
 | 
						|
         if (!stateAllocator_)
 | 
						|
-            stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator());
 | 
						|
+            stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();
 | 
						|
         return *stateAllocator_;
 | 
						|
     }
 | 
						|
 
 | 
						|
+    bool GetContinueOnErrors() const {
 | 
						|
+        return flags_ & kValidateContinueOnErrorFlag;
 | 
						|
+    }
 | 
						|
+
 | 
						|
     bool BeginValue() {
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::BeginValue");
 | 
						|
         if (schemaStack_.Empty())
 | 
						|
             PushSchema(root_);
 | 
						|
         else {
 | 
						|
             if (CurrentContext().inArray)
 | 
						|
                 internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
 | 
						|
 
 | 
						|
-            if (!CurrentSchema().BeginValue(CurrentContext()))
 | 
						|
+            if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors())
 | 
						|
                 return false;
 | 
						|
 
 | 
						|
             SizeType count = CurrentContext().patternPropertiesSchemaCount;
 | 
						|
             const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
 | 
						|
             typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
 | 
						|
             bool valueUniqueness = CurrentContext().valueUniqueness;
 | 
						|
-            if (CurrentContext().valueSchema)
 | 
						|
-                PushSchema(*CurrentContext().valueSchema);
 | 
						|
+            RAPIDJSON_ASSERT(CurrentContext().valueSchema);
 | 
						|
+            PushSchema(*CurrentContext().valueSchema);
 | 
						|
 
 | 
						|
             if (count > 0) {
 | 
						|
                 CurrentContext().objectPatternValidatorType = patternValidatorType;
 | 
						|
                 ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
 | 
						|
                 SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
 | 
						|
                 va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
 | 
						|
+                std::memset(va, 0, sizeof(ISchemaValidator*) * count);
 | 
						|
                 for (SizeType i = 0; i < count; i++)
 | 
						|
-                    va[validatorCount++] = CreateSchemaValidator(*sa[i]);
 | 
						|
+                    va[validatorCount++] = CreateSchemaValidator(*sa[i], true);  // Inherit continueOnError
 | 
						|
             }
 | 
						|
 
 | 
						|
             CurrentContext().arrayUniqueness = valueUniqueness;
 | 
						|
@@ -1841,31 +3012,37 @@ private:
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool EndValue() {
 | 
						|
-        if (!CurrentSchema().EndValue(CurrentContext()))
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndValue");
 | 
						|
+        if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors())
 | 
						|
             return false;
 | 
						|
 
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
         GenericStringBuffer<EncodingType> sb;
 | 
						|
-        schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
 | 
						|
-
 | 
						|
+        schemaDocument_->GetPointer(&CurrentSchema()).StringifyUriFragment(sb);
 | 
						|
         *documentStack_.template Push<Ch>() = '\0';
 | 
						|
         documentStack_.template Pop<Ch>(1);
 | 
						|
-        internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-        uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
 | 
						|
+        RAPIDJSON_SCHEMA_PRINT(ValidatorPointers, sb.GetString(), documentStack_.template Bottom<Ch>(), depth_);
 | 
						|
+        void* hasher = CurrentContext().hasher;
 | 
						|
+        uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast<HasherType*>(hasher)->GetHashCode() : 0;
 | 
						|
         
 | 
						|
         PopSchema();
 | 
						|
 
 | 
						|
         if (!schemaStack_.Empty()) {
 | 
						|
             Context& context = CurrentContext();
 | 
						|
-            if (context.valueUniqueness) {
 | 
						|
+            // Only check uniqueness if there is a hasher
 | 
						|
+            if (hasher && context.valueUniqueness) {
 | 
						|
                 HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
 | 
						|
                 if (!a)
 | 
						|
                     CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
 | 
						|
                 for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
 | 
						|
-                    if (itr->GetUint64() == h)
 | 
						|
-                        RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
 | 
						|
+                    if (itr->GetUint64() == h) {
 | 
						|
+                        DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
 | 
						|
+                        // Cleanup before returning if continuing
 | 
						|
+                        if (GetContinueOnErrors()) {
 | 
						|
+                            a->PushBack(h, GetStateAllocator());
 | 
						|
+                            while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/');
 | 
						|
+                        }
 | 
						|
+                        RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems);
 | 
						|
+                    }
 | 
						|
                 a->PushBack(h, GetStateAllocator());
 | 
						|
             }
 | 
						|
         }
 | 
						|
@@ -1894,7 +3071,7 @@ private:
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
-    RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
 | 
						|
+    RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema, flags_); }
 | 
						|
     
 | 
						|
     RAPIDJSON_FORCEINLINE void PopSchema() {
 | 
						|
         Context* c = schemaStack_.template Pop<Context>(1);
 | 
						|
@@ -1905,28 +3082,98 @@ private:
 | 
						|
         c->~Context();
 | 
						|
     }
 | 
						|
 
 | 
						|
+    void AddErrorInstanceLocation(ValueType& result, bool parent) {
 | 
						|
+        GenericStringBuffer<EncodingType> sb;
 | 
						|
+        PointerType instancePointer = GetInvalidDocumentPointer();
 | 
						|
+        ((parent && instancePointer.GetTokenCount() > 0)
 | 
						|
+         ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
 | 
						|
+         : instancePointer).StringifyUriFragment(sb);
 | 
						|
+        ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
 | 
						|
+                              GetStateAllocator());
 | 
						|
+        result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) {
 | 
						|
+        GenericStringBuffer<EncodingType> sb;
 | 
						|
+        SizeType len = CurrentSchema().GetURI().GetStringLength();
 | 
						|
+        if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch));
 | 
						|
+        if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
 | 
						|
+        else GetInvalidSchemaPointer().StringifyUriFragment(sb);
 | 
						|
+        ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
 | 
						|
+            GetStateAllocator());
 | 
						|
+        result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddErrorCode(ValueType& result, const ValidateErrorCode code) {
 | 
						|
+        result.AddMember(GetErrorCodeString(), code, GetStateAllocator());
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddError(ValueType& keyword, ValueType& error) {
 | 
						|
+        typename ValueType::MemberIterator member = error_.FindMember(keyword);
 | 
						|
+        if (member == error_.MemberEnd())
 | 
						|
+            error_.AddMember(keyword, error, GetStateAllocator());
 | 
						|
+        else {
 | 
						|
+            if (member->value.IsObject()) {
 | 
						|
+                ValueType errors(kArrayType);
 | 
						|
+                errors.PushBack(member->value, GetStateAllocator());
 | 
						|
+                member->value = errors;
 | 
						|
+            }
 | 
						|
+            member->value.PushBack(error, GetStateAllocator());
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddCurrentError(const ValidateErrorCode code, bool parent = false) {
 | 
						|
+        AddErrorCode(currentError_, code);
 | 
						|
+        AddErrorInstanceLocation(currentError_, parent);
 | 
						|
+        AddErrorSchemaLocation(currentError_);
 | 
						|
+        AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void MergeError(ValueType& other) {
 | 
						|
+        for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {
 | 
						|
+            AddError(it->name, it->value);
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected,
 | 
						|
+        const typename SchemaType::ValueType& (*exclusive)() = 0) {
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
 | 
						|
+        currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
 | 
						|
+        if (exclusive)
 | 
						|
+            currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator());
 | 
						|
+        AddCurrentError(code);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    void AddErrorArray(const ValidateErrorCode code,
 | 
						|
+        ISchemaValidator** subvalidators, SizeType count) {
 | 
						|
+        ValueType errors(kArrayType);
 | 
						|
+        for (SizeType i = 0; i < count; ++i)
 | 
						|
+            errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
 | 
						|
+        currentError_.SetObject();
 | 
						|
+        currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
 | 
						|
+        AddCurrentError(code);
 | 
						|
+    }
 | 
						|
+
 | 
						|
     const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
 | 
						|
     Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
 | 
						|
     const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
 | 
						|
 
 | 
						|
-    static OutputHandler& GetNullHandler() {
 | 
						|
-        static OutputHandler nullHandler;
 | 
						|
-        return nullHandler;
 | 
						|
-    }
 | 
						|
-
 | 
						|
     static const size_t kDefaultSchemaStackCapacity = 1024;
 | 
						|
     static const size_t kDefaultDocumentStackCapacity = 256;
 | 
						|
     const SchemaDocumentType* schemaDocument_;
 | 
						|
     const SchemaType& root_;
 | 
						|
-    OutputHandler& outputHandler_;
 | 
						|
     StateAllocator* stateAllocator_;
 | 
						|
     StateAllocator* ownStateAllocator_;
 | 
						|
     internal::Stack<StateAllocator> schemaStack_;    //!< stack to store the current path of schema (BaseSchemaType *)
 | 
						|
     internal::Stack<StateAllocator> documentStack_;  //!< stack to store the current path of validating document (Ch)
 | 
						|
+    OutputHandler* outputHandler_;
 | 
						|
+    ValueType error_;
 | 
						|
+    ValueType currentError_;
 | 
						|
+    ValueType missingDependents_;
 | 
						|
     bool valid_;
 | 
						|
-#if RAPIDJSON_SCHEMA_VERBOSE
 | 
						|
+    unsigned flags_;
 | 
						|
     unsigned depth_;
 | 
						|
-#endif
 | 
						|
 };
 | 
						|
 
 | 
						|
 typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
 | 
						|
@@ -1954,13 +3201,14 @@ class SchemaValidatingReader {
 | 
						|
 public:
 | 
						|
     typedef typename SchemaDocumentType::PointerType PointerType;
 | 
						|
     typedef typename InputStream::Ch Ch;
 | 
						|
+    typedef GenericValue<SourceEncoding, StackAllocator> ValueType;
 | 
						|
 
 | 
						|
     //! Constructor
 | 
						|
     /*!
 | 
						|
         \param is Input stream.
 | 
						|
         \param sd Schema document.
 | 
						|
     */
 | 
						|
-    SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
 | 
						|
+    SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {}
 | 
						|
 
 | 
						|
     template <typename Handler>
 | 
						|
     bool operator()(Handler& handler) {
 | 
						|
@@ -1973,11 +3221,14 @@ public:
 | 
						|
             invalidSchemaPointer_ = PointerType();
 | 
						|
             invalidSchemaKeyword_ = 0;
 | 
						|
             invalidDocumentPointer_ = PointerType();
 | 
						|
+            error_.SetObject();
 | 
						|
         }
 | 
						|
         else {
 | 
						|
             invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
 | 
						|
             invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
 | 
						|
+            invalidSchemaCode_ = validator.GetInvalidSchemaCode();
 | 
						|
             invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
 | 
						|
+            error_.CopyFrom(validator.GetError(), allocator_);
 | 
						|
         }
 | 
						|
 
 | 
						|
         return parseResult_;
 | 
						|
@@ -1988,6 +3239,8 @@ public:
 | 
						|
     const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
 | 
						|
     const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
 | 
						|
     const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
 | 
						|
+    const ValueType& GetError() const { return error_; }
 | 
						|
+    ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; }
 | 
						|
 
 | 
						|
 private:
 | 
						|
     InputStream& is_;
 | 
						|
@@ -1997,6 +3250,9 @@ private:
 | 
						|
     PointerType invalidSchemaPointer_;
 | 
						|
     const Ch* invalidSchemaKeyword_;
 | 
						|
     PointerType invalidDocumentPointer_;
 | 
						|
+    ValidateErrorCode invalidSchemaCode_;
 | 
						|
+    StackAllocator allocator_;
 | 
						|
+    ValueType error_;
 | 
						|
     bool isValid_;
 | 
						|
 };
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/stream.h b/src/common/thirdparty/rapidjson/stream.h
 | 
						|
index fef82c252..1fd70915c 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/stream.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/stream.h
 | 
						|
@@ -1,15 +1,15 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
-// 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+//
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
 //
 | 
						|
 // http://opensource.org/licenses/MIT
 | 
						|
 //
 | 
						|
-// Unless required by applicable law or agreed to in writing, software distributed 
 | 
						|
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
						|
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
 // specific language governing permissions and limitations under the License.
 | 
						|
 
 | 
						|
 #include "rapidjson.h"
 | 
						|
@@ -100,6 +100,50 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
 | 
						|
         PutUnsafe(stream, c);
 | 
						|
 }
 | 
						|
 
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// GenericStreamWrapper
 | 
						|
+
 | 
						|
+//! A Stream Wrapper
 | 
						|
+/*! \tThis string stream is a wrapper for any stream by just forwarding any
 | 
						|
+    \treceived message to the origin stream.
 | 
						|
+    \note implements Stream concept
 | 
						|
+*/
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
						|
+RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+template <typename InputStream, typename Encoding = UTF8<> >
 | 
						|
+class GenericStreamWrapper {
 | 
						|
+public:
 | 
						|
+    typedef typename Encoding::Ch Ch;
 | 
						|
+    GenericStreamWrapper(InputStream& is): is_(is) {}
 | 
						|
+
 | 
						|
+    Ch Peek() const { return is_.Peek(); }
 | 
						|
+    Ch Take() { return is_.Take(); }
 | 
						|
+    size_t Tell() { return is_.Tell(); }
 | 
						|
+    Ch* PutBegin() { return is_.PutBegin(); }
 | 
						|
+    void Put(Ch ch) { is_.Put(ch); }
 | 
						|
+    void Flush() { is_.Flush(); }
 | 
						|
+    size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }
 | 
						|
+
 | 
						|
+    // wrapper for MemoryStream
 | 
						|
+    const Ch* Peek4() const { return is_.Peek4(); }
 | 
						|
+
 | 
						|
+    // wrapper for AutoUTFInputStream
 | 
						|
+    UTFType GetType() const { return is_.GetType(); }
 | 
						|
+    bool HasBOM() const { return is_.HasBOM(); }
 | 
						|
+
 | 
						|
+protected:
 | 
						|
+    InputStream& is_;
 | 
						|
+};
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 ///////////////////////////////////////////////////////////////////////////////
 | 
						|
 // StringStream
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/stringbuffer.h b/src/common/thirdparty/rapidjson/stringbuffer.h
 | 
						|
index 78f34d209..82ad3ca6b 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/stringbuffer.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/stringbuffer.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -78,8 +78,12 @@ public:
 | 
						|
         return stack_.template Bottom<Ch>();
 | 
						|
     }
 | 
						|
 
 | 
						|
+    //! Get the size of string in bytes in the string buffer.
 | 
						|
     size_t GetSize() const { return stack_.GetSize(); }
 | 
						|
 
 | 
						|
+    //! Get the length of string in Ch in the string buffer.
 | 
						|
+    size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
 | 
						|
+
 | 
						|
     static const size_t kDefaultCapacity = 256;
 | 
						|
     mutable internal::Stack<Allocator> stack_;
 | 
						|
 
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/uri.h b/src/common/thirdparty/rapidjson/uri.h
 | 
						|
new file mode 100644
 | 
						|
index 000000000..f93e508a4
 | 
						|
--- /dev/null
 | 
						|
+++ b/src/common/thirdparty/rapidjson/uri.h
 | 
						|
@@ -0,0 +1,481 @@
 | 
						|
+// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
+//
 | 
						|
+// (C) Copyright IBM Corporation 2021
 | 
						|
+//
 | 
						|
+// Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
+// in compliance with the License. You may obtain a copy of the License at
 | 
						|
+//
 | 
						|
+// http://opensource.org/licenses/MIT
 | 
						|
+//
 | 
						|
+// Unless required by applicable law or agreed to in writing, software distributed
 | 
						|
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
						|
+// specific language governing permissions and limitations under the License.
 | 
						|
+
 | 
						|
+#ifndef RAPIDJSON_URI_H_
 | 
						|
+#define RAPIDJSON_URI_H_
 | 
						|
+
 | 
						|
+#include "internal/strfunc.h"
 | 
						|
+
 | 
						|
+#if defined(__clang__)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
+
 | 
						|
+///////////////////////////////////////////////////////////////////////////////
 | 
						|
+// GenericUri
 | 
						|
+
 | 
						|
+template <typename ValueType, typename Allocator=CrtAllocator>
 | 
						|
+class GenericUri {
 | 
						|
+public:
 | 
						|
+    typedef typename ValueType::Ch Ch;
 | 
						|
+#if RAPIDJSON_HAS_STDSTRING
 | 
						|
+    typedef std::basic_string<Ch> String;
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    //! Constructors
 | 
						|
+    GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+        Parse(uri, len);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+        Parse(uri, internal::StrLen<Ch>(uri));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Use with specializations of GenericValue
 | 
						|
+    template<typename T> GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+        const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h
 | 
						|
+        Parse(u, internal::StrLen<Ch>(u));
 | 
						|
+    }
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_STDSTRING
 | 
						|
+    GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+        Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
 | 
						|
+    }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    //! Copy constructor
 | 
						|
+    GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() {
 | 
						|
+        *this = rhs;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Copy constructor
 | 
						|
+    GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
						|
+        *this = rhs;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Destructor.
 | 
						|
+    ~GenericUri() {
 | 
						|
+        Free();
 | 
						|
+        RAPIDJSON_DELETE(ownAllocator_);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Assignment operator
 | 
						|
+    GenericUri& operator=(const GenericUri& rhs) {
 | 
						|
+        if (this != &rhs) {
 | 
						|
+            // Do not delete ownAllocator
 | 
						|
+            Free();
 | 
						|
+            Allocate(rhs.GetStringLength());
 | 
						|
+            auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
 | 
						|
+            path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
 | 
						|
+            query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
 | 
						|
+            frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
 | 
						|
+            base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
 | 
						|
+            uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
 | 
						|
+            CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
 | 
						|
+        }
 | 
						|
+        return *this;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Getters
 | 
						|
+    // Use with specializations of GenericValue
 | 
						|
+    template<typename T> void Get(T& uri, Allocator& allocator) {
 | 
						|
+        uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    const Ch* GetString() const { return uri_; }
 | 
						|
+    SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
 | 
						|
+    const Ch* GetBaseString() const { return base_; }
 | 
						|
+    SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
 | 
						|
+    const Ch* GetSchemeString() const { return scheme_; }
 | 
						|
+    SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); }
 | 
						|
+    const Ch* GetAuthString() const { return auth_; }
 | 
						|
+    SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
 | 
						|
+    const Ch* GetPathString() const { return path_; }
 | 
						|
+    SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
 | 
						|
+    const Ch* GetQueryString() const { return query_; }
 | 
						|
+    SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
 | 
						|
+    const Ch* GetFragString() const { return frag_; }
 | 
						|
+    SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
 | 
						|
+
 | 
						|
+#if RAPIDJSON_HAS_STDSTRING
 | 
						|
+    static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); }
 | 
						|
+    static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); }
 | 
						|
+    static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); }
 | 
						|
+    static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); }
 | 
						|
+    static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); }
 | 
						|
+    static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); }
 | 
						|
+    static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+    //! Equality operators
 | 
						|
+    bool operator==(const GenericUri& rhs) const {
 | 
						|
+        return Match(rhs, true);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    bool operator!=(const GenericUri& rhs) const {
 | 
						|
+        return !Match(rhs, true);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    bool Match(const GenericUri& uri, bool full = true) const {
 | 
						|
+        Ch* s1;
 | 
						|
+        Ch* s2;
 | 
						|
+        if (full) {
 | 
						|
+            s1 = uri_;
 | 
						|
+            s2 = uri.uri_;
 | 
						|
+        } else {
 | 
						|
+            s1 = base_;
 | 
						|
+            s2 = uri.base_;
 | 
						|
+        }
 | 
						|
+        if (s1 == s2) return true;
 | 
						|
+        if (s1 == 0 || s2 == 0) return false;
 | 
						|
+        return internal::StrCmp<Ch>(s1, s2) == 0;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Resolve this URI against another (base) URI in accordance with URI resolution rules.
 | 
						|
+    // See https://tools.ietf.org/html/rfc3986
 | 
						|
+    // Use for resolving an id or $ref with an in-scope id.
 | 
						|
+    // Returns a new GenericUri for the resolved URI.
 | 
						|
+    GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) {
 | 
						|
+        GenericUri resuri;
 | 
						|
+        resuri.allocator_ = allocator;
 | 
						|
+        // Ensure enough space for combining paths
 | 
						|
+        resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash
 | 
						|
+
 | 
						|
+        if (!(GetSchemeStringLength() == 0)) {
 | 
						|
+            // Use all of this URI
 | 
						|
+            resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
 | 
						|
+            resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
 | 
						|
+            resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
						|
+            resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
						|
+            resuri.RemoveDotSegments();
 | 
						|
+        } else {
 | 
						|
+            // Use the base scheme
 | 
						|
+            resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
 | 
						|
+            if (!(GetAuthStringLength() == 0)) {
 | 
						|
+                // Use this auth, path, query
 | 
						|
+                resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
 | 
						|
+                resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
						|
+                resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
						|
+                resuri.RemoveDotSegments();
 | 
						|
+            } else {
 | 
						|
+                // Use the base auth
 | 
						|
+                resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
 | 
						|
+                if (GetPathStringLength() == 0) {
 | 
						|
+                    // Use the base path
 | 
						|
+                    resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
 | 
						|
+                    if (GetQueryStringLength() == 0) {
 | 
						|
+                        // Use the base query
 | 
						|
+                        resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
 | 
						|
+                    } else {
 | 
						|
+                        // Use this query
 | 
						|
+                        resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
						|
+                    }
 | 
						|
+                } else {
 | 
						|
+                    if (path_[0] == '/') {
 | 
						|
+                        // Absolute path - use all of this path
 | 
						|
+                        resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
						|
+                        resuri.RemoveDotSegments();
 | 
						|
+                    } else {
 | 
						|
+                        // Relative path - append this path to base path after base path's last slash
 | 
						|
+                        size_t pos = 0;
 | 
						|
+                        if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) {
 | 
						|
+                            resuri.path_[pos] = '/';
 | 
						|
+                            pos++;
 | 
						|
+                        }
 | 
						|
+                        size_t lastslashpos = baseuri.GetPathStringLength();
 | 
						|
+                        while (lastslashpos > 0) {
 | 
						|
+                            if (baseuri.path_[lastslashpos - 1] == '/') break;
 | 
						|
+                            lastslashpos--;
 | 
						|
+                        }
 | 
						|
+                        std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch));
 | 
						|
+                        pos += lastslashpos;
 | 
						|
+                        resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
 | 
						|
+                        resuri.RemoveDotSegments();
 | 
						|
+                    }
 | 
						|
+                    // Use this query
 | 
						|
+                    resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        // Always use this frag
 | 
						|
+        resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
 | 
						|
+
 | 
						|
+        // Re-constitute base_ and uri_
 | 
						|
+        resuri.SetBase();
 | 
						|
+        resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
 | 
						|
+        resuri.SetUri();
 | 
						|
+        return resuri;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    //! Get the allocator of this GenericUri.
 | 
						|
+    Allocator& GetAllocator() { return *allocator_; }
 | 
						|
+
 | 
						|
+private:
 | 
						|
+    // Allocate memory for a URI
 | 
						|
+    // Returns total amount allocated
 | 
						|
+    std::size_t Allocate(std::size_t len) {
 | 
						|
+        // Create own allocator if user did not supply.
 | 
						|
+        if (!allocator_)
 | 
						|
+            ownAllocator_ =  allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
						|
+
 | 
						|
+        // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated.
 | 
						|
+        // Order: scheme, auth, path, query, frag, base, uri
 | 
						|
+        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
						|
+        size_t total = (3 * len + 7) * sizeof(Ch);
 | 
						|
+        scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
 | 
						|
+        *scheme_ = '\0';
 | 
						|
+        auth_ = scheme_;
 | 
						|
+        auth_++;
 | 
						|
+        *auth_ = '\0';
 | 
						|
+        path_ = auth_;
 | 
						|
+        path_++;
 | 
						|
+        *path_ = '\0';
 | 
						|
+        query_ = path_;
 | 
						|
+        query_++;
 | 
						|
+        *query_ = '\0';
 | 
						|
+        frag_ = query_;
 | 
						|
+        frag_++;
 | 
						|
+        *frag_ = '\0';
 | 
						|
+        base_ = frag_;
 | 
						|
+        base_++;
 | 
						|
+        *base_ = '\0';
 | 
						|
+        uri_ = base_;
 | 
						|
+        uri_++;
 | 
						|
+        *uri_ = '\0';
 | 
						|
+        return total;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Free memory for a URI
 | 
						|
+    void Free() {
 | 
						|
+        if (scheme_) {
 | 
						|
+            Allocator::Free(scheme_);
 | 
						|
+            scheme_ = 0;
 | 
						|
+        }
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Parse a URI into constituent scheme, authority, path, query, & fragment parts
 | 
						|
+    // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per
 | 
						|
+    // https://tools.ietf.org/html/rfc3986
 | 
						|
+    void Parse(const Ch* uri, std::size_t len) {
 | 
						|
+        std::size_t start = 0, pos1 = 0, pos2 = 0;
 | 
						|
+        Allocate(len);
 | 
						|
+
 | 
						|
+        // Look for scheme ([^:/?#]+):)?
 | 
						|
+        if (start < len) {
 | 
						|
+            while (pos1 < len) {
 | 
						|
+                if (uri[pos1] == ':') break;
 | 
						|
+                pos1++;
 | 
						|
+            }
 | 
						|
+            if (pos1 != len) {
 | 
						|
+                while (pos2 < len) {
 | 
						|
+                    if (uri[pos2] == '/') break;
 | 
						|
+                    if (uri[pos2] == '?') break;
 | 
						|
+                    if (uri[pos2] == '#') break;
 | 
						|
+                    pos2++;
 | 
						|
+                }
 | 
						|
+                if (pos1 < pos2) {
 | 
						|
+                    pos1++;
 | 
						|
+                    std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch));
 | 
						|
+                    scheme_[pos1] = '\0';
 | 
						|
+                    start = pos1;
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        // Look for auth (//([^/?#]*))?
 | 
						|
+        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
						|
+        auth_ = scheme_ + GetSchemeStringLength();
 | 
						|
+        auth_++;
 | 
						|
+        *auth_ = '\0';
 | 
						|
+        if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') {
 | 
						|
+            pos2 = start + 2;
 | 
						|
+            while (pos2 < len) {
 | 
						|
+                if (uri[pos2] == '/') break;
 | 
						|
+                if (uri[pos2] == '?') break;
 | 
						|
+                if (uri[pos2] == '#') break;
 | 
						|
+                pos2++;
 | 
						|
+            }
 | 
						|
+            std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
						|
+            auth_[pos2 - start] = '\0';
 | 
						|
+            start = pos2;
 | 
						|
+        }
 | 
						|
+        // Look for path ([^?#]*)
 | 
						|
+        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
						|
+        path_ = auth_ + GetAuthStringLength();
 | 
						|
+        path_++;
 | 
						|
+        *path_ = '\0';
 | 
						|
+        if (start < len) {
 | 
						|
+            pos2 = start;
 | 
						|
+            while (pos2 < len) {
 | 
						|
+                if (uri[pos2] == '?') break;
 | 
						|
+                if (uri[pos2] == '#') break;
 | 
						|
+                pos2++;
 | 
						|
+            }
 | 
						|
+            if (start != pos2) {
 | 
						|
+                std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
						|
+                path_[pos2 - start] = '\0';
 | 
						|
+                if (path_[0] == '/')
 | 
						|
+                    RemoveDotSegments();   // absolute path - normalize
 | 
						|
+                start = pos2;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        // Look for query (\?([^#]*))?
 | 
						|
+        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
						|
+        query_ = path_ + GetPathStringLength();
 | 
						|
+        query_++;
 | 
						|
+        *query_ = '\0';
 | 
						|
+        if (start < len && uri[start] == '?') {
 | 
						|
+            pos2 = start + 1;
 | 
						|
+            while (pos2 < len) {
 | 
						|
+                if (uri[pos2] == '#') break;
 | 
						|
+                pos2++;
 | 
						|
+            }
 | 
						|
+            if (start != pos2) {
 | 
						|
+                std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
						|
+                query_[pos2 - start] = '\0';
 | 
						|
+                start = pos2;
 | 
						|
+            }
 | 
						|
+        }
 | 
						|
+        // Look for fragment (#(.*))?
 | 
						|
+        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
						|
+        frag_ = query_ + GetQueryStringLength();
 | 
						|
+        frag_++;
 | 
						|
+        *frag_ = '\0';
 | 
						|
+        if (start < len && uri[start] == '#') {
 | 
						|
+            std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));
 | 
						|
+            frag_[len - start] = '\0';
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        // Re-constitute base_ and uri_
 | 
						|
+        base_ = frag_ + GetFragStringLength() + 1;
 | 
						|
+        SetBase();
 | 
						|
+        uri_ = base_ + GetBaseStringLength() + 1;
 | 
						|
+        SetUri();
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Reconstitute base
 | 
						|
+    void SetBase() {
 | 
						|
+        Ch* next = base_;
 | 
						|
+        std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetSchemeStringLength();
 | 
						|
+        std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetAuthStringLength();
 | 
						|
+        std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetPathStringLength();
 | 
						|
+        std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetQueryStringLength();
 | 
						|
+        *next = '\0';
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Reconstitute uri
 | 
						|
+    void SetUri() {
 | 
						|
+        Ch* next = uri_;
 | 
						|
+        std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetBaseStringLength();
 | 
						|
+        std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch));
 | 
						|
+        next+= GetFragStringLength();
 | 
						|
+        *next = '\0';
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Copy a part from one GenericUri to another
 | 
						|
+    // Return the pointer to the next part to be copied to
 | 
						|
+    Ch* CopyPart(Ch* to, Ch* from, std::size_t len) {
 | 
						|
+        RAPIDJSON_ASSERT(to != 0);
 | 
						|
+        RAPIDJSON_ASSERT(from != 0);
 | 
						|
+        std::memcpy(to, from, len * sizeof(Ch));
 | 
						|
+        to[len] = '\0';
 | 
						|
+        Ch* next = to + len + 1;
 | 
						|
+        return next;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    // Remove . and .. segments from the path_ member.
 | 
						|
+    // https://tools.ietf.org/html/rfc3986
 | 
						|
+    // This is done in place as we are only removing segments.
 | 
						|
+    void RemoveDotSegments() {
 | 
						|
+        std::size_t pathlen = GetPathStringLength();
 | 
						|
+        std::size_t pathpos = 0;  // Position in path_
 | 
						|
+        std::size_t newpos = 0;   // Position in new path_
 | 
						|
+
 | 
						|
+        // Loop through each segment in original path_
 | 
						|
+        while (pathpos < pathlen) {
 | 
						|
+            // Get next segment, bounded by '/' or end
 | 
						|
+            size_t slashpos = 0;
 | 
						|
+            while ((pathpos + slashpos) < pathlen) {
 | 
						|
+                if (path_[pathpos + slashpos] == '/') break;
 | 
						|
+                slashpos++;
 | 
						|
+            }
 | 
						|
+            // Check for .. and . segments
 | 
						|
+            if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') {
 | 
						|
+                // Backup a .. segment in the new path_
 | 
						|
+                // We expect to find a previously added slash at the end or nothing
 | 
						|
+                RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/');
 | 
						|
+                size_t lastslashpos = newpos;
 | 
						|
+                // Make sure we don't go beyond the start segment
 | 
						|
+                if (lastslashpos > 1) {
 | 
						|
+                    // Find the next to last slash and back up to it
 | 
						|
+                    lastslashpos--;
 | 
						|
+                    while (lastslashpos > 0) {
 | 
						|
+                        if (path_[lastslashpos - 1] == '/') break;
 | 
						|
+                        lastslashpos--;
 | 
						|
+                    }
 | 
						|
+                    // Set the new path_ position
 | 
						|
+                    newpos = lastslashpos;
 | 
						|
+                }
 | 
						|
+            } else if (slashpos == 1 && path_[pathpos] == '.') {
 | 
						|
+                // Discard . segment, leaves new path_ unchanged
 | 
						|
+            } else {
 | 
						|
+                // Move any other kind of segment to the new path_
 | 
						|
+                RAPIDJSON_ASSERT(newpos <= pathpos);
 | 
						|
+                std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch));
 | 
						|
+                newpos += slashpos;
 | 
						|
+                // Add slash if not at end
 | 
						|
+                if ((pathpos + slashpos) < pathlen) {
 | 
						|
+                    path_[newpos] = '/';
 | 
						|
+                    newpos++;
 | 
						|
+                }
 | 
						|
+            }
 | 
						|
+            // Move to next segment
 | 
						|
+            pathpos += slashpos + 1;
 | 
						|
+        }
 | 
						|
+        path_[newpos] = '\0';
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    Ch* uri_;    // Everything
 | 
						|
+    Ch* base_;   // Everything except fragment
 | 
						|
+    Ch* scheme_; // Includes the :
 | 
						|
+    Ch* auth_;   // Includes the //
 | 
						|
+    Ch* path_;   // Absolute if starts with /
 | 
						|
+    Ch* query_;  // Includes the ?
 | 
						|
+    Ch* frag_;   // Includes the #
 | 
						|
+
 | 
						|
+    Allocator* allocator_;      //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
 | 
						|
+    Allocator* ownAllocator_;   //!< Allocator owned by this Uri.
 | 
						|
+};
 | 
						|
+
 | 
						|
+//! GenericUri for Value (UTF-8, default allocator).
 | 
						|
+typedef GenericUri<Value> Uri;
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_END
 | 
						|
+
 | 
						|
+#if defined(__clang__)
 | 
						|
+RAPIDJSON_DIAG_POP
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+#endif // RAPIDJSON_URI_H_
 | 
						|
diff --git a/src/common/thirdparty/rapidjson/writer.h b/src/common/thirdparty/rapidjson/writer.h
 | 
						|
index 200abadae..50f6af989 100644
 | 
						|
--- a/src/common/thirdparty/rapidjson/writer.h
 | 
						|
+++ b/src/common/thirdparty/rapidjson/writer.h
 | 
						|
@@ -1,6 +1,6 @@
 | 
						|
 // Tencent is pleased to support the open source community by making RapidJSON available.
 | 
						|
 // 
 | 
						|
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 | 
						|
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
						|
 //
 | 
						|
 // Licensed under the MIT License (the "License"); you may not use this file except
 | 
						|
 // in compliance with the License. You may obtain a copy of the License at
 | 
						|
@@ -16,6 +16,8 @@
 | 
						|
 #define RAPIDJSON_WRITER_H_
 | 
						|
 
 | 
						|
 #include "stream.h"
 | 
						|
+#include "internal/clzll.h"
 | 
						|
+#include "internal/meta.h"
 | 
						|
 #include "internal/stack.h"
 | 
						|
 #include "internal/strfunc.h"
 | 
						|
 #include "internal/dtoa.h"
 | 
						|
@@ -31,17 +33,18 @@
 | 
						|
 #include <nmmintrin.h>
 | 
						|
 #elif defined(RAPIDJSON_SSE2)
 | 
						|
 #include <emmintrin.h>
 | 
						|
-#endif
 | 
						|
-
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_PUSH
 | 
						|
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 | 
						|
+#elif defined(RAPIDJSON_NEON)
 | 
						|
+#include <arm_neon.h>
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #ifdef __clang__
 | 
						|
 RAPIDJSON_DIAG_PUSH
 | 
						|
 RAPIDJSON_DIAG_OFF(padded)
 | 
						|
 RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
						|
+RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
						|
+#elif defined(_MSC_VER)
 | 
						|
+RAPIDJSON_DIAG_PUSH
 | 
						|
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 RAPIDJSON_NAMESPACE_BEGIN
 | 
						|
@@ -103,6 +106,13 @@ public:
 | 
						|
     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
 | 
						|
+    Writer(Writer&& rhs) :
 | 
						|
+        os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
 | 
						|
+        rhs.os_ = 0;
 | 
						|
+    }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
     //! Reset the writer with a new stream.
 | 
						|
     /*!
 | 
						|
         This function reset the writer with a new stream and default settings,
 | 
						|
@@ -211,10 +221,18 @@ public:
 | 
						|
 
 | 
						|
     bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
 | 
						|
 
 | 
						|
+#if RAPIDJSON_HAS_STDSTRING
 | 
						|
+    bool Key(const std::basic_string<Ch>& str)
 | 
						|
+    {
 | 
						|
+      return Key(str.data(), SizeType(str.size()));
 | 
						|
+    }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
     bool EndObject(SizeType memberCount = 0) {
 | 
						|
         (void)memberCount;
 | 
						|
-        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
 | 
						|
-        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
 | 
						|
+        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
 | 
						|
+        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
 | 
						|
+        RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
 | 
						|
         level_stack_.template Pop<Level>(1);
 | 
						|
         return EndValue(WriteEndObject());
 | 
						|
     }
 | 
						|
@@ -238,9 +256,9 @@ public:
 | 
						|
     //@{
 | 
						|
 
 | 
						|
     //! Simpler but slower overload.
 | 
						|
-    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
 | 
						|
-    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
 | 
						|
-
 | 
						|
+    bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
 | 
						|
+    bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
 | 
						|
+    
 | 
						|
     //@}
 | 
						|
 
 | 
						|
     //! Write a raw JSON value.
 | 
						|
@@ -257,6 +275,16 @@ public:
 | 
						|
         return EndValue(WriteRawValue(json, length));
 | 
						|
     }
 | 
						|
 
 | 
						|
+    //! Flush the output stream.
 | 
						|
+    /*!
 | 
						|
+        Allows the user to flush the output stream immediately.
 | 
						|
+     */
 | 
						|
+    void Flush() {
 | 
						|
+        os_->Flush();
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    static const size_t kDefaultLevelDepth = 32;
 | 
						|
+
 | 
						|
 protected:
 | 
						|
     //! Information for each nested level
 | 
						|
     struct Level {
 | 
						|
@@ -265,8 +293,6 @@ protected:
 | 
						|
         bool inArray;       //!< true if in array, otherwise in object
 | 
						|
     };
 | 
						|
 
 | 
						|
-    static const size_t kDefaultLevelDepth = 32;
 | 
						|
-
 | 
						|
     bool WriteNull()  {
 | 
						|
         PutReserve(*os_, 4);
 | 
						|
         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
 | 
						|
@@ -289,7 +315,7 @@ protected:
 | 
						|
         const char* end = internal::i32toa(i, buffer);
 | 
						|
         PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
						|
         for (const char* p = buffer; p != end; ++p)
 | 
						|
-            PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
 | 
						|
+            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -298,7 +324,7 @@ protected:
 | 
						|
         const char* end = internal::u32toa(u, buffer);
 | 
						|
         PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
						|
         for (const char* p = buffer; p != end; ++p)
 | 
						|
-            PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
 | 
						|
+            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -307,7 +333,7 @@ protected:
 | 
						|
         const char* end = internal::i64toa(i64, buffer);
 | 
						|
         PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
						|
         for (const char* p = buffer; p != end; ++p)
 | 
						|
-            PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
 | 
						|
+            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -316,7 +342,7 @@ protected:
 | 
						|
         char* end = internal::u64toa(u64, buffer);
 | 
						|
         PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
						|
         for (char* p = buffer; p != end; ++p)
 | 
						|
-            PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
 | 
						|
+            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -352,12 +378,12 @@ protected:
 | 
						|
         char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
 | 
						|
         PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
						|
         for (char* p = buffer; p != end; ++p)
 | 
						|
-            PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
 | 
						|
+            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
						|
         return ret;
 | 
						|
     }
 | 
						|
 
 | 
						|
     bool WriteString(const Ch* str, SizeType length)  {
 | 
						|
-        static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 | 
						|
+        static const 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] = {
 | 
						|
 #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
 | 
						|
@@ -413,7 +439,7 @@ protected:
 | 
						|
             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
 | 
						|
                 is.Take();
 | 
						|
                 PutUnsafe(*os_, '\\');
 | 
						|
-                PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
 | 
						|
+                PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
 | 
						|
                 if (escape[static_cast<unsigned char>(c)] == 'u') {
 | 
						|
                     PutUnsafe(*os_, '0');
 | 
						|
                     PutUnsafe(*os_, '0');
 | 
						|
@@ -441,9 +467,13 @@ protected:
 | 
						|
 
 | 
						|
     bool WriteRawValue(const Ch* json, size_t length) {
 | 
						|
         PutReserve(*os_, length);
 | 
						|
-        for (size_t i = 0; i < length; i++) {
 | 
						|
-            RAPIDJSON_ASSERT(json[i] != '\0');
 | 
						|
-            PutUnsafe(*os_, json[i]);
 | 
						|
+        GenericStringStream<SourceEncoding> is(json);
 | 
						|
+        while (RAPIDJSON_LIKELY(is.Tell() < length)) {
 | 
						|
+            RAPIDJSON_ASSERT(is.Peek() != '\0');
 | 
						|
+            if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
 | 
						|
+                Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
 | 
						|
+                Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
 | 
						|
+                return false;
 | 
						|
         }
 | 
						|
         return true;
 | 
						|
     }
 | 
						|
@@ -471,7 +501,7 @@ protected:
 | 
						|
     // Flush the value if it is the top level one.
 | 
						|
     bool EndValue(bool ret) {
 | 
						|
         if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text
 | 
						|
-            os_->Flush();
 | 
						|
+            Flush();
 | 
						|
         return ret;
 | 
						|
     }
 | 
						|
 
 | 
						|
@@ -524,15 +554,8 @@ template<>
 | 
						|
 inline bool Writer<StringBuffer>::WriteDouble(double d) {
 | 
						|
     if (internal::Double(d).IsNanOrInf()) {
 | 
						|
         // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
 | 
						|
-		if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
 | 
						|
-		{
 | 
						|
-			// At least ensure that the output does not get broken.
 | 
						|
-			PutReserve(*os_, 3);
 | 
						|
-			PutUnsafe(*os_, '0');
 | 
						|
-			PutUnsafe(*os_, '.');
 | 
						|
-			PutUnsafe(*os_, '0');
 | 
						|
-			return false;
 | 
						|
-		}
 | 
						|
+        if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
 | 
						|
+            return false;
 | 
						|
         if (internal::Double(d).IsNan()) {
 | 
						|
             PutReserve(*os_, 3);
 | 
						|
             PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
 | 
						|
@@ -582,7 +605,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
 | 
						|
     // The rest of string using SIMD
 | 
						|
     static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
 | 
						|
     static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
 | 
						|
-    static const char space[16]  = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
 | 
						|
+    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 bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
 | 
						|
     const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
 | 
						|
@@ -591,7 +614,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
 | 
						|
         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
						|
         const __m128i t1 = _mm_cmpeq_epi8(s, dq);
 | 
						|
         const __m128i t2 = _mm_cmpeq_epi8(s, bs);
 | 
						|
-        const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
 | 
						|
+        const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
 | 
						|
         const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
 | 
						|
         unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
 | 
						|
         if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
 | 
						|
@@ -616,15 +639,79 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
 | 
						|
     is.src_ = p;
 | 
						|
     return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
						|
 }
 | 
						|
-#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
 | 
						|
+#elif defined(RAPIDJSON_NEON)
 | 
						|
+template<>
 | 
						|
+inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
 | 
						|
+    if (length < 16)
 | 
						|
+        return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
						|
 
 | 
						|
-RAPIDJSON_NAMESPACE_END
 | 
						|
+    if (!RAPIDJSON_LIKELY(is.Tell() < length))
 | 
						|
+        return false;
 | 
						|
 
 | 
						|
-#ifdef _MSC_VER
 | 
						|
-RAPIDJSON_DIAG_POP
 | 
						|
-#endif
 | 
						|
+    const char* p = is.src_;
 | 
						|
+    const char* end = is.head_ + length;
 | 
						|
+    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
 | 
						|
+    const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
 | 
						|
+    if (nextAligned > end)
 | 
						|
+        return true;
 | 
						|
 
 | 
						|
-#ifdef __clang__
 | 
						|
+    while (p != nextAligned)
 | 
						|
+        if (*p < 0x20 || *p == '\"' || *p == '\\') {
 | 
						|
+            is.src_ = p;
 | 
						|
+            return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
						|
+        }
 | 
						|
+        else
 | 
						|
+            os_->PutUnsafe(*p++);
 | 
						|
+
 | 
						|
+    // The rest of string using SIMD
 | 
						|
+    const uint8x16_t s0 = vmovq_n_u8('"');
 | 
						|
+    const uint8x16_t s1 = vmovq_n_u8('\\');
 | 
						|
+    const uint8x16_t s2 = vmovq_n_u8('\b');
 | 
						|
+    const uint8x16_t s3 = vmovq_n_u8(32);
 | 
						|
+
 | 
						|
+    for (; p != endAligned; p += 16) {
 | 
						|
+        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
 | 
						|
+        uint8x16_t x = vceqq_u8(s, s0);
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, s1));
 | 
						|
+        x = vorrq_u8(x, vceqq_u8(s, s2));
 | 
						|
+        x = vorrq_u8(x, vcltq_u8(s, s3));
 | 
						|
+
 | 
						|
+        x = vrev64q_u8(x);                     // Rev in 64
 | 
						|
+        uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
						|
+        uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
						|
+
 | 
						|
+        SizeType len = 0;
 | 
						|
+        bool escaped = false;
 | 
						|
+        if (low == 0) {
 | 
						|
+            if (high != 0) {
 | 
						|
+                uint32_t lz = internal::clzll(high);
 | 
						|
+                len = 8 + (lz >> 3);
 | 
						|
+                escaped = true;
 | 
						|
+            }
 | 
						|
+        } else {
 | 
						|
+            uint32_t lz = internal::clzll(low);
 | 
						|
+            len = lz >> 3;
 | 
						|
+            escaped = true;
 | 
						|
+        }
 | 
						|
+        if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
 | 
						|
+            char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
 | 
						|
+            for (size_t i = 0; i < len; i++)
 | 
						|
+                q[i] = p[i];
 | 
						|
+
 | 
						|
+            p += len;
 | 
						|
+            break;
 | 
						|
+        }
 | 
						|
+        vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    is.src_ = p;
 | 
						|
+    return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
						|
+}
 | 
						|
+#endif // RAPIDJSON_NEON
 | 
						|
+
 | 
						|
+RAPIDJSON_NAMESPACE_END
 | 
						|
+
 | 
						|
+#if defined(_MSC_VER) || defined(__clang__)
 | 
						|
 RAPIDJSON_DIAG_POP
 | 
						|
 #endif
 | 
						|
 
 | 
						|
-- 
 | 
						|
2.39.3
 | 
						|
 |