mirror of
				https://github.com/AlexandreRouma/SDRPlusPlus.git
				synced 2025-10-31 00:48:11 +01:00 
			
		
		
		
	fixes
This commit is contained in:
		| @@ -58,11 +58,11 @@ typedef struct DiscordEventHandlers { | ||||
|     void (*joinRequest)(const DiscordUser* request); | ||||
| } DiscordEventHandlers; | ||||
|  | ||||
| #define DISCORD_REPLY_NO      0 | ||||
| #define DISCORD_REPLY_YES     1 | ||||
| #define DISCORD_REPLY_IGNORE  2 | ||||
| #define DISCORD_REPLY_NO 0 | ||||
| #define DISCORD_REPLY_YES 1 | ||||
| #define DISCORD_REPLY_IGNORE 2 | ||||
| #define DISCORD_PARTY_PRIVATE 0 | ||||
| #define DISCORD_PARTY_PUBLIC  1 | ||||
| #define DISCORD_PARTY_PUBLIC 1 | ||||
|  | ||||
| DISCORD_EXPORT void Discord_Initialize(const char* applicationId, | ||||
|                                        DiscordEventHandlers* handlers, | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_ALLOCATORS_H_ | ||||
| @@ -82,7 +82,7 @@ concept Allocator { | ||||
| class CrtAllocator { | ||||
| public: | ||||
|     static const bool kNeedFree = true; | ||||
|     void* Malloc(size_t size) { | ||||
|     void* Malloc(size_t size) {  | ||||
|         if (size) //  behavior of malloc(0) is implementation defined. | ||||
|             return RAPIDJSON_MALLOC(size); | ||||
|         else | ||||
| @@ -96,7 +96,7 @@ public: | ||||
|         } | ||||
|         return RAPIDJSON_REALLOC(originalPtr, newSize); | ||||
|     } | ||||
|     static void Free(void* ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } | ||||
|     static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } | ||||
|  | ||||
|     bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { | ||||
|         return true; | ||||
| @@ -131,13 +131,13 @@ class MemoryPoolAllocator { | ||||
|     /*! 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. | ||||
|         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. | ||||
|         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; | ||||
| @@ -146,26 +146,31 @@ class MemoryPoolAllocator { | ||||
|     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) { | ||||
|     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) { | ||||
|     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 | ||||
|     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) : chunk_capacity_(chunkSize), | ||||
|                                                                                                                baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), | ||||
|                                                                                                                shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) { | ||||
|     explicit | ||||
|     MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 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) { | ||||
| @@ -192,9 +197,11 @@ public: | ||||
|         \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. | ||||
|         \param baseAllocator The allocator for allocating memory chunks. | ||||
|     */ | ||||
|     MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize), | ||||
|                                                                                                                                  baseAllocator_(baseAllocator), | ||||
|                                                                                                                                  shared_(static_cast<SharedData*>(AlignBuffer(buffer, size))) { | ||||
|     MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : | ||||
|         chunk_capacity_(chunkSize), | ||||
|         baseAllocator_(baseAllocator), | ||||
|         shared_(static_cast<SharedData*>(AlignBuffer(buffer, size))) | ||||
|     { | ||||
|         RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); | ||||
|         shared_->chunkHead = GetChunkHead(shared_); | ||||
|         shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; | ||||
| @@ -205,13 +212,16 @@ public: | ||||
|         shared_->refcount = 1; | ||||
|     } | ||||
|  | ||||
|     MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_), | ||||
|                                                                              baseAllocator_(rhs.baseAllocator_), | ||||
|                                                                              shared_(rhs.shared_) { | ||||
|     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 { | ||||
|     MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); | ||||
|         ++rhs.shared_->refcount; | ||||
|         this->~MemoryPoolAllocator(); | ||||
| @@ -222,13 +232,16 @@ public: | ||||
|     } | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|     MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_), | ||||
|                                                                         baseAllocator_(rhs.baseAllocator_), | ||||
|                                                                         shared_(rhs.shared_) { | ||||
|     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 { | ||||
|     MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); | ||||
|         this->~MemoryPoolAllocator(); | ||||
|         baseAllocator_ = rhs.baseAllocator_; | ||||
| @@ -252,7 +265,7 @@ public: | ||||
|             return; | ||||
|         } | ||||
|         Clear(); | ||||
|         BaseAllocator* a = shared_->ownBaseAllocator; | ||||
|         BaseAllocator *a = shared_->ownBaseAllocator; | ||||
|         if (shared_->ownBuffer) { | ||||
|             baseAllocator_->Free(shared_); | ||||
|         } | ||||
| @@ -314,7 +327,7 @@ public: | ||||
|             if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) | ||||
|                 return NULL; | ||||
|  | ||||
|         void* buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; | ||||
|         void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; | ||||
|         shared_->chunkHead->size += size; | ||||
|         return buffer; | ||||
|     } | ||||
| @@ -355,7 +368,7 @@ public: | ||||
|     } | ||||
|  | ||||
|     //! Frees a memory block (concept Allocator) | ||||
|     static void Free(void* ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing | ||||
|     static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing | ||||
|  | ||||
|     //! Compare (equality) with another MemoryPoolAllocator | ||||
|     bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { | ||||
| @@ -387,7 +400,8 @@ private: | ||||
|             return false; | ||||
|     } | ||||
|  | ||||
|     static inline void* AlignBuffer(void* buf, size_t& size) { | ||||
|     static inline void* AlignBuffer(void* buf, size_t &size) | ||||
|     { | ||||
|         RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); | ||||
|         const uintptr_t mask = sizeof(void*) - 1; | ||||
|         const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf); | ||||
| @@ -400,31 +414,38 @@ private: | ||||
|         return buf; | ||||
|     } | ||||
|  | ||||
|     size_t chunk_capacity_;        //!< The minimum capacity of chunk when they are allocated. | ||||
|     BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. | ||||
|     SharedData* shared_;           //!< The shared data of the allocator | ||||
|     size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated. | ||||
|     BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks. | ||||
|     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, 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) { | ||||
| 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 <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T)); | ||||
|     return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); | ||||
| } | ||||
|  | ||||
| template <typename T, typename A> | ||||
| inline T* Malloc(A& a, size_t n = 1) { | ||||
| 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) { | ||||
| 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)); | ||||
| } | ||||
|  | ||||
| @@ -434,7 +455,9 @@ RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename BaseAllocator = CrtAllocator> | ||||
| class StdAllocator : public std::allocator<T> { | ||||
| class StdAllocator : | ||||
|     public std::allocator<T> | ||||
| { | ||||
|     typedef std::allocator<T> allocator_type; | ||||
| #if RAPIDJSON_HAS_CXX11 | ||||
|     typedef std::allocator_traits<allocator_type> traits_type; | ||||
| @@ -445,19 +468,27 @@ class StdAllocator : public std::allocator<T> { | ||||
| public: | ||||
|     typedef BaseAllocator BaseAllocatorType; | ||||
|  | ||||
|     StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(), | ||||
|                                         baseAllocator_() {} | ||||
|     StdAllocator() RAPIDJSON_NOEXCEPT : | ||||
|         allocator_type(), | ||||
|         baseAllocator_() | ||||
|     { } | ||||
|  | ||||
|     StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), | ||||
|                                                                baseAllocator_(rhs.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_) {} | ||||
|     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_)) {} | ||||
|     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; | ||||
| @@ -465,85 +496,102 @@ public: | ||||
| #endif | ||||
|  | ||||
|     /* implicit */ | ||||
|     StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(), | ||||
|                                                                       baseAllocator_(allocator) {} | ||||
|     StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : | ||||
|         allocator_type(), | ||||
|         baseAllocator_(allocator) | ||||
|     { } | ||||
|  | ||||
|     ~StdAllocator() RAPIDJSON_NOEXCEPT {} | ||||
|     ~StdAllocator() RAPIDJSON_NOEXCEPT | ||||
|     { } | ||||
|  | ||||
|     template <typename U> | ||||
|     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::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; | ||||
|     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; | ||||
|     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 { | ||||
|     pointer address(reference r) const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return std::addressof(r); | ||||
|     } | ||||
|     const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT { | ||||
|     const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return std::addressof(r); | ||||
|     } | ||||
|  | ||||
|     size_type max_size() const RAPIDJSON_NOEXCEPT { | ||||
|     size_type max_size() const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return traits_type::max_size(*this); | ||||
|     } | ||||
|  | ||||
|     template <typename... Args> | ||||
|     void construct(pointer p, Args&&... args) { | ||||
|     template <typename ...Args> | ||||
|     void construct(pointer p, Args&&... args) | ||||
|     { | ||||
|         traits_type::construct(*this, p, std::forward<Args>(args)...); | ||||
|     } | ||||
|     void destroy(pointer p) { | ||||
|     void destroy(pointer p) | ||||
|     { | ||||
|         traits_type::destroy(*this, p); | ||||
|     } | ||||
|  | ||||
| #else // !RAPIDJSON_HAS_CXX11 | ||||
|  | ||||
|     typedef typename allocator_type::reference reference; | ||||
|     typedef typename allocator_type::reference       reference; | ||||
|     typedef typename allocator_type::const_reference const_reference; | ||||
|  | ||||
|     pointer address(reference r) const RAPIDJSON_NOEXCEPT { | ||||
|     pointer address(reference r) const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return allocator_type::address(r); | ||||
|     } | ||||
|     const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT { | ||||
|     const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return allocator_type::address(r); | ||||
|     } | ||||
|  | ||||
|     size_type max_size() const RAPIDJSON_NOEXCEPT { | ||||
|     size_type max_size() const RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         return allocator_type::max_size(); | ||||
|     } | ||||
|  | ||||
|     void construct(pointer p, const_reference r) { | ||||
|     void construct(pointer p, const_reference r) | ||||
|     { | ||||
|         allocator_type::construct(p, r); | ||||
|     } | ||||
|     void destroy(pointer p) { | ||||
|     void destroy(pointer p) | ||||
|     { | ||||
|         allocator_type::destroy(p); | ||||
|     } | ||||
|  | ||||
| #endif // !RAPIDJSON_HAS_CXX11 | ||||
|  | ||||
|     template <typename U> | ||||
|     U* allocate(size_type n = 1, const void* = 0) { | ||||
|     U* allocate(size_type n = 1, const void* = 0) | ||||
|     { | ||||
|         return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n); | ||||
|     } | ||||
|     template <typename U> | ||||
|     void deallocate(U* p, size_type n = 1) { | ||||
|     void deallocate(U* p, size_type n = 1) | ||||
|     { | ||||
|         RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n); | ||||
|     } | ||||
|  | ||||
|     pointer allocate(size_type n = 1, const void* = 0) { | ||||
|     pointer allocate(size_type n = 1, const void* = 0) | ||||
|     { | ||||
|         return allocate<value_type>(n); | ||||
|     } | ||||
|     void deallocate(pointer p, size_type n = 1) { | ||||
|     void deallocate(pointer p, size_type n = 1) | ||||
|     { | ||||
|         deallocate<value_type>(p, n); | ||||
|     } | ||||
|  | ||||
| @@ -551,25 +599,30 @@ public: | ||||
|     using is_always_equal = std::is_empty<BaseAllocator>; | ||||
| #endif | ||||
|  | ||||
|     template <typename U> | ||||
|     bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT { | ||||
|     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 { | ||||
|     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) { | ||||
|     void* Malloc(size_t size) | ||||
|     { | ||||
|         return baseAllocator_.Malloc(size); | ||||
|     } | ||||
|     void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { | ||||
|     void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) | ||||
|     { | ||||
|         return baseAllocator_.Realloc(originalPtr, originalSize, newSize); | ||||
|     } | ||||
|     static void Free(void* ptr) RAPIDJSON_NOEXCEPT { | ||||
|     static void Free(void *ptr) RAPIDJSON_NOEXCEPT | ||||
|     { | ||||
|         BaseAllocator::Free(ptr); | ||||
|     } | ||||
|  | ||||
| @@ -582,29 +635,40 @@ private: | ||||
|  | ||||
| #if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17 | ||||
| template <typename BaseAllocator> | ||||
| class StdAllocator<void, BaseAllocator> : public std::allocator<void> { | ||||
| class StdAllocator<void, BaseAllocator> : | ||||
|     public std::allocator<void> | ||||
| { | ||||
|     typedef std::allocator<void> allocator_type; | ||||
|  | ||||
| public: | ||||
|     typedef BaseAllocator BaseAllocatorType; | ||||
|  | ||||
|     StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(), | ||||
|                                         baseAllocator_() {} | ||||
|     StdAllocator() RAPIDJSON_NOEXCEPT : | ||||
|         allocator_type(), | ||||
|         baseAllocator_() | ||||
|     { } | ||||
|  | ||||
|     StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), | ||||
|                                                                baseAllocator_(rhs.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_) {} | ||||
|     template<typename U> | ||||
|     StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : | ||||
|         allocator_type(rhs), | ||||
|         baseAllocator_(rhs.baseAllocator_) | ||||
|     { } | ||||
|  | ||||
|     /* implicit */ | ||||
|     StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(), | ||||
|                                                                       baseAllocator_(allocator) {} | ||||
|     StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : | ||||
|         allocator_type(), | ||||
|         baseAllocator_(allocator) | ||||
|     { } | ||||
|  | ||||
|     ~StdAllocator() RAPIDJSON_NOEXCEPT {} | ||||
|     ~StdAllocator() RAPIDJSON_NOEXCEPT | ||||
|     { } | ||||
|  | ||||
|     template <typename U> | ||||
|     template<typename U> | ||||
|     struct rebind { | ||||
|         typedef StdAllocator<U, BaseAllocator> other; | ||||
|     }; | ||||
|   | ||||
| @@ -24,8 +24,8 @@ RAPIDJSON_DIAG_OFF(effc++) | ||||
|  | ||||
| #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 | ||||
| RAPIDJSON_DIAG_OFF(4702)  // unreachable code | ||||
| RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -35,22 +35,22 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| /*! | ||||
|     \tparam InputStream     Any stream that implements Stream Concept | ||||
| */ | ||||
| template <typename InputStream, typename Encoding = UTF8<>> | ||||
| template <typename InputStream, typename Encoding = UTF8<> > | ||||
| class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> { | ||||
| public: | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|  | ||||
|     CursorStreamWrapper(InputStream& is) : GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {} | ||||
|     CursorStreamWrapper(InputStream& is): | ||||
|         GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {} | ||||
|  | ||||
|     // counting line and column number | ||||
|     Ch Take() { | ||||
|         Ch ch = this->is_.Take(); | ||||
|         if (ch == '\n') { | ||||
|             line_++; | ||||
|         if(ch == '\n') { | ||||
|             line_ ++; | ||||
|             col_ = 0; | ||||
|         } | ||||
|         else { | ||||
|             col_++; | ||||
|         } else { | ||||
|             col_ ++; | ||||
|         } | ||||
|         return ch; | ||||
|     } | ||||
| @@ -61,8 +61,8 @@ public: | ||||
|     size_t GetColumn() const { return col_; } | ||||
|  | ||||
| private: | ||||
|     size_t line_; //!< Current Line | ||||
|     size_t col_;  //!< Current Column | ||||
|     size_t line_;   //!< Current Line | ||||
|     size_t col_;    //!< Current Column | ||||
| }; | ||||
|  | ||||
| #if defined(_MSC_VER) && _MSC_VER <= 1800 | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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. | ||||
| // | ||||
| // 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_ENCODEDSTREAM_H_ | ||||
| @@ -38,33 +38,22 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| template <typename Encoding, typename InputByteStream> | ||||
| class EncodedInputStream { | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); | ||||
|  | ||||
| public: | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|  | ||||
|     EncodedInputStream(InputByteStream& is) : is_(is) { | ||||
|     EncodedInputStream(InputByteStream& is) : is_(is) {  | ||||
|         current_ = Encoding::TakeBOM(is_); | ||||
|     } | ||||
|  | ||||
|     Ch Peek() const { return current_; } | ||||
|     Ch Take() { | ||||
|         Ch c = current_; | ||||
|         current_ = Encoding::Take(is_); | ||||
|         return c; | ||||
|     } | ||||
|     Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } | ||||
|     size_t Tell() const { return is_.Tell(); } | ||||
|  | ||||
|     // Not implemented | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); }  | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     EncodedInputStream(const EncodedInputStream&); | ||||
| @@ -91,7 +80,7 @@ public: | ||||
|  | ||||
|     // Not implemented | ||||
|     void Put(Ch) {} | ||||
|     void Flush() {} | ||||
|     void Flush() {}  | ||||
|     Ch* PutBegin() { return 0; } | ||||
|     size_t PutEnd(Ch*) { return 0; } | ||||
|  | ||||
| @@ -110,39 +99,23 @@ private: | ||||
| template <typename Encoding, typename OutputByteStream> | ||||
| class EncodedOutputStream { | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); | ||||
|  | ||||
| public: | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|  | ||||
|     EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { | ||||
|     EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {  | ||||
|         if (putBOM) | ||||
|             Encoding::PutBOM(os_); | ||||
|     } | ||||
|  | ||||
|     void Put(Ch c) { Encoding::Put(os_, c); } | ||||
|     void Put(Ch c) { Encoding::Put(os_, c);  } | ||||
|     void Flush() { os_.Flush(); } | ||||
|  | ||||
|     // Not implemented | ||||
|     Ch Peek() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch Take() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t Tell() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} | ||||
|     Ch Take() { RAPIDJSON_ASSERT(false); return 0;} | ||||
|     size_t Tell() const { RAPIDJSON_ASSERT(false);  return 0; } | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     EncodedOutputStream(const EncodedOutputStream&); | ||||
| @@ -161,7 +134,6 @@ private: | ||||
| template <typename CharType, typename InputByteStream> | ||||
| class AutoUTFInputStream { | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); | ||||
|  | ||||
| public: | ||||
|     typedef CharType Ch; | ||||
|  | ||||
| @@ -171,7 +143,7 @@ public: | ||||
|         \param type UTF encoding type if it is not detected from the stream. | ||||
|     */ | ||||
|     AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { | ||||
|         RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); | ||||
|         RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);         | ||||
|         DetectType(); | ||||
|         static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; | ||||
|         takeFunc_ = f[type_]; | ||||
| @@ -182,24 +154,14 @@ public: | ||||
|     bool HasBOM() const { return hasBOM_; } | ||||
|  | ||||
|     Ch Peek() const { return current_; } | ||||
|     Ch Take() { | ||||
|         Ch c = current_; | ||||
|         current_ = takeFunc_(*is_); | ||||
|         return c; | ||||
|     } | ||||
|     Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } | ||||
|     size_t Tell() const { return is_->Tell(); } | ||||
|  | ||||
|     // Not implemented | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); }  | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     AutoUTFInputStream(const AutoUTFInputStream&); | ||||
| @@ -214,47 +176,17 @@ private: | ||||
|         // FF FE        UTF-16LE | ||||
|         // EF BB BF     UTF-8 | ||||
|  | ||||
|         const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4()); | ||||
|         const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4()); | ||||
|         if (!c) | ||||
|             return; | ||||
|  | ||||
|         unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); | ||||
|         hasBOM_ = false; | ||||
|         if (bom == 0xFFFE0000) { | ||||
|             type_ = kUTF32BE; | ||||
|             hasBOM_ = true; | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|         } | ||||
|         else if (bom == 0x0000FEFF) { | ||||
|             type_ = kUTF32LE; | ||||
|             hasBOM_ = true; | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|         } | ||||
|         else if ((bom & 0xFFFF) == 0xFFFE) { | ||||
|             type_ = kUTF16BE; | ||||
|             hasBOM_ = true; | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|         } | ||||
|         else if ((bom & 0xFFFF) == 0xFEFF) { | ||||
|             type_ = kUTF16LE; | ||||
|             hasBOM_ = true; | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|         } | ||||
|         else if ((bom & 0xFFFFFF) == 0xBFBBEF) { | ||||
|             type_ = kUTF8; | ||||
|             hasBOM_ = true; | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|             is_->Take(); | ||||
|         } | ||||
|         if (bom == 0xFFFE0000)                  { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } | ||||
|         else if (bom == 0x0000FEFF)             { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } | ||||
|         else if ((bom & 0xFFFF) == 0xFFFE)      { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take();                           } | ||||
|         else if ((bom & 0xFFFF) == 0xFEFF)      { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take();                           } | ||||
|         else if ((bom & 0xFFFFFF) == 0xBFBBEF)  { type_ = kUTF8;    hasBOM_ = true; is_->Take(); is_->Take(); is_->Take();              } | ||||
|  | ||||
|         // RFC 4627: Section 3 | ||||
|         // "Since the first two characters of a JSON text will always be ASCII | ||||
| @@ -270,23 +202,12 @@ private: | ||||
|         if (!hasBOM_) { | ||||
|             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; | ||||
|             case 0x01: | ||||
|                 type_ = kUTF32LE; | ||||
|                 break; | ||||
|             case 0x05: | ||||
|                 type_ = kUTF16LE; | ||||
|                 break; | ||||
|             case 0x0F: | ||||
|                 type_ = kUTF8; | ||||
|                 break; | ||||
|             default: | ||||
|                 break; // Use type defined by user. | ||||
|             case 0x08: type_ = kUTF32BE; break; | ||||
|             case 0x0A: type_ = kUTF16BE; break; | ||||
|             case 0x01: type_ = kUTF32LE; break; | ||||
|             case 0x05: type_ = kUTF16LE; break; | ||||
|             case 0x0F: type_ = kUTF8;    break; | ||||
|             default: break; // Use type defined by user. | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -311,7 +232,6 @@ private: | ||||
| template <typename CharType, typename OutputByteStream> | ||||
| class AutoUTFOutputStream { | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); | ||||
|  | ||||
| public: | ||||
|     typedef CharType Ch; | ||||
|  | ||||
| @@ -338,35 +258,20 @@ public: | ||||
|     UTFType GetType() const { return type_; } | ||||
|  | ||||
|     void Put(Ch c) { putFunc_(*os_, c); } | ||||
|     void Flush() { os_->Flush(); } | ||||
|     void Flush() { os_->Flush(); }  | ||||
|  | ||||
|     // Not implemented | ||||
|     Ch Peek() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch Take() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t Tell() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} | ||||
|     Ch Take() { RAPIDJSON_ASSERT(false); return 0;} | ||||
|     size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     AutoUTFOutputStream(const AutoUTFOutputStream&); | ||||
|     AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); | ||||
|  | ||||
|     void PutBOM() { | ||||
|     void PutBOM() {  | ||||
|         typedef void (*PutBOMFunc)(OutputByteStream&); | ||||
|         static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; | ||||
|         f[type_](*os_); | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_ENCODINGS_H_ | ||||
| @@ -20,7 +20,7 @@ | ||||
| #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 | ||||
| RAPIDJSON_DIAG_OFF(4702)  // unreachable code | ||||
| #elif defined(__GNUC__) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(effc++) | ||||
| @@ -92,15 +92,15 @@ concept Encoding { | ||||
|     \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. | ||||
|     \note implements Encoding concept | ||||
| */ | ||||
| template <typename CharType = char> | ||||
| template<typename CharType = char> | ||||
| struct UTF8 { | ||||
|     typedef CharType Ch; | ||||
|  | ||||
|     enum { supportUnicode = 1 }; | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void Encode(OutputStream& os, unsigned codepoint) { | ||||
|         if (codepoint <= 0x7F) | ||||
|         if (codepoint <= 0x7F)  | ||||
|             os.Put(static_cast<Ch>(codepoint & 0xFF)); | ||||
|         else if (codepoint <= 0x7FF) { | ||||
|             os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); | ||||
| @@ -120,9 +120,9 @@ struct UTF8 { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { | ||||
|         if (codepoint <= 0x7F) | ||||
|         if (codepoint <= 0x7F)  | ||||
|             PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); | ||||
|         else if (codepoint <= 0x7FF) { | ||||
|             PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); | ||||
| @@ -144,13 +144,9 @@ struct UTF8 { | ||||
|  | ||||
|     template <typename InputStream> | ||||
|     static bool Decode(InputStream& is, unsigned* codepoint) { | ||||
| #define RAPIDJSON_COPY() \ | ||||
|     c = is.Take();       \ | ||||
|     *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) | ||||
| #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) | ||||
| #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) | ||||
|         typename InputStream::Ch c = is.Take(); | ||||
|         if (!(c & 0x80)) { | ||||
|             *codepoint = static_cast<unsigned char>(c); | ||||
| @@ -160,48 +156,19 @@ struct UTF8 { | ||||
|         unsigned char type = GetRange(static_cast<unsigned char>(c)); | ||||
|         if (type >= 32) { | ||||
|             *codepoint = 0; | ||||
|         } | ||||
|         else { | ||||
|         } else { | ||||
|             *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c); | ||||
|         } | ||||
|         bool result = true; | ||||
|         switch (type) { | ||||
|         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; | ||||
|         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 RAPIDJSON_COPY | ||||
| #undef RAPIDJSON_TRANS | ||||
| @@ -210,11 +177,9 @@ struct UTF8 { | ||||
|  | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|     static bool Validate(InputStream& is, OutputStream& os) { | ||||
| #define RAPIDJSON_COPY()      os.Put(c = is.Take()) | ||||
| #define RAPIDJSON_COPY() os.Put(c = is.Take()) | ||||
| #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) | ||||
| #define RAPIDJSON_TAIL() \ | ||||
|     RAPIDJSON_COPY();    \ | ||||
|     RAPIDJSON_TRANS(0x70) | ||||
| #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) | ||||
|         Ch c; | ||||
|         RAPIDJSON_COPY(); | ||||
|         if (!(c & 0x80)) | ||||
| @@ -222,42 +187,14 @@ struct UTF8 { | ||||
|  | ||||
|         bool result = true; | ||||
|         switch (GetRange(static_cast<unsigned char>(c))) { | ||||
|         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; | ||||
|         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 RAPIDJSON_COPY | ||||
| #undef RAPIDJSON_TRANS | ||||
| @@ -268,262 +205,16 @@ struct UTF8 { | ||||
|         // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ | ||||
|         // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. | ||||
|         static const unsigned char type[] = { | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x10, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x40, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             0x20, | ||||
|             8, | ||||
|             8, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             2, | ||||
|             10, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             3, | ||||
|             4, | ||||
|             3, | ||||
|             3, | ||||
|             11, | ||||
|             6, | ||||
|             6, | ||||
|             6, | ||||
|             5, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             8, | ||||
|             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|             0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, | ||||
|             0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, | ||||
|             0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, | ||||
|             0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, | ||||
|             8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, | ||||
|             10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, | ||||
|         }; | ||||
|         return type[c]; | ||||
|     } | ||||
| @@ -574,18 +265,18 @@ struct UTF8 { | ||||
|     \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. | ||||
|     For streaming, use UTF16LE and UTF16BE, which handle endianness. | ||||
| */ | ||||
| template <typename CharType = wchar_t> | ||||
| template<typename CharType = wchar_t> | ||||
| struct UTF16 { | ||||
|     typedef CharType Ch; | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); | ||||
|  | ||||
|     enum { supportUnicode = 1 }; | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void Encode(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); | ||||
|         if (codepoint <= 0xFFFF) { | ||||
|             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair | ||||
|             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair  | ||||
|             os.Put(static_cast<typename OutputStream::Ch>(codepoint)); | ||||
|         } | ||||
|         else { | ||||
| @@ -597,11 +288,11 @@ struct UTF16 { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); | ||||
|         if (codepoint <= 0xFFFF) { | ||||
|             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair | ||||
|             RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair  | ||||
|             PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint)); | ||||
|         } | ||||
|         else { | ||||
| @@ -647,7 +338,7 @@ struct UTF16 { | ||||
| }; | ||||
|  | ||||
| //! UTF-16 little endian encoding. | ||||
| template <typename CharType = wchar_t> | ||||
| template<typename CharType = wchar_t> | ||||
| struct UTF16LE : UTF16<CharType> { | ||||
|     template <typename InputByteStream> | ||||
|     static CharType TakeBOM(InputByteStream& is) { | ||||
| @@ -680,7 +371,7 @@ struct UTF16LE : UTF16<CharType> { | ||||
| }; | ||||
|  | ||||
| //! UTF-16 big endian encoding. | ||||
| template <typename CharType = wchar_t> | ||||
| template<typename CharType = wchar_t> | ||||
| struct UTF16BE : UTF16<CharType> { | ||||
|     template <typename InputByteStream> | ||||
|     static CharType TakeBOM(InputByteStream& is) { | ||||
| @@ -715,7 +406,7 @@ struct UTF16BE : UTF16<CharType> { | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // UTF32 | ||||
|  | ||||
| //! UTF-32 encoding. | ||||
| //! UTF-32 encoding.  | ||||
| /*! http://en.wikipedia.org/wiki/UTF-32 | ||||
|     \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. | ||||
|     \note implements Encoding concept | ||||
| @@ -723,21 +414,21 @@ struct UTF16BE : UTF16<CharType> { | ||||
|     \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. | ||||
|     For streaming, use UTF32LE and UTF32BE, which handle endianness. | ||||
| */ | ||||
| template <typename CharType = unsigned> | ||||
| template<typename CharType = unsigned> | ||||
| struct UTF32 { | ||||
|     typedef CharType Ch; | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); | ||||
|  | ||||
|     enum { supportUnicode = 1 }; | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void Encode(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); | ||||
|         RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); | ||||
|         os.Put(codepoint); | ||||
|     } | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); | ||||
|         RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); | ||||
| @@ -762,7 +453,7 @@ struct UTF32 { | ||||
| }; | ||||
|  | ||||
| //! UTF-32 little endian enocoding. | ||||
| template <typename CharType = unsigned> | ||||
| template<typename CharType = unsigned> | ||||
| struct UTF32LE : UTF32<CharType> { | ||||
|     template <typename InputByteStream> | ||||
|     static CharType TakeBOM(InputByteStream& is) { | ||||
| @@ -801,13 +492,13 @@ struct UTF32LE : UTF32<CharType> { | ||||
| }; | ||||
|  | ||||
| //! UTF-32 big endian encoding. | ||||
| template <typename CharType = unsigned> | ||||
| template<typename CharType = unsigned> | ||||
| struct UTF32BE : UTF32<CharType> { | ||||
|     template <typename InputByteStream> | ||||
|     static CharType TakeBOM(InputByteStream& is) { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); | ||||
|         CharType c = Take(is); | ||||
|         return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; | ||||
|         return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;  | ||||
|     } | ||||
|  | ||||
|     template <typename InputByteStream> | ||||
| @@ -847,19 +538,19 @@ struct UTF32BE : UTF32<CharType> { | ||||
|     \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. | ||||
|     \note implements Encoding concept | ||||
| */ | ||||
| template <typename CharType = char> | ||||
| template<typename CharType = char> | ||||
| struct ASCII { | ||||
|     typedef CharType Ch; | ||||
|  | ||||
|     enum { supportUnicode = 0 }; | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void Encode(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_ASSERT(codepoint <= 0x7F); | ||||
|         os.Put(static_cast<Ch>(codepoint & 0xFF)); | ||||
|     } | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { | ||||
|         RAPIDJSON_ASSERT(codepoint <= 0x7F); | ||||
|         PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); | ||||
| @@ -910,17 +601,17 @@ struct ASCII { | ||||
|  | ||||
| //! Runtime-specified UTF encoding type of a stream. | ||||
| enum UTFType { | ||||
|     kUTF8 = 0,    //!< UTF-8. | ||||
|     kUTF16LE = 1, //!< UTF-16 little endian. | ||||
|     kUTF16BE = 2, //!< UTF-16 big endian. | ||||
|     kUTF32LE = 3, //!< UTF-32 little endian. | ||||
|     kUTF32BE = 4  //!< UTF-32 big endian. | ||||
|     kUTF8 = 0,      //!< UTF-8. | ||||
|     kUTF16LE = 1,   //!< UTF-16 little endian. | ||||
|     kUTF16BE = 2,   //!< UTF-16 big endian. | ||||
|     kUTF32LE = 3,   //!< UTF-32 little endian. | ||||
|     kUTF32BE = 4    //!< UTF-32 big endian. | ||||
| }; | ||||
|  | ||||
| //! Dynamically select encoding according to stream's runtime-specified UTF encoding type. | ||||
| /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). | ||||
| */ | ||||
| template <typename CharType> | ||||
| template<typename CharType> | ||||
| struct AutoUTF { | ||||
|     typedef CharType Ch; | ||||
|  | ||||
| @@ -928,14 +619,14 @@ struct AutoUTF { | ||||
|  | ||||
| #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x | ||||
|  | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     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> | ||||
|     template<typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { | ||||
|         typedef void (*EncodeFunc)(OutputStream&, unsigned); | ||||
|         static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; | ||||
| @@ -963,10 +654,10 @@ struct AutoUTF { | ||||
| // Transcoder | ||||
|  | ||||
| //! Encoding conversion. | ||||
| template <typename SourceEncoding, typename TargetEncoding> | ||||
| 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> | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { | ||||
|         unsigned codepoint; | ||||
|         if (!SourceEncoding::Decode(is, &codepoint)) | ||||
| @@ -975,7 +666,7 @@ struct Transcoder { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { | ||||
|         unsigned codepoint; | ||||
|         if (!SourceEncoding::Decode(is, &codepoint)) | ||||
| @@ -985,34 +676,34 @@ struct Transcoder { | ||||
|     } | ||||
|  | ||||
|     //! Validate one Unicode codepoint from an encoded stream. | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { | ||||
|         return Transcode(is, os); // Since source/target encoding is different, must transcode. | ||||
|         return Transcode(is, os);   // Since source/target encoding is different, must transcode. | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // Forward declaration. | ||||
| template <typename Stream> | ||||
| template<typename Stream> | ||||
| inline void PutUnsafe(Stream& stream, typename Stream::Ch c); | ||||
|  | ||||
| //! Specialization of Transcoder with same source and target encoding. | ||||
| template <typename Encoding> | ||||
| template<typename Encoding> | ||||
| struct Transcoder<Encoding, Encoding> { | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { | ||||
|         os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. | ||||
|         os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class. | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|      | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { | ||||
|         PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. | ||||
|         PutUnsafe(os, is.Take());  // Just copy one code unit. This semantic is different from primary template class. | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     template <typename InputStream, typename OutputStream> | ||||
|      | ||||
|     template<typename InputStream, typename OutputStream> | ||||
|     static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { | ||||
|         return Encoding::Validate(is, os); // source/target encoding are the same | ||||
|         return Encoding::Validate(is, os);  // source/target encoding are the same | ||||
|     } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_ERROR_EN_H_ | ||||
| @@ -19,8 +19,8 @@ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(switch - enum) | ||||
| RAPIDJSON_DIAG_OFF(covered - switch - default) | ||||
| RAPIDJSON_DIAG_OFF(switch-enum) | ||||
| RAPIDJSON_DIAG_OFF(covered-switch-default) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -35,52 +35,33 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| */ | ||||
| inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { | ||||
|     switch (parseErrorCode) { | ||||
|     case kParseErrorNone: | ||||
|         return RAPIDJSON_ERROR_STRING("No error."); | ||||
|         case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error."); | ||||
|  | ||||
|     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 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 kParseErrorValueInvalid: | ||||
|         return RAPIDJSON_ERROR_STRING("Invalid value."); | ||||
|         case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); | ||||
|         case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); | ||||
|         case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); | ||||
|         case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); | ||||
|         case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); | ||||
|  | ||||
|     case 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 kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); | ||||
|         case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); | ||||
|         case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number."); | ||||
|  | ||||
|     case kParseErrorArrayMissCommaOrSquareBracket: | ||||
|         return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); | ||||
|         case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); | ||||
|         case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); | ||||
|  | ||||
|     case kParseErrorStringUnicodeEscapeInvalidHex: | ||||
|         return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); | ||||
|     case kParseErrorStringUnicodeSurrogateInvalid: | ||||
|         return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); | ||||
|     case kParseErrorStringEscapeInvalid: | ||||
|         return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); | ||||
|     case kParseErrorStringMissQuotationMark: | ||||
|         return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); | ||||
|     case kParseErrorStringInvalidEncoding: | ||||
|         return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); | ||||
|  | ||||
|     case kParseErrorNumberTooBig: | ||||
|         return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); | ||||
|     case kParseErrorNumberMissFraction: | ||||
|         return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); | ||||
|     case kParseErrorNumberMissExponent: | ||||
|         return RAPIDJSON_ERROR_STRING("Miss exponent in number."); | ||||
|  | ||||
|     case kParseErrorTermination: | ||||
|         return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); | ||||
|     case kParseErrorUnspecificSyntaxError: | ||||
|         return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); | ||||
|  | ||||
|     default: | ||||
|         return RAPIDJSON_ERROR_STRING("Unknown error."); | ||||
|         default:                                        return RAPIDJSON_ERROR_STRING("Unknown error."); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -94,69 +75,41 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro | ||||
| */ | ||||
| inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) { | ||||
|     switch (validateErrorCode) { | ||||
|     case kValidateErrors: | ||||
|         return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); | ||||
|     case kValidateErrorNone: | ||||
|         return RAPIDJSON_ERROR_STRING("No error."); | ||||
|         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 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 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 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 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 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'."); | ||||
|     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 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'."); | ||||
|         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'."); | ||||
|  | ||||
|     default: | ||||
|         return RAPIDJSON_ERROR_STRING("Unknown error."); | ||||
|         default:                                        return RAPIDJSON_ERROR_STRING("Unknown error."); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_ERROR_ERROR_H_ | ||||
| @@ -62,31 +62,31 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|     \see GenericReader::Parse, GenericReader::GetParseErrorCode | ||||
| */ | ||||
| enum ParseErrorCode { | ||||
|     kParseErrorNone = 0, //!< No error. | ||||
|     kParseErrorNone = 0,                        //!< No error. | ||||
|  | ||||
|     kParseErrorDocumentEmpty,           //!< The document is empty. | ||||
|     kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. | ||||
|     kParseErrorDocumentEmpty,                   //!< The document is empty. | ||||
|     kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values. | ||||
|  | ||||
|     kParseErrorValueInvalid, //!< Invalid value. | ||||
|     kParseErrorValueInvalid,                    //!< Invalid value. | ||||
|  | ||||
|     kParseErrorObjectMissName,                //!< Missing a name for object member. | ||||
|     kParseErrorObjectMissColon,               //!< Missing a colon after a name of object member. | ||||
|     kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. | ||||
|     kParseErrorObjectMissName,                  //!< Missing a name for object member. | ||||
|     kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member. | ||||
|     kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member. | ||||
|  | ||||
|     kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. | ||||
|     kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element. | ||||
|  | ||||
|     kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. | ||||
|     kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. | ||||
|     kParseErrorStringEscapeInvalid,           //!< Invalid escape character in string. | ||||
|     kParseErrorStringMissQuotationMark,       //!< Missing a closing quotation mark in string. | ||||
|     kParseErrorStringInvalidEncoding,         //!< Invalid encoding in string. | ||||
|     kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string. | ||||
|     kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid. | ||||
|     kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string. | ||||
|     kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string. | ||||
|     kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string. | ||||
|  | ||||
|     kParseErrorNumberTooBig,       //!< Number too big to be stored in double. | ||||
|     kParseErrorNumberMissFraction, //!< Miss fraction part in number. | ||||
|     kParseErrorNumberMissExponent, //!< Miss exponent in number. | ||||
|     kParseErrorNumberTooBig,                    //!< Number too big to be stored in double. | ||||
|     kParseErrorNumberMissFraction,              //!< Miss fraction part in number. | ||||
|     kParseErrorNumberMissExponent,              //!< Miss exponent in number. | ||||
|  | ||||
|     kParseErrorTermination,          //!< Parsing was terminated. | ||||
|     kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. | ||||
|     kParseErrorTermination,                     //!< Parsing was terminated. | ||||
|     kParseErrorUnspecificSyntaxError            //!< Unspecific syntax error. | ||||
| }; | ||||
|  | ||||
| //! Result of parsing (wraps ParseErrorCode) | ||||
| @@ -106,7 +106,6 @@ enum ParseErrorCode { | ||||
| struct ParseResult { | ||||
|     //!! Unspecified boolean type | ||||
|     typedef bool (ParseResult::*BooleanType)() const; | ||||
|  | ||||
| public: | ||||
|     //! Default constructor, no error. | ||||
|     ParseResult() : code_(kParseErrorNone), offset_(0) {} | ||||
| @@ -125,19 +124,16 @@ public: | ||||
|  | ||||
|     bool operator==(const ParseResult& that) const { return code_ == that.code_; } | ||||
|     bool operator==(ParseErrorCode code) const { return code_ == code; } | ||||
|     friend bool operator==(ParseErrorCode code, const ParseResult& err) { return code == err.code_; } | ||||
|     friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } | ||||
|  | ||||
|     bool operator!=(const ParseResult& that) const { return !(*this == that); } | ||||
|     bool operator!=(ParseErrorCode code) const { return !(*this == code); } | ||||
|     friend bool operator!=(ParseErrorCode code, const ParseResult& err) { return err != code; } | ||||
|     friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } | ||||
|  | ||||
|     //! Reset error code. | ||||
|     void Clear() { Set(kParseErrorNone); } | ||||
|     //! Update error code and offset. | ||||
|     void Set(ParseErrorCode code, size_t offset = 0) { | ||||
|         code_ = code; | ||||
|         offset_ = offset; | ||||
|     } | ||||
|     void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } | ||||
|  | ||||
| private: | ||||
|     ParseErrorCode code_; | ||||
| @@ -164,39 +160,39 @@ typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); | ||||
|     \see GenericSchemaValidator | ||||
| */ | ||||
| enum ValidateErrorCode { | ||||
|     kValidateErrors = -1,   //!< Top level error code when kValidateContinueOnErrorsFlag set. | ||||
|     kValidateErrorNone = 0, //!< No error. | ||||
|     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. | ||||
|     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. | ||||
|     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. | ||||
|     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. | ||||
|     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.. | ||||
|     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'. | ||||
|     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'. | ||||
| }; | ||||
|  | ||||
| //! Function pointer type of GetValidateError(). | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_FILEREADSTREAM_H_ | ||||
| @@ -21,8 +21,8 @@ | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(padded) | ||||
| RAPIDJSON_DIAG_OFF(unreachable - code) | ||||
| RAPIDJSON_DIAG_OFF(missing - noreturn) | ||||
| RAPIDJSON_DIAG_OFF(unreachable-code) | ||||
| RAPIDJSON_DIAG_OFF(missing-noreturn) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -33,7 +33,7 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| */ | ||||
| class FileReadStream { | ||||
| public: | ||||
|     typedef char Ch; //!< Character type (byte). | ||||
|     typedef char Ch;    //!< Character type (byte). | ||||
|  | ||||
|     //! Constructor. | ||||
|     /*! | ||||
| @@ -41,31 +41,21 @@ public: | ||||
|         \param buffer user-supplied buffer. | ||||
|         \param bufferSize size of buffer in bytes. Must >=4 bytes. | ||||
|     */ | ||||
|     FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { | ||||
|     FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {  | ||||
|         RAPIDJSON_ASSERT(fp_ != 0); | ||||
|         RAPIDJSON_ASSERT(bufferSize >= 4); | ||||
|         Read(); | ||||
|     } | ||||
|  | ||||
|     Ch Peek() const { return *current_; } | ||||
|     Ch Take() { | ||||
|         Ch c = *current_; | ||||
|         Read(); | ||||
|         return c; | ||||
|     } | ||||
|     Ch Take() { Ch c = *current_; Read(); return c; } | ||||
|     size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } | ||||
|  | ||||
|     // Not implemented | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     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 { | ||||
| @@ -91,12 +81,12 @@ private: | ||||
|     } | ||||
|  | ||||
|     std::FILE* fp_; | ||||
|     Ch* buffer_; | ||||
|     Ch *buffer_; | ||||
|     size_t bufferSize_; | ||||
|     Ch* bufferLast_; | ||||
|     Ch* current_; | ||||
|     Ch *bufferLast_; | ||||
|     Ch *current_; | ||||
|     size_t readCount_; | ||||
|     size_t count_; //!< Number of characters read | ||||
|     size_t count_;  //!< Number of characters read | ||||
|     bool eof_; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_FILEWRITESTREAM_H_ | ||||
| @@ -20,7 +20,7 @@ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(unreachable - code) | ||||
| RAPIDJSON_DIAG_OFF(unreachable-code) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -31,13 +31,13 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| */ | ||||
| class FileWriteStream { | ||||
| public: | ||||
|     typedef char Ch; //!< Character type. Only support char. | ||||
|     typedef char Ch;    //!< Character type. Only support char. | ||||
|  | ||||
|     FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { | ||||
|     FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {  | ||||
|         RAPIDJSON_ASSERT(fp_ != 0); | ||||
|     } | ||||
|  | ||||
|     void Put(char c) { | ||||
|     void Put(char c) {  | ||||
|         if (current_ >= bufferEnd_) | ||||
|             Flush(); | ||||
|  | ||||
| @@ -72,26 +72,11 @@ public: | ||||
|     } | ||||
|  | ||||
|     // Not implemented | ||||
|     char Peek() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char Take() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t Tell() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(char*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char Peek() const { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     char Take() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     // Prohibit copy constructor & assignment operator. | ||||
| @@ -99,13 +84,13 @@ private: | ||||
|     FileWriteStream& operator=(const FileWriteStream&); | ||||
|  | ||||
|     std::FILE* fp_; | ||||
|     char* buffer_; | ||||
|     char* bufferEnd_; | ||||
|     char* current_; | ||||
|     char *buffer_; | ||||
|     char *bufferEnd_; | ||||
|     char *current_; | ||||
| }; | ||||
|  | ||||
| //! Implement specialized version of PutN() with memset() for better performance. | ||||
| template <> | ||||
| template<> | ||||
| inline void PutN(FileWriteStream& stream, char c, size_t n) { | ||||
|     stream.PutN(c, n); | ||||
| } | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_FWD_H_ | ||||
| @@ -21,26 +21,17 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
| // encodings.h | ||||
|  | ||||
| template <typename CharType> | ||||
| struct UTF8; | ||||
| template <typename CharType> | ||||
| struct UTF16; | ||||
| template <typename CharType> | ||||
| struct UTF16BE; | ||||
| template <typename CharType> | ||||
| struct UTF16LE; | ||||
| template <typename CharType> | ||||
| struct UTF32; | ||||
| template <typename CharType> | ||||
| struct UTF32BE; | ||||
| template <typename CharType> | ||||
| struct UTF32LE; | ||||
| template <typename CharType> | ||||
| struct ASCII; | ||||
| template <typename CharType> | ||||
| struct AutoUTF; | ||||
| template<typename CharType> struct UTF8; | ||||
| template<typename CharType> struct UTF16; | ||||
| template<typename CharType> struct UTF16BE; | ||||
| template<typename CharType> struct UTF16LE; | ||||
| template<typename CharType> struct UTF32; | ||||
| template<typename CharType> struct UTF32BE; | ||||
| template<typename CharType> struct UTF32LE; | ||||
| template<typename CharType> struct ASCII; | ||||
| template<typename CharType> struct AutoUTF; | ||||
|  | ||||
| template <typename SourceEncoding, typename TargetEncoding> | ||||
| template<typename SourceEncoding, typename TargetEncoding> | ||||
| struct Transcoder; | ||||
|  | ||||
| // allocators.h | ||||
| @@ -55,12 +46,12 @@ class MemoryPoolAllocator; | ||||
| template <typename Encoding> | ||||
| struct GenericStringStream; | ||||
|  | ||||
| typedef GenericStringStream<UTF8<char>> StringStream; | ||||
| typedef GenericStringStream<UTF8<char> > StringStream; | ||||
|  | ||||
| template <typename Encoding> | ||||
| struct GenericInsituStringStream; | ||||
|  | ||||
| typedef GenericInsituStringStream<UTF8<char>> InsituStringStream; | ||||
| typedef GenericInsituStringStream<UTF8<char> > InsituStringStream; | ||||
|  | ||||
| // stringbuffer.h | ||||
|  | ||||
| @@ -90,7 +81,7 @@ struct MemoryStream; | ||||
|  | ||||
| // reader.h | ||||
|  | ||||
| template <typename Encoding, typename Derived> | ||||
| template<typename Encoding, typename Derived> | ||||
| struct BaseReaderHandler; | ||||
|  | ||||
| template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator> | ||||
| @@ -100,29 +91,29 @@ typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader; | ||||
|  | ||||
| // writer.h | ||||
|  | ||||
| template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> | ||||
| template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> | ||||
| class Writer; | ||||
|  | ||||
| // prettywriter.h | ||||
|  | ||||
| template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> | ||||
| template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> | ||||
| class PrettyWriter; | ||||
|  | ||||
| // document.h | ||||
|  | ||||
| template <typename Encoding, typename Allocator> | ||||
| template <typename Encoding, typename Allocator>  | ||||
| class GenericMember; | ||||
|  | ||||
| template <bool Const, typename Encoding, typename Allocator> | ||||
| class GenericMemberIterator; | ||||
|  | ||||
| template <typename CharType> | ||||
| template<typename CharType> | ||||
| struct GenericStringRef; | ||||
|  | ||||
| template <typename Encoding, typename Allocator> | ||||
| template <typename Encoding, typename Allocator>  | ||||
| class GenericValue; | ||||
|  | ||||
| typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator>> Value; | ||||
| typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; | ||||
|  | ||||
| template <typename Encoding, typename Allocator, typename StackAllocator> | ||||
| class GenericDocument; | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_BIGINTEGER_H_ | ||||
| @@ -25,274 +25,264 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     class BigInteger { | ||||
|     public: | ||||
|         typedef uint64_t Type; | ||||
| class BigInteger { | ||||
| public: | ||||
|     typedef uint64_t Type; | ||||
|  | ||||
|         BigInteger(const BigInteger& rhs) : count_(rhs.count_) { | ||||
|     BigInteger(const BigInteger& rhs) : count_(rhs.count_) { | ||||
|         std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); | ||||
|     } | ||||
|  | ||||
|     explicit BigInteger(uint64_t u) : count_(1) { | ||||
|         digits_[0] = u; | ||||
|     } | ||||
|  | ||||
|     BigInteger(const char* decimals, size_t length) : count_(1) { | ||||
|         RAPIDJSON_ASSERT(length > 0); | ||||
|         digits_[0] = 0; | ||||
|         size_t i = 0; | ||||
|         const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19 | ||||
|         while (length >= kMaxDigitPerIteration) { | ||||
|             AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); | ||||
|             length -= kMaxDigitPerIteration; | ||||
|             i += kMaxDigitPerIteration; | ||||
|         } | ||||
|  | ||||
|         if (length > 0) | ||||
|             AppendDecimal64(decimals + i, decimals + i + length); | ||||
|     } | ||||
|      | ||||
|     BigInteger& operator=(const BigInteger &rhs) | ||||
|     { | ||||
|         if (this != &rhs) { | ||||
|             count_ = rhs.count_; | ||||
|             std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
|      | ||||
|     BigInteger& operator=(uint64_t u) { | ||||
|         digits_[0] = u;             | ||||
|         count_ = 1; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|         explicit BigInteger(uint64_t u) : count_(1) { | ||||
|             digits_[0] = u; | ||||
|     BigInteger& operator+=(uint64_t u) { | ||||
|         Type backup = digits_[0]; | ||||
|         digits_[0] += u; | ||||
|         for (size_t i = 0; i < count_ - 1; i++) { | ||||
|             if (digits_[i] >= backup) | ||||
|                 return *this; // no carry | ||||
|             backup = digits_[i + 1]; | ||||
|             digits_[i + 1] += 1; | ||||
|         } | ||||
|  | ||||
|         BigInteger(const char* decimals, size_t length) : count_(1) { | ||||
|             RAPIDJSON_ASSERT(length > 0); | ||||
|             digits_[0] = 0; | ||||
|             size_t i = 0; | ||||
|             const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 | ||||
|             while (length >= kMaxDigitPerIteration) { | ||||
|                 AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); | ||||
|                 length -= kMaxDigitPerIteration; | ||||
|                 i += kMaxDigitPerIteration; | ||||
|             } | ||||
|         // Last carry | ||||
|         if (digits_[count_ - 1] < backup) | ||||
|             PushBack(1); | ||||
|  | ||||
|             if (length > 0) | ||||
|                 AppendDecimal64(decimals + i, decimals + i + length); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     BigInteger& operator*=(uint64_t u) { | ||||
|         if (u == 0) return *this = 0; | ||||
|         if (u == 1) return *this; | ||||
|         if (*this == 1) return *this = u; | ||||
|  | ||||
|         uint64_t k = 0; | ||||
|         for (size_t i = 0; i < count_; i++) { | ||||
|             uint64_t hi; | ||||
|             digits_[i] = MulAdd64(digits_[i], u, k, &hi); | ||||
|             k = hi; | ||||
|         } | ||||
|          | ||||
|         if (k > 0) | ||||
|             PushBack(k); | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     BigInteger& operator*=(uint32_t u) { | ||||
|         if (u == 0) return *this = 0; | ||||
|         if (u == 1) return *this; | ||||
|         if (*this == 1) return *this = u; | ||||
|  | ||||
|         uint64_t k = 0; | ||||
|         for (size_t i = 0; i < count_; i++) { | ||||
|             const uint64_t c = digits_[i] >> 32; | ||||
|             const uint64_t d = digits_[i] & 0xFFFFFFFF; | ||||
|             const uint64_t uc = u * c; | ||||
|             const uint64_t ud = u * d; | ||||
|             const uint64_t p0 = ud + k; | ||||
|             const uint64_t p1 = uc + (p0 >> 32); | ||||
|             digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); | ||||
|             k = p1 >> 32; | ||||
|         } | ||||
|          | ||||
|         if (k > 0) | ||||
|             PushBack(k); | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     BigInteger& operator<<=(size_t shift) { | ||||
|         if (IsZero() || shift == 0) return *this; | ||||
|  | ||||
|         size_t offset = shift / kTypeBit; | ||||
|         size_t interShift = shift % kTypeBit; | ||||
|         RAPIDJSON_ASSERT(count_ + offset <= kCapacity); | ||||
|  | ||||
|         if (interShift == 0) { | ||||
|             std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); | ||||
|             count_ += offset; | ||||
|         } | ||||
|         else { | ||||
|             digits_[count_] = 0; | ||||
|             for (size_t i = count_; i > 0; i--) | ||||
|                 digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); | ||||
|             digits_[offset] = digits_[0] << interShift; | ||||
|             count_ += offset; | ||||
|             if (digits_[count_]) | ||||
|                 count_++; | ||||
|         } | ||||
|  | ||||
|         BigInteger& operator=(const BigInteger& rhs) { | ||||
|             if (this != &rhs) { | ||||
|                 count_ = rhs.count_; | ||||
|                 std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); | ||||
|             } | ||||
|             return *this; | ||||
|         std::memset(digits_, 0, offset * sizeof(Type)); | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     bool operator==(const BigInteger& rhs) const { | ||||
|         return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; | ||||
|     } | ||||
|  | ||||
|     bool operator==(const Type rhs) const { | ||||
|         return count_ == 1 && digits_[0] == rhs; | ||||
|     } | ||||
|  | ||||
|     BigInteger& MultiplyPow5(unsigned exp) { | ||||
|         static const uint32_t kPow5[12] = { | ||||
|             5, | ||||
|             5 * 5, | ||||
|             5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|             5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 | ||||
|         }; | ||||
|         if (exp == 0) return *this; | ||||
|         for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 | ||||
|         for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13 | ||||
|         if (exp > 0)                 *this *= kPow5[exp - 1]; | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     // Compute absolute difference of this and rhs. | ||||
|     // Assume this != rhs | ||||
|     bool Difference(const BigInteger& rhs, BigInteger* out) const { | ||||
|         int cmp = Compare(rhs); | ||||
|         RAPIDJSON_ASSERT(cmp != 0); | ||||
|         const BigInteger *a, *b;  // Makes a > b | ||||
|         bool ret; | ||||
|         if (cmp < 0) { a = &rhs; b = this; ret = true; } | ||||
|         else         { a = this; b = &rhs; ret = false; } | ||||
|  | ||||
|         Type borrow = 0; | ||||
|         for (size_t i = 0; i < a->count_; i++) { | ||||
|             Type d = a->digits_[i] - borrow; | ||||
|             if (i < b->count_) | ||||
|                 d -= b->digits_[i]; | ||||
|             borrow = (d > a->digits_[i]) ? 1 : 0; | ||||
|             out->digits_[i] = d; | ||||
|             if (d != 0) | ||||
|                 out->count_ = i + 1; | ||||
|         } | ||||
|  | ||||
|         BigInteger& operator=(uint64_t u) { | ||||
|             digits_[0] = u; | ||||
|             count_ = 1; | ||||
|             return *this; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     int Compare(const BigInteger& rhs) const { | ||||
|         if (count_ != rhs.count_) | ||||
|             return count_ < rhs.count_ ? -1 : 1; | ||||
|  | ||||
|         for (size_t i = count_; i-- > 0;) | ||||
|             if (digits_[i] != rhs.digits_[i]) | ||||
|                 return digits_[i] < rhs.digits_[i] ? -1 : 1; | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     size_t GetCount() const { return count_; } | ||||
|     Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } | ||||
|     bool IsZero() const { return count_ == 1 && digits_[0] == 0; } | ||||
|  | ||||
| private: | ||||
|     void AppendDecimal64(const char* begin, const char* end) { | ||||
|         uint64_t u = ParseUint64(begin, end); | ||||
|         if (IsZero()) | ||||
|             *this = u; | ||||
|         else { | ||||
|             unsigned exp = static_cast<unsigned>(end - begin); | ||||
|             (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         BigInteger& operator+=(uint64_t u) { | ||||
|             Type backup = digits_[0]; | ||||
|             digits_[0] += u; | ||||
|             for (size_t i = 0; i < count_ - 1; i++) { | ||||
|                 if (digits_[i] >= backup) | ||||
|                     return *this; // no carry | ||||
|                 backup = digits_[i + 1]; | ||||
|                 digits_[i + 1] += 1; | ||||
|             } | ||||
|     void PushBack(Type digit) { | ||||
|         RAPIDJSON_ASSERT(count_ < kCapacity); | ||||
|         digits_[count_++] = digit; | ||||
|     } | ||||
|  | ||||
|             // Last carry | ||||
|             if (digits_[count_ - 1] < backup) | ||||
|                 PushBack(1); | ||||
|  | ||||
|             return *this; | ||||
|     static uint64_t ParseUint64(const char* begin, const char* end) { | ||||
|         uint64_t r = 0; | ||||
|         for (const char* p = begin; p != end; ++p) { | ||||
|             RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); | ||||
|             r = r * 10u + static_cast<unsigned>(*p - '0'); | ||||
|         } | ||||
|         return r; | ||||
|     } | ||||
|  | ||||
|         BigInteger& operator*=(uint64_t u) { | ||||
|             if (u == 0) return *this = 0; | ||||
|             if (u == 1) return *this; | ||||
|             if (*this == 1) return *this = u; | ||||
|  | ||||
|             uint64_t k = 0; | ||||
|             for (size_t i = 0; i < count_; i++) { | ||||
|                 uint64_t hi; | ||||
|                 digits_[i] = MulAdd64(digits_[i], u, k, &hi); | ||||
|                 k = hi; | ||||
|             } | ||||
|  | ||||
|             if (k > 0) | ||||
|                 PushBack(k); | ||||
|  | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         BigInteger& operator*=(uint32_t u) { | ||||
|             if (u == 0) return *this = 0; | ||||
|             if (u == 1) return *this; | ||||
|             if (*this == 1) return *this = u; | ||||
|  | ||||
|             uint64_t k = 0; | ||||
|             for (size_t i = 0; i < count_; i++) { | ||||
|                 const uint64_t c = digits_[i] >> 32; | ||||
|                 const uint64_t d = digits_[i] & 0xFFFFFFFF; | ||||
|                 const uint64_t uc = u * c; | ||||
|                 const uint64_t ud = u * d; | ||||
|                 const uint64_t p0 = ud + k; | ||||
|                 const uint64_t p1 = uc + (p0 >> 32); | ||||
|                 digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); | ||||
|                 k = p1 >> 32; | ||||
|             } | ||||
|  | ||||
|             if (k > 0) | ||||
|                 PushBack(k); | ||||
|  | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         BigInteger& operator<<=(size_t shift) { | ||||
|             if (IsZero() || shift == 0) return *this; | ||||
|  | ||||
|             size_t offset = shift / kTypeBit; | ||||
|             size_t interShift = shift % kTypeBit; | ||||
|             RAPIDJSON_ASSERT(count_ + offset <= kCapacity); | ||||
|  | ||||
|             if (interShift == 0) { | ||||
|                 std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); | ||||
|                 count_ += offset; | ||||
|             } | ||||
|             else { | ||||
|                 digits_[count_] = 0; | ||||
|                 for (size_t i = count_; i > 0; i--) | ||||
|                     digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); | ||||
|                 digits_[offset] = digits_[0] << interShift; | ||||
|                 count_ += offset; | ||||
|                 if (digits_[count_]) | ||||
|                     count_++; | ||||
|             } | ||||
|  | ||||
|             std::memset(digits_, 0, offset * sizeof(Type)); | ||||
|  | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         bool operator==(const BigInteger& rhs) const { | ||||
|             return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; | ||||
|         } | ||||
|  | ||||
|         bool operator==(const Type rhs) const { | ||||
|             return count_ == 1 && digits_[0] == rhs; | ||||
|         } | ||||
|  | ||||
|         BigInteger& MultiplyPow5(unsigned exp) { | ||||
|             static const uint32_t kPow5[12] = { | ||||
|                 5, | ||||
|                 5 * 5, | ||||
|                 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, | ||||
|                 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 | ||||
|             }; | ||||
|             if (exp == 0) return *this; | ||||
|             for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 | ||||
|             for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u);          // 5^13 | ||||
|             if (exp > 0) *this *= kPow5[exp - 1]; | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         // Compute absolute difference of this and rhs. | ||||
|         // Assume this != rhs | ||||
|         bool Difference(const BigInteger& rhs, BigInteger* out) const { | ||||
|             int cmp = Compare(rhs); | ||||
|             RAPIDJSON_ASSERT(cmp != 0); | ||||
|             const BigInteger *a, *b; // Makes a > b | ||||
|             bool ret; | ||||
|             if (cmp < 0) { | ||||
|                 a = &rhs; | ||||
|                 b = this; | ||||
|                 ret = true; | ||||
|             } | ||||
|             else { | ||||
|                 a = this; | ||||
|                 b = &rhs; | ||||
|                 ret = false; | ||||
|             } | ||||
|  | ||||
|             Type borrow = 0; | ||||
|             for (size_t i = 0; i < a->count_; i++) { | ||||
|                 Type d = a->digits_[i] - borrow; | ||||
|                 if (i < b->count_) | ||||
|                     d -= b->digits_[i]; | ||||
|                 borrow = (d > a->digits_[i]) ? 1 : 0; | ||||
|                 out->digits_[i] = d; | ||||
|                 if (d != 0) | ||||
|                     out->count_ = i + 1; | ||||
|             } | ||||
|  | ||||
|             return ret; | ||||
|         } | ||||
|  | ||||
|         int Compare(const BigInteger& rhs) const { | ||||
|             if (count_ != rhs.count_) | ||||
|                 return count_ < rhs.count_ ? -1 : 1; | ||||
|  | ||||
|             for (size_t i = count_; i-- > 0;) | ||||
|                 if (digits_[i] != rhs.digits_[i]) | ||||
|                     return digits_[i] < rhs.digits_[i] ? -1 : 1; | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         size_t GetCount() const { return count_; } | ||||
|         Type GetDigit(size_t index) const { | ||||
|             RAPIDJSON_ASSERT(index < count_); | ||||
|             return digits_[index]; | ||||
|         } | ||||
|         bool IsZero() const { return count_ == 1 && digits_[0] == 0; } | ||||
|  | ||||
|     private: | ||||
|         void AppendDecimal64(const char* begin, const char* end) { | ||||
|             uint64_t u = ParseUint64(begin, end); | ||||
|             if (IsZero()) | ||||
|                 *this = u; | ||||
|             else { | ||||
|                 unsigned exp = static_cast<unsigned>(end - begin); | ||||
|                 (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         void PushBack(Type digit) { | ||||
|             RAPIDJSON_ASSERT(count_ < kCapacity); | ||||
|             digits_[count_++] = digit; | ||||
|         } | ||||
|  | ||||
|         static uint64_t ParseUint64(const char* begin, const char* end) { | ||||
|             uint64_t r = 0; | ||||
|             for (const char* p = begin; p != end; ++p) { | ||||
|                 RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); | ||||
|                 r = r * 10u + static_cast<unsigned>(*p - '0'); | ||||
|             } | ||||
|             return r; | ||||
|         } | ||||
|  | ||||
|         // Assume a * b + k < 2^128 | ||||
|         static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { | ||||
|     // Assume a * b + k < 2^128 | ||||
|     static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { | ||||
| #if defined(_MSC_VER) && defined(_M_AMD64) | ||||
|             uint64_t low = _umul128(a, b, outHigh) + k; | ||||
|             if (low < k) | ||||
|                 (*outHigh)++; | ||||
|             return low; | ||||
|         uint64_t low = _umul128(a, b, outHigh) + k; | ||||
|         if (low < k) | ||||
|             (*outHigh)++; | ||||
|         return low; | ||||
| #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) | ||||
|             __extension__ typedef unsigned __int128 uint128; | ||||
|             uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); | ||||
|             p += k; | ||||
|             *outHigh = static_cast<uint64_t>(p >> 64); | ||||
|             return static_cast<uint64_t>(p); | ||||
|         __extension__ typedef unsigned __int128 uint128; | ||||
|         uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); | ||||
|         p += k; | ||||
|         *outHigh = static_cast<uint64_t>(p >> 64); | ||||
|         return static_cast<uint64_t>(p); | ||||
| #else | ||||
|             const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; | ||||
|             uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; | ||||
|             x1 += (x0 >> 32); // can't give carry | ||||
|             x1 += x2; | ||||
|             if (x1 < x2) | ||||
|                 x3 += (static_cast<uint64_t>(1) << 32); | ||||
|             uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); | ||||
|             uint64_t hi = x3 + (x1 >> 32); | ||||
|         const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; | ||||
|         uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; | ||||
|         x1 += (x0 >> 32); // can't give carry | ||||
|         x1 += x2; | ||||
|         if (x1 < x2) | ||||
|             x3 += (static_cast<uint64_t>(1) << 32); | ||||
|         uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); | ||||
|         uint64_t hi = x3 + (x1 >> 32); | ||||
|  | ||||
|             lo += k; | ||||
|             if (lo < k) | ||||
|                 hi++; | ||||
|             *outHigh = hi; | ||||
|             return lo; | ||||
|         lo += k; | ||||
|         if (lo < k) | ||||
|             hi++; | ||||
|         *outHigh = hi; | ||||
|         return lo; | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 | ||||
|         static const size_t kCapacity = kBitCount / sizeof(Type); | ||||
|         static const size_t kTypeBit = sizeof(Type) * 8; | ||||
|     static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000 | ||||
|     static const size_t kCapacity = kBitCount / sizeof(Type); | ||||
|     static const size_t kTypeBit = sizeof(Type) * 8; | ||||
|  | ||||
|         Type digits_[kCapacity]; | ||||
|         size_t count_; | ||||
|     }; | ||||
|     Type digits_[kCapacity]; | ||||
|     size_t count_; | ||||
| }; | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -29,40 +29,40 @@ | ||||
| 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); | ||||
| 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; | ||||
|     unsigned long r = 0; | ||||
| #if defined(_WIN64) | ||||
|         _BitScanReverse64(&r, x); | ||||
|     _BitScanReverse64(&r, x); | ||||
| #else | ||||
|         // Scan the high 32 bits. | ||||
|         if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) | ||||
|             return 63 - (r + 32); | ||||
|     // 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)); | ||||
|     // Scan the low 32 bits. | ||||
|     _BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF)); | ||||
| #endif // _WIN64 | ||||
|  | ||||
|         return 63 - r; | ||||
|     return 63 - r; | ||||
| #elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) | ||||
|         // __builtin_clzll wrapper | ||||
|         return static_cast<uint32_t>(__builtin_clzll(x)); | ||||
|     // __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 | ||||
|     // 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 | ||||
|   | ||||
| @@ -32,222 +32,223 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
|     RAPIDJSON_DIAG_PUSH | ||||
|     RAPIDJSON_DIAG_OFF(effc++) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(effc++) | ||||
| #endif | ||||
|  | ||||
| #ifdef __clang__ | ||||
|     RAPIDJSON_DIAG_PUSH | ||||
|     RAPIDJSON_DIAG_OFF(padded) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(padded) | ||||
| #endif | ||||
|  | ||||
|     struct DiyFp { | ||||
|         DiyFp() : f(), e() {} | ||||
| struct DiyFp { | ||||
|     DiyFp() : f(), e() {} | ||||
|  | ||||
|         DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} | ||||
|     DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} | ||||
|  | ||||
|         explicit DiyFp(double d) { | ||||
|             union { | ||||
|                 double d; | ||||
|                 uint64_t u64; | ||||
|             } u = { d }; | ||||
|     explicit DiyFp(double d) { | ||||
|         union { | ||||
|             double d; | ||||
|             uint64_t u64; | ||||
|         } u = { d }; | ||||
|  | ||||
|             int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize); | ||||
|             uint64_t significand = (u.u64 & kDpSignificandMask); | ||||
|             if (biased_e != 0) { | ||||
|                 f = significand + kDpHiddenBit; | ||||
|                 e = biased_e - kDpExponentBias; | ||||
|             } | ||||
|             else { | ||||
|                 f = significand; | ||||
|                 e = kDpMinExponent + 1; | ||||
|             } | ||||
|         int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize); | ||||
|         uint64_t significand = (u.u64 & kDpSignificandMask); | ||||
|         if (biased_e != 0) { | ||||
|             f = significand + kDpHiddenBit; | ||||
|             e = biased_e - kDpExponentBias; | ||||
|         } | ||||
|  | ||||
|         DiyFp operator-(const DiyFp& rhs) const { | ||||
|             return DiyFp(f - rhs.f, e); | ||||
|         else { | ||||
|             f = significand; | ||||
|             e = kDpMinExponent + 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         DiyFp operator*(const DiyFp& rhs) const { | ||||
|     DiyFp operator-(const DiyFp& rhs) const { | ||||
|         return DiyFp(f - rhs.f, e); | ||||
|     } | ||||
|  | ||||
|     DiyFp operator*(const DiyFp& rhs) const { | ||||
| #if defined(_MSC_VER) && defined(_M_AMD64) | ||||
|             uint64_t h; | ||||
|             uint64_t l = _umul128(f, rhs.f, &h); | ||||
|             if (l & (uint64_t(1) << 63)) // rounding | ||||
|                 h++; | ||||
|             return DiyFp(h, e + rhs.e + 64); | ||||
|         uint64_t h; | ||||
|         uint64_t l = _umul128(f, rhs.f, &h); | ||||
|         if (l & (uint64_t(1) << 63)) // rounding | ||||
|             h++; | ||||
|         return DiyFp(h, e + rhs.e + 64); | ||||
| #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) | ||||
|             __extension__ typedef unsigned __int128 uint128; | ||||
|             uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); | ||||
|             uint64_t h = static_cast<uint64_t>(p >> 64); | ||||
|             uint64_t l = static_cast<uint64_t>(p); | ||||
|             if (l & (uint64_t(1) << 63)) // rounding | ||||
|                 h++; | ||||
|             return DiyFp(h, e + rhs.e + 64); | ||||
|         __extension__ typedef unsigned __int128 uint128; | ||||
|         uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); | ||||
|         uint64_t h = static_cast<uint64_t>(p >> 64); | ||||
|         uint64_t l = static_cast<uint64_t>(p); | ||||
|         if (l & (uint64_t(1) << 63)) // rounding | ||||
|             h++; | ||||
|         return DiyFp(h, e + rhs.e + 64); | ||||
| #else | ||||
|             const uint64_t M32 = 0xFFFFFFFF; | ||||
|             const uint64_t a = f >> 32; | ||||
|             const uint64_t b = f & M32; | ||||
|             const uint64_t c = rhs.f >> 32; | ||||
|             const uint64_t d = rhs.f & M32; | ||||
|             const uint64_t ac = a * c; | ||||
|             const uint64_t bc = b * c; | ||||
|             const uint64_t ad = a * d; | ||||
|             const uint64_t bd = b * d; | ||||
|             uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); | ||||
|             tmp += 1U << 31; /// mult_round | ||||
|             return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); | ||||
|         const uint64_t M32 = 0xFFFFFFFF; | ||||
|         const uint64_t a = f >> 32; | ||||
|         const uint64_t b = f & M32; | ||||
|         const uint64_t c = rhs.f >> 32; | ||||
|         const uint64_t d = rhs.f & M32; | ||||
|         const uint64_t ac = a * c; | ||||
|         const uint64_t bc = b * c; | ||||
|         const uint64_t ad = a * d; | ||||
|         const uint64_t bd = b * d; | ||||
|         uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); | ||||
|         tmp += 1U << 31;  /// mult_round | ||||
|         return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     DiyFp Normalize() const { | ||||
|         int s = static_cast<int>(clzll(f)); | ||||
|         return DiyFp(f << s, e - s); | ||||
|     } | ||||
|  | ||||
|     DiyFp NormalizeBoundary() const { | ||||
|         DiyFp res = *this; | ||||
|         while (!(res.f & (kDpHiddenBit << 1))) { | ||||
|             res.f <<= 1; | ||||
|             res.e--; | ||||
|         } | ||||
|         res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); | ||||
|         res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|         DiyFp Normalize() const { | ||||
|             int s = static_cast<int>(clzll(f)); | ||||
|             return DiyFp(f << s, e - s); | ||||
|     void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { | ||||
|         DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); | ||||
|         DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); | ||||
|         mi.f <<= mi.e - pl.e; | ||||
|         mi.e = pl.e; | ||||
|         *plus = pl; | ||||
|         *minus = mi; | ||||
|     } | ||||
|  | ||||
|     double ToDouble() const { | ||||
|         union { | ||||
|             double d; | ||||
|             uint64_t u64; | ||||
|         }u; | ||||
|         RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); | ||||
|         if (e < kDpDenormalExponent) { | ||||
|             // Underflow. | ||||
|             return 0.0; | ||||
|         } | ||||
|  | ||||
|         DiyFp NormalizeBoundary() const { | ||||
|             DiyFp res = *this; | ||||
|             while (!(res.f & (kDpHiddenBit << 1))) { | ||||
|                 res.f <<= 1; | ||||
|                 res.e--; | ||||
|             } | ||||
|             res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); | ||||
|             res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); | ||||
|             return res; | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|         void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { | ||||
|             DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); | ||||
|             DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); | ||||
|             mi.f <<= mi.e - pl.e; | ||||
|             mi.e = pl.e; | ||||
|             *plus = pl; | ||||
|             *minus = mi; | ||||
|         } | ||||
|     static const int kDiySignificandSize = 64; | ||||
|     static const int kDpSignificandSize = 52; | ||||
|     static const int kDpExponentBias = 0x3FF + kDpSignificandSize; | ||||
|     static const int kDpMaxExponent = 0x7FF - kDpExponentBias; | ||||
|     static const int kDpMinExponent = -kDpExponentBias; | ||||
|     static const int kDpDenormalExponent = -kDpExponentBias + 1; | ||||
|     static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); | ||||
|     static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); | ||||
|     static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); | ||||
|  | ||||
|         double ToDouble() const { | ||||
|             union { | ||||
|                 double d; | ||||
|                 uint64_t u64; | ||||
|             } u; | ||||
|             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; | ||||
|         } | ||||
|     uint64_t f; | ||||
|     int e; | ||||
| }; | ||||
|  | ||||
|         static const int kDiySignificandSize = 64; | ||||
|         static const int kDpSignificandSize = 52; | ||||
|         static const int kDpExponentBias = 0x3FF + kDpSignificandSize; | ||||
|         static const int kDpMaxExponent = 0x7FF - kDpExponentBias; | ||||
|         static const int kDpMinExponent = -kDpExponentBias; | ||||
|         static const int kDpDenormalExponent = -kDpExponentBias + 1; | ||||
|         static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); | ||||
|         static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); | ||||
|         static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); | ||||
|  | ||||
|         uint64_t f; | ||||
|         int e; | ||||
| inline DiyFp GetCachedPowerByIndex(size_t index) { | ||||
|     // 10^-348, 10^-340, ..., 10^340 | ||||
|     static const uint64_t kCachedPowers_F[] = { | ||||
|         RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), | ||||
|         RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), | ||||
|         RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), | ||||
|         RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), | ||||
|         RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), | ||||
|         RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), | ||||
|         RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), | ||||
|         RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), | ||||
|         RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), | ||||
|         RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), | ||||
|         RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), | ||||
|         RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), | ||||
|         RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), | ||||
|         RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), | ||||
|         RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), | ||||
|         RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), | ||||
|         RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), | ||||
|         RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), | ||||
|         RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), | ||||
|         RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), | ||||
|         RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), | ||||
|         RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), | ||||
|         RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), | ||||
|         RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), | ||||
|         RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), | ||||
|         RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), | ||||
|         RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), | ||||
|         RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), | ||||
|         RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), | ||||
|         RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), | ||||
|         RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), | ||||
|         RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), | ||||
|         RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), | ||||
|         RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), | ||||
|         RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), | ||||
|         RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), | ||||
|         RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), | ||||
|         RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), | ||||
|         RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), | ||||
|         RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), | ||||
|         RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), | ||||
|         RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), | ||||
|         RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), | ||||
|         RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) | ||||
|     }; | ||||
|     static const int16_t kCachedPowers_E[] = { | ||||
|         -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980, | ||||
|         -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715, | ||||
|         -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449, | ||||
|         -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183, | ||||
|         -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83, | ||||
|         109,   136,   162,   189,   216,   242,   269,   295,   322,   348, | ||||
|         375,   402,   428,   455,   481,   508,   534,   561,   588,   614, | ||||
|         641,   667,   694,   720,   747,   774,   800,   827,   853,   880, | ||||
|         907,   933,   960,   986,  1013,  1039,  1066 | ||||
|     }; | ||||
|     RAPIDJSON_ASSERT(index < 87); | ||||
|     return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); | ||||
| } | ||||
|  | ||||
|     inline DiyFp GetCachedPowerByIndex(size_t index) { | ||||
|         // 10^-348, 10^-340, ..., 10^340 | ||||
|         static const uint64_t kCachedPowers_F[] = { | ||||
|             RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), | ||||
|             RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), | ||||
|             RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), | ||||
|             RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), | ||||
|             RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), | ||||
|             RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), | ||||
|             RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), | ||||
|             RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), | ||||
|             RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), | ||||
|             RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), | ||||
|             RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), | ||||
|             RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), | ||||
|             RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), | ||||
|             RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), | ||||
|             RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), | ||||
|             RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), | ||||
|             RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), | ||||
|             RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), | ||||
|             RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), | ||||
|             RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), | ||||
|             RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), | ||||
|             RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), | ||||
|             RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), | ||||
|             RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), | ||||
|             RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), | ||||
|             RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), | ||||
|             RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), | ||||
|             RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), | ||||
|             RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), | ||||
|             RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), | ||||
|             RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), | ||||
|             RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), | ||||
|             RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), | ||||
|             RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), | ||||
|             RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), | ||||
|             RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), | ||||
|             RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), | ||||
|             RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), | ||||
|             RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), | ||||
|             RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), | ||||
|             RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), | ||||
|             RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), | ||||
|             RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), | ||||
|             RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) | ||||
|         }; | ||||
|         static const int16_t kCachedPowers_E[] = { | ||||
|             -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, | ||||
|             -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, | ||||
|             -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, | ||||
|             -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, | ||||
|             -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, | ||||
|             109, 136, 162, 189, 216, 242, 269, 295, 322, 348, | ||||
|             375, 402, 428, 455, 481, 508, 534, 561, 588, 614, | ||||
|             641, 667, 694, 720, 747, 774, 800, 827, 853, 880, | ||||
|             907, 933, 960, 986, 1013, 1039, 1066 | ||||
|         }; | ||||
|         RAPIDJSON_ASSERT(index < 87); | ||||
|         return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); | ||||
|     } | ||||
| inline DiyFp GetCachedPower(int e, int* K) { | ||||
|  | ||||
|     inline DiyFp GetCachedPower(int e, int* K) { | ||||
|     //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; | ||||
|     double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive | ||||
|     int k = static_cast<int>(dk); | ||||
|     if (dk - k > 0.0) | ||||
|         k++; | ||||
|  | ||||
|         //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; | ||||
|         double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive | ||||
|         int k = static_cast<int>(dk); | ||||
|         if (dk - k > 0.0) | ||||
|             k++; | ||||
|     unsigned index = static_cast<unsigned>((k >> 3) + 1); | ||||
|     *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table | ||||
|  | ||||
|         unsigned index = static_cast<unsigned>((k >> 3) + 1); | ||||
|         *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table | ||||
|     return GetCachedPowerByIndex(index); | ||||
| } | ||||
|  | ||||
|         return GetCachedPowerByIndex(index); | ||||
|     } | ||||
|  | ||||
|     inline DiyFp GetCachedPower10(int exp, int* outExp) { | ||||
|         RAPIDJSON_ASSERT(exp >= -348); | ||||
|         unsigned index = static_cast<unsigned>(exp + 348) / 8u; | ||||
|         *outExp = -348 + static_cast<int>(index) * 8; | ||||
|         return GetCachedPowerByIndex(index); | ||||
|     } | ||||
| inline DiyFp GetCachedPower10(int exp, int *outExp) { | ||||
|     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 | ||||
| RAPIDJSON_DIAG_POP | ||||
| #endif | ||||
|  | ||||
| #ifdef __clang__ | ||||
|     RAPIDJSON_DIAG_POP | ||||
|     RAPIDJSON_DIAG_OFF(padded) | ||||
| RAPIDJSON_DIAG_POP | ||||
| RAPIDJSON_DIAG_OFF(padded) | ||||
| #endif | ||||
|  | ||||
| } // namespace internal | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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. | ||||
|  | ||||
| // This is a C++ header-only implementation of Grisu2 algorithm from the publication: | ||||
| @@ -27,243 +27,216 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
|     RAPIDJSON_DIAG_PUSH | ||||
|     RAPIDJSON_DIAG_OFF(effc++) | ||||
|     RAPIDJSON_DIAG_OFF(array - bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(effc++) | ||||
| RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 | ||||
| #endif | ||||
|  | ||||
|     inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { | ||||
|         while (rest < wp_w && delta - rest >= ten_kappa && | ||||
|                (rest + ten_kappa < wp_w || /// closer | ||||
|                 wp_w - rest > rest + ten_kappa - wp_w)) { | ||||
|             buffer[len - 1]--; | ||||
|             rest += ten_kappa; | ||||
|         } | ||||
| inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { | ||||
|     while (rest < wp_w && delta - rest >= ten_kappa && | ||||
|            (rest + ten_kappa < wp_w ||  /// closer | ||||
|             wp_w - rest > rest + ten_kappa - wp_w)) { | ||||
|         buffer[len - 1]--; | ||||
|         rest += ten_kappa; | ||||
|     } | ||||
| } | ||||
|  | ||||
|     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; | ||||
|         if (n < 1000) return 3; | ||||
|         if (n < 10000) return 4; | ||||
|         if (n < 100000) return 5; | ||||
|         if (n < 1000000) return 6; | ||||
|         if (n < 10000000) return 7; | ||||
|         if (n < 100000000) return 8; | ||||
|         // Will not reach 10 digits in DigitGen() | ||||
|         //if (n < 1000000000) return 9; | ||||
|         //return 10; | ||||
|         return 9; | ||||
|     } | ||||
| 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; | ||||
|     if (n < 1000) return 3; | ||||
|     if (n < 10000) return 4; | ||||
|     if (n < 100000) return 5; | ||||
|     if (n < 1000000) return 6; | ||||
|     if (n < 10000000) return 7; | ||||
|     if (n < 100000000) return 8; | ||||
|     // Will not reach 10 digits in DigitGen() | ||||
|     //if (n < 1000000000) return 9; | ||||
|     //return 10; | ||||
|     return 9; | ||||
| } | ||||
|  | ||||
|     inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { | ||||
|         static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; | ||||
|         const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); | ||||
|         const DiyFp wp_w = Mp - W; | ||||
|         uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); | ||||
|         uint64_t p2 = Mp.f & (one.f - 1); | ||||
|         int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] | ||||
|         *len = 0; | ||||
| 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 }; | ||||
|     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); | ||||
|     int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] | ||||
|     *len = 0; | ||||
|  | ||||
|         while (kappa > 0) { | ||||
|             uint32_t d = 0; | ||||
|             switch (kappa) { | ||||
|             case 9: | ||||
|                 d = p1 / 100000000; | ||||
|                 p1 %= 100000000; | ||||
|                 break; | ||||
|             case 8: | ||||
|                 d = p1 / 10000000; | ||||
|                 p1 %= 10000000; | ||||
|                 break; | ||||
|             case 7: | ||||
|                 d = p1 / 1000000; | ||||
|                 p1 %= 1000000; | ||||
|                 break; | ||||
|             case 6: | ||||
|                 d = p1 / 100000; | ||||
|                 p1 %= 100000; | ||||
|                 break; | ||||
|             case 5: | ||||
|                 d = p1 / 10000; | ||||
|                 p1 %= 10000; | ||||
|                 break; | ||||
|             case 4: | ||||
|                 d = p1 / 1000; | ||||
|                 p1 %= 1000; | ||||
|                 break; | ||||
|             case 3: | ||||
|                 d = p1 / 100; | ||||
|                 p1 %= 100; | ||||
|                 break; | ||||
|             case 2: | ||||
|                 d = p1 / 10; | ||||
|                 p1 %= 10; | ||||
|                 break; | ||||
|             case 1: | ||||
|                 d = p1; | ||||
|                 p1 = 0; | ||||
|                 break; | ||||
|     while (kappa > 0) { | ||||
|         uint32_t d = 0; | ||||
|         switch (kappa) { | ||||
|             case  9: d = p1 /  100000000; p1 %=  100000000; break; | ||||
|             case  8: d = p1 /   10000000; p1 %=   10000000; break; | ||||
|             case  7: d = p1 /    1000000; p1 %=    1000000; break; | ||||
|             case  6: d = p1 /     100000; p1 %=     100000; break; | ||||
|             case  5: d = p1 /      10000; p1 %=      10000; break; | ||||
|             case  4: d = p1 /       1000; p1 %=       1000; break; | ||||
|             case  3: d = p1 /        100; p1 %=        100; break; | ||||
|             case  2: d = p1 /         10; p1 %=         10; break; | ||||
|             case  1: d = p1;              p1 =           0; break; | ||||
|             default:; | ||||
|             } | ||||
|             if (d || *len) | ||||
|                 buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d)); | ||||
|             kappa--; | ||||
|             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); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // kappa = 0 | ||||
|         for (;;) { | ||||
|             p2 *= 10; | ||||
|             delta *= 10; | ||||
|             char d = static_cast<char>(p2 >> -one.e); | ||||
|             if (d || *len) | ||||
|                 buffer[(*len)++] = static_cast<char>('0' + d); | ||||
|             p2 &= one.f - 1; | ||||
|             kappa--; | ||||
|             if (p2 < delta) { | ||||
|                 *K += kappa; | ||||
|                 int index = -kappa; | ||||
|                 GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); | ||||
|                 return; | ||||
|             } | ||||
|         if (d || *len) | ||||
|             buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d)); | ||||
|         kappa--; | ||||
|         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); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     inline void Grisu2(double value, char* buffer, int* length, int* K) { | ||||
|         const DiyFp v(value); | ||||
|         DiyFp w_m, w_p; | ||||
|         v.NormalizedBoundaries(&w_m, &w_p); | ||||
|     // kappa = 0 | ||||
|     for (;;) { | ||||
|         p2 *= 10; | ||||
|         delta *= 10; | ||||
|         char d = static_cast<char>(p2 >> -one.e); | ||||
|         if (d || *len) | ||||
|             buffer[(*len)++] = static_cast<char>('0' + d); | ||||
|         p2 &= one.f - 1; | ||||
|         kappa--; | ||||
|         if (p2 < delta) { | ||||
|             *K += kappa; | ||||
|             int index = -kappa; | ||||
|             GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|         const DiyFp c_mk = GetCachedPower(w_p.e, K); | ||||
|         const DiyFp W = v.Normalize() * c_mk; | ||||
|         DiyFp Wp = w_p * c_mk; | ||||
|         DiyFp Wm = w_m * c_mk; | ||||
|         Wm.f++; | ||||
|         Wp.f--; | ||||
|         DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); | ||||
| inline void Grisu2(double value, char* buffer, int* length, int* K) { | ||||
|     const DiyFp v(value); | ||||
|     DiyFp w_m, w_p; | ||||
|     v.NormalizedBoundaries(&w_m, &w_p); | ||||
|  | ||||
|     const DiyFp c_mk = GetCachedPower(w_p.e, K); | ||||
|     const DiyFp W = v.Normalize() * c_mk; | ||||
|     DiyFp Wp = w_p * c_mk; | ||||
|     DiyFp Wm = w_m * c_mk; | ||||
|     Wm.f++; | ||||
|     Wp.f--; | ||||
|     DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); | ||||
| } | ||||
|  | ||||
| inline char* WriteExponent(int K, char* buffer) { | ||||
|     if (K < 0) { | ||||
|         *buffer++ = '-'; | ||||
|         K = -K; | ||||
|     } | ||||
|  | ||||
|     inline char* WriteExponent(int K, char* buffer) { | ||||
|         if (K < 0) { | ||||
|             *buffer++ = '-'; | ||||
|             K = -K; | ||||
|         } | ||||
|     if (K >= 100) { | ||||
|         *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100)); | ||||
|         K %= 100; | ||||
|         const char* d = GetDigitsLut() + K * 2; | ||||
|         *buffer++ = d[0]; | ||||
|         *buffer++ = d[1]; | ||||
|     } | ||||
|     else if (K >= 10) { | ||||
|         const char* d = GetDigitsLut() + K * 2; | ||||
|         *buffer++ = d[0]; | ||||
|         *buffer++ = d[1]; | ||||
|     } | ||||
|     else | ||||
|         *buffer++ = static_cast<char>('0' + static_cast<char>(K)); | ||||
|  | ||||
|         if (K >= 100) { | ||||
|             *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100)); | ||||
|             K %= 100; | ||||
|             const char* d = GetDigitsLut() + K * 2; | ||||
|             *buffer++ = d[0]; | ||||
|             *buffer++ = d[1]; | ||||
|         } | ||||
|         else if (K >= 10) { | ||||
|             const char* d = GetDigitsLut() + K * 2; | ||||
|             *buffer++ = d[0]; | ||||
|             *buffer++ = d[1]; | ||||
|     return buffer; | ||||
| } | ||||
|  | ||||
| inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { | ||||
|     const int kk = length + k;  // 10^(kk-1) <= v < 10^kk | ||||
|  | ||||
|     if (0 <= k && kk <= 21) { | ||||
|         // 1234e7 -> 12340000000 | ||||
|         for (int i = length; i < kk; i++) | ||||
|             buffer[i] = '0'; | ||||
|         buffer[kk] = '.'; | ||||
|         buffer[kk + 1] = '0'; | ||||
|         return &buffer[kk + 2]; | ||||
|     } | ||||
|     else if (0 < kk && kk <= 21) { | ||||
|         // 1234e-2 -> 12.34 | ||||
|         std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk)); | ||||
|         buffer[kk] = '.'; | ||||
|         if (0 > k + maxDecimalPlaces) { | ||||
|             // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 | ||||
|             // Remove extra trailing zeros (at least one) after truncation. | ||||
|             for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) | ||||
|                 if (buffer[i] != '0') | ||||
|                     return &buffer[i + 1]; | ||||
|             return &buffer[kk + 2]; // Reserve one zero | ||||
|         } | ||||
|         else | ||||
|             *buffer++ = static_cast<char>('0' + static_cast<char>(K)); | ||||
|  | ||||
|         return buffer; | ||||
|             return &buffer[length + 1]; | ||||
|     } | ||||
|  | ||||
|     inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { | ||||
|         const int kk = length + k; // 10^(kk-1) <= v < 10^kk | ||||
|  | ||||
|         if (0 <= k && kk <= 21) { | ||||
|             // 1234e7 -> 12340000000 | ||||
|             for (int i = length; i < kk; i++) | ||||
|                 buffer[i] = '0'; | ||||
|             buffer[kk] = '.'; | ||||
|             buffer[kk + 1] = '0'; | ||||
|             return &buffer[kk + 2]; | ||||
|         } | ||||
|         else if (0 < kk && kk <= 21) { | ||||
|             // 1234e-2 -> 12.34 | ||||
|             std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk)); | ||||
|             buffer[kk] = '.'; | ||||
|             if (0 > k + maxDecimalPlaces) { | ||||
|                 // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 | ||||
|                 // Remove extra trailing zeros (at least one) after truncation. | ||||
|                 for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) | ||||
|                     if (buffer[i] != '0') | ||||
|                         return &buffer[i + 1]; | ||||
|                 return &buffer[kk + 2]; // Reserve one zero | ||||
|             } | ||||
|             else | ||||
|                 return &buffer[length + 1]; | ||||
|         } | ||||
|         else if (-6 < kk && kk <= 0) { | ||||
|             // 1234e-6 -> 0.001234 | ||||
|             const int offset = 2 - kk; | ||||
|             std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length)); | ||||
|             buffer[0] = '0'; | ||||
|             buffer[1] = '.'; | ||||
|             for (int i = 2; i < offset; i++) | ||||
|                 buffer[i] = '0'; | ||||
|             if (length - kk > maxDecimalPlaces) { | ||||
|                 // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 | ||||
|                 // Remove extra trailing zeros (at least one) after truncation. | ||||
|                 for (int i = maxDecimalPlaces + 1; i > 2; i--) | ||||
|                     if (buffer[i] != '0') | ||||
|                         return &buffer[i + 1]; | ||||
|                 return &buffer[3]; // Reserve one zero | ||||
|             } | ||||
|             else | ||||
|                 return &buffer[length + offset]; | ||||
|         } | ||||
|         else if (kk < -maxDecimalPlaces) { | ||||
|             // Truncate to zero | ||||
|             buffer[0] = '0'; | ||||
|             buffer[1] = '.'; | ||||
|             buffer[2] = '0'; | ||||
|             return &buffer[3]; | ||||
|         } | ||||
|         else if (length == 1) { | ||||
|             // 1e30 | ||||
|             buffer[1] = 'e'; | ||||
|             return WriteExponent(kk - 1, &buffer[2]); | ||||
|         } | ||||
|         else { | ||||
|             // 1234e30 -> 1.234e33 | ||||
|             std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1)); | ||||
|             buffer[1] = '.'; | ||||
|             buffer[length + 1] = 'e'; | ||||
|             return WriteExponent(kk - 1, &buffer[0 + length + 2]); | ||||
|     else if (-6 < kk && kk <= 0) { | ||||
|         // 1234e-6 -> 0.001234 | ||||
|         const int offset = 2 - kk; | ||||
|         std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length)); | ||||
|         buffer[0] = '0'; | ||||
|         buffer[1] = '.'; | ||||
|         for (int i = 2; i < offset; i++) | ||||
|             buffer[i] = '0'; | ||||
|         if (length - kk > maxDecimalPlaces) { | ||||
|             // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 | ||||
|             // Remove extra trailing zeros (at least one) after truncation. | ||||
|             for (int i = maxDecimalPlaces + 1; i > 2; i--) | ||||
|                 if (buffer[i] != '0') | ||||
|                     return &buffer[i + 1]; | ||||
|             return &buffer[3]; // Reserve one zero | ||||
|         } | ||||
|         else | ||||
|             return &buffer[length + offset]; | ||||
|     } | ||||
|  | ||||
|     inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { | ||||
|         RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); | ||||
|         Double d(value); | ||||
|         if (d.IsZero()) { | ||||
|             if (d.Sign()) | ||||
|                 *buffer++ = '-'; // -0.0, Issue #289 | ||||
|             buffer[0] = '0'; | ||||
|             buffer[1] = '.'; | ||||
|             buffer[2] = '0'; | ||||
|             return &buffer[3]; | ||||
|         } | ||||
|         else { | ||||
|             if (value < 0) { | ||||
|                 *buffer++ = '-'; | ||||
|                 value = -value; | ||||
|             } | ||||
|             int length, K; | ||||
|             Grisu2(value, buffer, &length, &K); | ||||
|             return Prettify(buffer, length, K, maxDecimalPlaces); | ||||
|         } | ||||
|     else if (kk < -maxDecimalPlaces) { | ||||
|         // Truncate to zero | ||||
|         buffer[0] = '0'; | ||||
|         buffer[1] = '.'; | ||||
|         buffer[2] = '0'; | ||||
|         return &buffer[3]; | ||||
|     } | ||||
|     else if (length == 1) { | ||||
|         // 1e30 | ||||
|         buffer[1] = 'e'; | ||||
|         return WriteExponent(kk - 1, &buffer[2]); | ||||
|     } | ||||
|     else { | ||||
|         // 1234e30 -> 1.234e33 | ||||
|         std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1)); | ||||
|         buffer[1] = '.'; | ||||
|         buffer[length + 1] = 'e'; | ||||
|         return WriteExponent(kk - 1, &buffer[0 + length + 2]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { | ||||
|     RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); | ||||
|     Double d(value); | ||||
|     if (d.IsZero()) { | ||||
|         if (d.Sign()) | ||||
|             *buffer++ = '-';     // -0.0, Issue #289 | ||||
|         buffer[0] = '0'; | ||||
|         buffer[1] = '.'; | ||||
|         buffer[2] = '0'; | ||||
|         return &buffer[3]; | ||||
|     } | ||||
|     else { | ||||
|         if (value < 0) { | ||||
|             *buffer++ = '-'; | ||||
|             value = -value; | ||||
|         } | ||||
|         int length, K; | ||||
|         Grisu2(value, buffer, &length, &K); | ||||
|         return Prettify(buffer, length, K, maxDecimalPlaces); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
|     RAPIDJSON_DIAG_POP | ||||
| RAPIDJSON_DIAG_POP | ||||
| #endif | ||||
|  | ||||
| } // namespace internal | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_IEEE754_ | ||||
| @@ -20,57 +20,57 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     class Double { | ||||
|     public: | ||||
|         Double() {} | ||||
|         Double(double d) : d_(d) {} | ||||
|         Double(uint64_t u) : u_(u) {} | ||||
| class Double { | ||||
| public: | ||||
|     Double() {} | ||||
|     Double(double d) : d_(d) {} | ||||
|     Double(uint64_t u) : u_(u) {} | ||||
|  | ||||
|         double Value() const { return d_; } | ||||
|         uint64_t Uint64Value() const { return u_; } | ||||
|     double Value() const { return d_; } | ||||
|     uint64_t Uint64Value() const { return u_; } | ||||
|  | ||||
|         double NextPositiveDouble() const { | ||||
|             RAPIDJSON_ASSERT(!Sign()); | ||||
|             return Double(u_ + 1).Value(); | ||||
|         } | ||||
|     double NextPositiveDouble() const { | ||||
|         RAPIDJSON_ASSERT(!Sign()); | ||||
|         return Double(u_ + 1).Value(); | ||||
|     } | ||||
|  | ||||
|         bool Sign() const { return (u_ & kSignMask) != 0; } | ||||
|         uint64_t Significand() const { return u_ & kSignificandMask; } | ||||
|         int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } | ||||
|     bool Sign() const { return (u_ & kSignMask) != 0; } | ||||
|     uint64_t Significand() const { return u_ & kSignificandMask; } | ||||
|     int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } | ||||
|  | ||||
|         bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } | ||||
|         bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } | ||||
|         bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } | ||||
|         bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } | ||||
|         bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } | ||||
|     bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } | ||||
|     bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } | ||||
|     bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } | ||||
|     bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } | ||||
|     bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } | ||||
|  | ||||
|         uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } | ||||
|         int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } | ||||
|         uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } | ||||
|     uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } | ||||
|     int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } | ||||
|     uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } | ||||
|  | ||||
|         static int EffectiveSignificandSize(int order) { | ||||
|             if (order >= -1021) | ||||
|                 return 53; | ||||
|             else if (order <= -1074) | ||||
|                 return 0; | ||||
|             else | ||||
|                 return order + 1074; | ||||
|         } | ||||
|     static int EffectiveSignificandSize(int order) { | ||||
|         if (order >= -1021) | ||||
|             return 53; | ||||
|         else if (order <= -1074) | ||||
|             return 0; | ||||
|         else | ||||
|             return order + 1074; | ||||
|     } | ||||
|  | ||||
|     private: | ||||
|         static const int kSignificandSize = 52; | ||||
|         static const int kExponentBias = 0x3FF; | ||||
|         static const int kDenormalExponent = 1 - kExponentBias; | ||||
|         static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); | ||||
|         static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); | ||||
|         static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); | ||||
|         static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); | ||||
| private: | ||||
|     static const int kSignificandSize = 52; | ||||
|     static const int kExponentBias = 0x3FF; | ||||
|     static const int kDenormalExponent = 1 - kExponentBias; | ||||
|     static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); | ||||
|     static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); | ||||
|     static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); | ||||
|     static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); | ||||
|  | ||||
|         union { | ||||
|             double d_; | ||||
|             uint64_t u_; | ||||
|         }; | ||||
|     union { | ||||
|         double d_; | ||||
|         uint64_t u_; | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -20,43 +20,140 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     inline const char* GetDigitsLut() { | ||||
|         static const char cDigitsLut[200] = { | ||||
|             '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', | ||||
|             '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', | ||||
|             '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', | ||||
|             '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', | ||||
|             '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', | ||||
|             '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', | ||||
|             '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', | ||||
|             '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', | ||||
|             '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', | ||||
|             '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' | ||||
|         }; | ||||
|         return cDigitsLut; | ||||
| inline const char* GetDigitsLut() { | ||||
|     static const char cDigitsLut[200] = { | ||||
|         '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', | ||||
|         '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', | ||||
|         '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', | ||||
|         '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', | ||||
|         '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', | ||||
|         '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', | ||||
|         '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', | ||||
|         '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', | ||||
|         '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', | ||||
|         '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' | ||||
|     }; | ||||
|     return cDigitsLut; | ||||
| } | ||||
|  | ||||
| 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) | ||||
|             *buffer++ = cDigitsLut[d1 + 1]; | ||||
|         if (value >= 10) | ||||
|             *buffer++ = cDigitsLut[d2]; | ||||
|         *buffer++ = cDigitsLut[d2 + 1]; | ||||
|     } | ||||
|     else if (value < 100000000) { | ||||
|         // 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) | ||||
|             *buffer++ = cDigitsLut[d1 + 1]; | ||||
|         if (value >= 100000) | ||||
|             *buffer++ = cDigitsLut[d2]; | ||||
|         *buffer++ = cDigitsLut[d2 + 1]; | ||||
|  | ||||
|         *buffer++ = cDigitsLut[d3]; | ||||
|         *buffer++ = cDigitsLut[d3 + 1]; | ||||
|         *buffer++ = cDigitsLut[d4]; | ||||
|         *buffer++ = cDigitsLut[d4 + 1]; | ||||
|     } | ||||
|     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]; | ||||
|             *buffer++ = cDigitsLut[i + 1]; | ||||
|         } | ||||
|         else | ||||
|             *buffer++ = static_cast<char>('0' + static_cast<char>(a)); | ||||
|  | ||||
|         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]; | ||||
|         *buffer++ = cDigitsLut[d2 + 1]; | ||||
|         *buffer++ = cDigitsLut[d3]; | ||||
|         *buffer++ = cDigitsLut[d3 + 1]; | ||||
|         *buffer++ = cDigitsLut[d4]; | ||||
|         *buffer++ = cDigitsLut[d4 + 1]; | ||||
|     } | ||||
|     return 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++ = '-'; | ||||
|         u = ~u + 1; | ||||
|     } | ||||
|  | ||||
|     inline char* u32toa(uint32_t value, char* buffer) { | ||||
|         RAPIDJSON_ASSERT(buffer != 0); | ||||
|     return u32toa(u, buffer); | ||||
| } | ||||
|  | ||||
|         const char* cDigitsLut = GetDigitsLut(); | ||||
| 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; | ||||
|     const uint64_t kTen10 = kTen8 * 100; | ||||
|     const uint64_t kTen11 = kTen8 * 1000; | ||||
|     const uint64_t kTen12 = kTen8 * 10000; | ||||
|     const uint64_t kTen13 = kTen8 * 100000; | ||||
|     const uint64_t kTen14 = kTen8 * 1000000; | ||||
|     const uint64_t kTen15 = kTen8 * 10000000; | ||||
|     const uint64_t kTen16 = kTen8 * kTen8; | ||||
|  | ||||
|         if (value < 10000) { | ||||
|             const uint32_t d1 = (value / 100) << 1; | ||||
|             const uint32_t d2 = (value % 100) << 1; | ||||
|     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 (value >= 1000) | ||||
|             if (v >= 1000) | ||||
|                 *buffer++ = cDigitsLut[d1]; | ||||
|             if (value >= 100) | ||||
|             if (v >= 100) | ||||
|                 *buffer++ = cDigitsLut[d1 + 1]; | ||||
|             if (value >= 10) | ||||
|             if (v >= 10) | ||||
|                 *buffer++ = cDigitsLut[d2]; | ||||
|             *buffer++ = cDigitsLut[d2 + 1]; | ||||
|         } | ||||
|         else if (value < 100000000) { | ||||
|         else { | ||||
|             // value = bbbbcccc | ||||
|             const uint32_t b = value / 10000; | ||||
|             const uint32_t c = value % 10000; | ||||
|             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; | ||||
| @@ -77,231 +174,134 @@ namespace internal { | ||||
|             *buffer++ = cDigitsLut[d4]; | ||||
|             *buffer++ = cDigitsLut[d4 + 1]; | ||||
|         } | ||||
|         else { | ||||
|             // value = aabbbbcccc in decimal | ||||
|     } | ||||
|     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 a = value / 100000000; // 1 to 42 | ||||
|             value %= 100000000; | ||||
|         const uint32_t b0 = v0 / 10000; | ||||
|         const uint32_t c0 = v0 % 10000; | ||||
|  | ||||
|             if (a >= 10) { | ||||
|                 const unsigned i = a << 1; | ||||
|                 *buffer++ = cDigitsLut[i]; | ||||
|                 *buffer++ = cDigitsLut[i + 1]; | ||||
|             } | ||||
|             else | ||||
|                 *buffer++ = static_cast<char>('0' + static_cast<char>(a)); | ||||
|         const uint32_t d1 = (b0 / 100) << 1; | ||||
|         const uint32_t d2 = (b0 % 100) << 1; | ||||
|  | ||||
|             const uint32_t b = value / 10000; // 0 to 9999 | ||||
|             const uint32_t c = value % 10000; // 0 to 9999 | ||||
|         const uint32_t d3 = (c0 / 100) << 1; | ||||
|         const uint32_t d4 = (c0 % 100) << 1; | ||||
|  | ||||
|             const uint32_t d1 = (b / 100) << 1; | ||||
|             const uint32_t d2 = (b % 100) << 1; | ||||
|         const uint32_t b1 = v1 / 10000; | ||||
|         const uint32_t c1 = v1 % 10000; | ||||
|  | ||||
|             const uint32_t d3 = (c / 100) << 1; | ||||
|             const uint32_t d4 = (c % 100) << 1; | ||||
|         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; | ||||
|  | ||||
|         if (value >= kTen15) | ||||
|             *buffer++ = cDigitsLut[d1]; | ||||
|         if (value >= kTen14) | ||||
|             *buffer++ = cDigitsLut[d1 + 1]; | ||||
|         if (value >= kTen13) | ||||
|             *buffer++ = cDigitsLut[d2]; | ||||
|         if (value >= kTen12) | ||||
|             *buffer++ = cDigitsLut[d2 + 1]; | ||||
|         if (value >= kTen11) | ||||
|             *buffer++ = cDigitsLut[d3]; | ||||
|         if (value >= kTen10) | ||||
|             *buffer++ = cDigitsLut[d3 + 1]; | ||||
|         if (value >= kTen9) | ||||
|             *buffer++ = cDigitsLut[d4]; | ||||
|             *buffer++ = cDigitsLut[d4 + 1]; | ||||
|         } | ||||
|         return buffer; | ||||
|  | ||||
|         *buffer++ = cDigitsLut[d4 + 1]; | ||||
|         *buffer++ = cDigitsLut[d5]; | ||||
|         *buffer++ = cDigitsLut[d5 + 1]; | ||||
|         *buffer++ = cDigitsLut[d6]; | ||||
|         *buffer++ = cDigitsLut[d6 + 1]; | ||||
|         *buffer++ = cDigitsLut[d7]; | ||||
|         *buffer++ = cDigitsLut[d7 + 1]; | ||||
|         *buffer++ = cDigitsLut[d8]; | ||||
|         *buffer++ = cDigitsLut[d8 + 1]; | ||||
|     } | ||||
|     else { | ||||
|         const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844 | ||||
|         value %= kTen16; | ||||
|  | ||||
|     inline char* i32toa(int32_t value, char* buffer) { | ||||
|         RAPIDJSON_ASSERT(buffer != 0); | ||||
|         uint32_t u = static_cast<uint32_t>(value); | ||||
|         if (value < 0) { | ||||
|             *buffer++ = '-'; | ||||
|             u = ~u + 1; | ||||
|         if (a < 10) | ||||
|             *buffer++ = static_cast<char>('0' + static_cast<char>(a)); | ||||
|         else if (a < 100) { | ||||
|             const uint32_t i = a << 1; | ||||
|             *buffer++ = cDigitsLut[i]; | ||||
|             *buffer++ = cDigitsLut[i + 1]; | ||||
|         } | ||||
|         else if (a < 1000) { | ||||
|             *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100)); | ||||
|  | ||||
|         return u32toa(u, 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; | ||||
|         const uint64_t kTen10 = kTen8 * 100; | ||||
|         const uint64_t kTen11 = kTen8 * 1000; | ||||
|         const uint64_t kTen12 = kTen8 * 10000; | ||||
|         const uint64_t kTen13 = kTen8 * 100000; | ||||
|         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) | ||||
|                     *buffer++ = cDigitsLut[d1 + 1]; | ||||
|                 if (v >= 10) | ||||
|                     *buffer++ = cDigitsLut[d2]; | ||||
|                 *buffer++ = cDigitsLut[d2 + 1]; | ||||
|             } | ||||
|             else { | ||||
|                 // 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) | ||||
|                     *buffer++ = cDigitsLut[d1 + 1]; | ||||
|                 if (value >= 100000) | ||||
|                     *buffer++ = cDigitsLut[d2]; | ||||
|                 *buffer++ = cDigitsLut[d2 + 1]; | ||||
|  | ||||
|                 *buffer++ = cDigitsLut[d3]; | ||||
|                 *buffer++ = cDigitsLut[d3 + 1]; | ||||
|                 *buffer++ = cDigitsLut[d4]; | ||||
|                 *buffer++ = cDigitsLut[d4 + 1]; | ||||
|             } | ||||
|         } | ||||
|         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; | ||||
|  | ||||
|             if (value >= kTen15) | ||||
|                 *buffer++ = cDigitsLut[d1]; | ||||
|             if (value >= kTen14) | ||||
|                 *buffer++ = cDigitsLut[d1 + 1]; | ||||
|             if (value >= kTen13) | ||||
|                 *buffer++ = cDigitsLut[d2]; | ||||
|             if (value >= kTen12) | ||||
|                 *buffer++ = cDigitsLut[d2 + 1]; | ||||
|             if (value >= kTen11) | ||||
|                 *buffer++ = cDigitsLut[d3]; | ||||
|             if (value >= kTen10) | ||||
|                 *buffer++ = cDigitsLut[d3 + 1]; | ||||
|             if (value >= kTen9) | ||||
|                 *buffer++ = cDigitsLut[d4]; | ||||
|  | ||||
|             *buffer++ = cDigitsLut[d4 + 1]; | ||||
|             *buffer++ = cDigitsLut[d5]; | ||||
|             *buffer++ = cDigitsLut[d5 + 1]; | ||||
|             *buffer++ = cDigitsLut[d6]; | ||||
|             *buffer++ = cDigitsLut[d6 + 1]; | ||||
|             *buffer++ = cDigitsLut[d7]; | ||||
|             *buffer++ = cDigitsLut[d7 + 1]; | ||||
|             *buffer++ = cDigitsLut[d8]; | ||||
|             *buffer++ = cDigitsLut[d8 + 1]; | ||||
|             const uint32_t i = (a % 100) << 1; | ||||
|             *buffer++ = cDigitsLut[i]; | ||||
|             *buffer++ = cDigitsLut[i + 1]; | ||||
|         } | ||||
|         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) { | ||||
|                 const uint32_t i = a << 1; | ||||
|                 *buffer++ = cDigitsLut[i]; | ||||
|                 *buffer++ = cDigitsLut[i + 1]; | ||||
|             } | ||||
|             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]; | ||||
|             } | ||||
|             else { | ||||
|                 const uint32_t i = (a / 100) << 1; | ||||
|                 const uint32_t j = (a % 100) << 1; | ||||
|                 *buffer++ = cDigitsLut[i]; | ||||
|                 *buffer++ = cDigitsLut[i + 1]; | ||||
|                 *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]; | ||||
|             *buffer++ = cDigitsLut[d2 + 1]; | ||||
|             *buffer++ = cDigitsLut[d3]; | ||||
|             *buffer++ = cDigitsLut[d3 + 1]; | ||||
|             *buffer++ = cDigitsLut[d4]; | ||||
|             *buffer++ = cDigitsLut[d4 + 1]; | ||||
|             *buffer++ = cDigitsLut[d5]; | ||||
|             *buffer++ = cDigitsLut[d5 + 1]; | ||||
|             *buffer++ = cDigitsLut[d6]; | ||||
|             *buffer++ = cDigitsLut[d6 + 1]; | ||||
|             *buffer++ = cDigitsLut[d7]; | ||||
|             *buffer++ = cDigitsLut[d7 + 1]; | ||||
|             *buffer++ = cDigitsLut[d8]; | ||||
|             *buffer++ = cDigitsLut[d8 + 1]; | ||||
|             const uint32_t i = (a / 100) << 1; | ||||
|             const uint32_t j = (a % 100) << 1; | ||||
|             *buffer++ = cDigitsLut[i]; | ||||
|             *buffer++ = cDigitsLut[i + 1]; | ||||
|             *buffer++ = cDigitsLut[j]; | ||||
|             *buffer++ = cDigitsLut[j + 1]; | ||||
|         } | ||||
|  | ||||
|         return buffer; | ||||
|         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]; | ||||
|         *buffer++ = cDigitsLut[d2 + 1]; | ||||
|         *buffer++ = cDigitsLut[d3]; | ||||
|         *buffer++ = cDigitsLut[d3 + 1]; | ||||
|         *buffer++ = cDigitsLut[d4]; | ||||
|         *buffer++ = cDigitsLut[d4 + 1]; | ||||
|         *buffer++ = cDigitsLut[d5]; | ||||
|         *buffer++ = cDigitsLut[d5 + 1]; | ||||
|         *buffer++ = cDigitsLut[d6]; | ||||
|         *buffer++ = cDigitsLut[d6 + 1]; | ||||
|         *buffer++ = cDigitsLut[d7]; | ||||
|         *buffer++ = cDigitsLut[d7 + 1]; | ||||
|         *buffer++ = cDigitsLut[d8]; | ||||
|         *buffer++ = cDigitsLut[d8 + 1]; | ||||
|     } | ||||
|  | ||||
|     inline char* i64toa(int64_t value, char* buffer) { | ||||
|         RAPIDJSON_ASSERT(buffer != 0); | ||||
|         uint64_t u = static_cast<uint64_t>(value); | ||||
|         if (value < 0) { | ||||
|             *buffer++ = '-'; | ||||
|             u = ~u + 1; | ||||
|         } | ||||
|     return buffer; | ||||
| } | ||||
|  | ||||
|         return u64toa(u, 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++ = '-'; | ||||
|         u = ~u + 1; | ||||
|     } | ||||
|  | ||||
|     return u64toa(u, buffer); | ||||
| } | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_INTERNAL_META_H_ | ||||
| @@ -35,177 +35,141 @@ RAPIDJSON_DIAG_OFF(6334) | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching | ||||
|     template <typename T> | ||||
|     struct Void { typedef void Type; }; | ||||
| // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching | ||||
| template <typename T> struct Void { typedef void Type; }; | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     // BoolType, TrueType, FalseType | ||||
|     // | ||||
|     template <bool Cond> | ||||
|     struct BoolType { | ||||
|         static const bool Value = Cond; | ||||
|         typedef BoolType Type; | ||||
|     }; | ||||
|     typedef BoolType<true> TrueType; | ||||
|     typedef BoolType<false> FalseType; | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // BoolType, TrueType, FalseType | ||||
| // | ||||
| template <bool Cond> struct BoolType { | ||||
|     static const bool Value = Cond; | ||||
|     typedef BoolType Type; | ||||
| }; | ||||
| typedef BoolType<true> TrueType; | ||||
| typedef BoolType<false> FalseType; | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr | ||||
|     // | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr | ||||
| // | ||||
|  | ||||
|     template <bool C> | ||||
|     struct SelectIfImpl { | ||||
|         template <typename T1, typename T2> | ||||
|         struct Apply { typedef T1 Type; }; | ||||
|     }; | ||||
|     template <> | ||||
|     struct SelectIfImpl<false> { | ||||
|         template <typename T1, typename T2> | ||||
|         struct Apply { typedef T2 Type; }; | ||||
|     }; | ||||
|     template <bool C, typename T1, typename T2> | ||||
|     struct SelectIfCond : SelectIfImpl<C>::template Apply<T1, T2> {}; | ||||
|     template <typename C, typename T1, typename T2> | ||||
|     struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; | ||||
| template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; | ||||
| template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; | ||||
| template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; | ||||
| template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; | ||||
|  | ||||
|     template <bool Cond1, bool Cond2> | ||||
|     struct AndExprCond : FalseType {}; | ||||
|     template <> | ||||
|     struct AndExprCond<true, true> : TrueType {}; | ||||
|     template <bool Cond1, bool Cond2> | ||||
|     struct OrExprCond : TrueType {}; | ||||
|     template <> | ||||
|     struct OrExprCond<false, false> : FalseType {}; | ||||
| template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; | ||||
| template <> struct AndExprCond<true, true> : TrueType {}; | ||||
| template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; | ||||
| template <> struct OrExprCond<false, false> : FalseType {}; | ||||
|  | ||||
|     template <typename C> | ||||
|     struct BoolExpr : SelectIf<C, TrueType, FalseType>::Type {}; | ||||
|     template <typename C> | ||||
|     struct NotExpr : SelectIf<C, FalseType, TrueType>::Type {}; | ||||
|     template <typename C1, typename C2> | ||||
|     struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; | ||||
|     template <typename C1, typename C2> | ||||
|     struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; | ||||
| template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; | ||||
| template <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {}; | ||||
| template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; | ||||
| template <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {}; | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     // AddConst, MaybeAddConst, RemoveConst | ||||
|     template <typename T> | ||||
|     struct AddConst { typedef const T Type; }; | ||||
|     template <bool Constify, typename T> | ||||
|     struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; | ||||
|     template <typename T> | ||||
|     struct RemoveConst { typedef T Type; }; | ||||
|     template <typename T> | ||||
|     struct RemoveConst<const T> { typedef T Type; }; | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // AddConst, MaybeAddConst, RemoveConst | ||||
| template <typename T> struct AddConst { typedef const T Type; }; | ||||
| template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; | ||||
| template <typename T> struct RemoveConst { typedef T Type; }; | ||||
| template <typename T> struct RemoveConst<const T> { typedef T Type; }; | ||||
|  | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     // IsSame, IsConst, IsMoreConst, IsPointer | ||||
|     // | ||||
|     template <typename T, typename U> | ||||
|     struct IsSame : FalseType {}; | ||||
|     template <typename T> | ||||
|     struct IsSame<T, T> : TrueType {}; | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // IsSame, IsConst, IsMoreConst, IsPointer | ||||
| // | ||||
| template <typename T, typename U> struct IsSame : FalseType {}; | ||||
| template <typename T> struct IsSame<T, T> : TrueType {}; | ||||
|  | ||||
|     template <typename T> | ||||
|     struct IsConst : FalseType {}; | ||||
|     template <typename T> | ||||
|     struct IsConst<const T> : TrueType {}; | ||||
| template <typename T> struct IsConst : FalseType {}; | ||||
| template <typename T> struct IsConst<const T> : TrueType {}; | ||||
|  | ||||
|     template <typename CT, typename T> | ||||
|     struct IsMoreConst | ||||
|         : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, | ||||
|                   BoolType<IsConst<CT>::Value >= IsConst<T>::Value>>::Type {}; | ||||
| template <typename CT, typename T> | ||||
| struct IsMoreConst | ||||
|     : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, | ||||
|               BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; | ||||
|  | ||||
|     template <typename T> | ||||
|     struct IsPointer : FalseType {}; | ||||
|     template <typename T> | ||||
|     struct IsPointer<T*> : TrueType {}; | ||||
| template <typename T> struct IsPointer : FalseType {}; | ||||
| template <typename T> struct IsPointer<T*> : TrueType {}; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // IsBaseOf | ||||
| // | ||||
| #if RAPIDJSON_HAS_CXX11_TYPETRAITS | ||||
|  | ||||
|     template <typename B, typename D> | ||||
|     struct IsBaseOf | ||||
|         : BoolType<::std::is_base_of<B, D>::value> {}; | ||||
| template <typename B, typename D> struct IsBaseOf | ||||
|     : BoolType< ::std::is_base_of<B,D>::value> {}; | ||||
|  | ||||
| #else // simplified version adopted from Boost | ||||
|  | ||||
|     template <typename B, typename D> | ||||
|     struct IsBaseOfImpl { | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); | ||||
|         RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); | ||||
| template<typename B, typename D> struct IsBaseOfImpl { | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); | ||||
|     RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); | ||||
|  | ||||
|         typedef char (&Yes)[1]; | ||||
|         typedef char (&No)[2]; | ||||
|     typedef char (&Yes)[1]; | ||||
|     typedef char (&No) [2]; | ||||
|  | ||||
|         template <typename T> | ||||
|         static Yes Check(const D*, T); | ||||
|         static No Check(const B*, int); | ||||
|     template <typename T> | ||||
|     static Yes Check(const D*, T); | ||||
|     static No  Check(const B*, int); | ||||
|  | ||||
|         struct Host { | ||||
|             operator const B*() const; | ||||
|             operator const D*(); | ||||
|         }; | ||||
|  | ||||
|         enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; | ||||
|     struct Host { | ||||
|         operator const B*() const; | ||||
|         operator const D*(); | ||||
|     }; | ||||
|  | ||||
|     template <typename B, typename D> | ||||
|     struct IsBaseOf | ||||
|         : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D>>>::Type {}; | ||||
|     enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; | ||||
| }; | ||||
|  | ||||
| template <typename B, typename D> struct IsBaseOf | ||||
|     : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; | ||||
|  | ||||
| #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS | ||||
|  | ||||
|  | ||||
|     ////////////////////////////////////////////////////////////////////////// | ||||
|     // EnableIf / DisableIf | ||||
|     // | ||||
|     template <bool Condition, typename T = void> | ||||
|     struct EnableIfCond { typedef T Type; }; | ||||
|     template <typename T> | ||||
|     struct EnableIfCond<false, T> { /* empty */ | ||||
|     }; | ||||
| ////////////////////////////////////////////////////////////////////////// | ||||
| // EnableIf / DisableIf | ||||
| // | ||||
| template <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; }; | ||||
| template <typename T> struct EnableIfCond<false, T> { /* empty */ }; | ||||
|  | ||||
|     template <bool Condition, typename T = void> | ||||
|     struct DisableIfCond { typedef T Type; }; | ||||
|     template <typename T> | ||||
|     struct DisableIfCond<true, T> { /* empty */ | ||||
|     }; | ||||
| template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; | ||||
| template <typename T> struct DisableIfCond<true, T> { /* empty */ }; | ||||
|  | ||||
|     template <typename Condition, typename T = void> | ||||
|     struct EnableIf : EnableIfCond<Condition::Value, T> {}; | ||||
| template <typename Condition, typename T = void> | ||||
| struct EnableIf : EnableIfCond<Condition::Value, T> {}; | ||||
|  | ||||
|     template <typename Condition, typename T = void> | ||||
|     struct DisableIf : DisableIfCond<Condition::Value, T> {}; | ||||
| template <typename Condition, typename T = void> | ||||
| struct DisableIf : DisableIfCond<Condition::Value, T> {}; | ||||
|  | ||||
|     // SFINAE helpers | ||||
|     struct SfinaeTag {}; | ||||
|     template <typename T> | ||||
|     struct RemoveSfinaeTag; | ||||
|     template <typename T> | ||||
|     struct RemoveSfinaeTag<SfinaeTag& (*)(T)> { typedef T Type; }; | ||||
| // SFINAE helpers | ||||
| struct SfinaeTag {}; | ||||
| template <typename T> struct RemoveSfinaeTag; | ||||
| template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; | ||||
|  | ||||
| #define RAPIDJSON_REMOVEFPTR_(type) \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag<::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*)type>::Type | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ | ||||
|         < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type | ||||
|  | ||||
| #define RAPIDJSON_ENABLEIF(cond) \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ | ||||
|         <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL | ||||
|  | ||||
| #define RAPIDJSON_DISABLEIF(cond) \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ | ||||
|         <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL | ||||
|  | ||||
| #define RAPIDJSON_ENABLEIF_RETURN(cond, returntype)                                 \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond), \ | ||||
|                                                        RAPIDJSON_REMOVEFPTR_(returntype)>::Type | ||||
| #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ | ||||
|         <RAPIDJSON_REMOVEFPTR_(cond), \ | ||||
|          RAPIDJSON_REMOVEFPTR_(returntype)>::Type | ||||
|  | ||||
| #define RAPIDJSON_DISABLEIF_RETURN(cond, returntype)                                 \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond), \ | ||||
|                                                         RAPIDJSON_REMOVEFPTR_(returntype)>::Type | ||||
| #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ | ||||
|     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ | ||||
|         <RAPIDJSON_REMOVEFPTR_(cond), \ | ||||
|          RAPIDJSON_REMOVEFPTR_(returntype)>::Type | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_POW10_ | ||||
| @@ -20,34 +20,34 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     //! Computes integer powers of 10 in double (10.0^n). | ||||
|     /*! This function uses lookup table for fast and accurate results. | ||||
| //! Computes integer powers of 10 in double (10.0^n). | ||||
| /*! This function uses lookup table for fast and accurate results. | ||||
|     \param n non-negative exponent. Must <= 308. | ||||
|     \return 10.0^n | ||||
| */ | ||||
|     inline double Pow10(int n) { | ||||
|         static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes | ||||
|                                     1e+0, | ||||
|                                     1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, | ||||
|                                     1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, | ||||
|                                     1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, | ||||
|                                     1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, | ||||
|                                     1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, | ||||
|                                     1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119, 1e+120, | ||||
|                                     1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, | ||||
|                                     1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, | ||||
|                                     1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179, 1e+180, | ||||
|                                     1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199, 1e+200, | ||||
|                                     1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219, 1e+220, | ||||
|                                     1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, | ||||
|                                     1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260, | ||||
|                                     1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269, 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279, 1e+280, | ||||
|                                     1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299, 1e+300, | ||||
|                                     1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 | ||||
|         }; | ||||
|         RAPIDJSON_ASSERT(n >= 0 && n <= 308); | ||||
|         return e[n]; | ||||
|     } | ||||
| inline double Pow10(int n) { | ||||
|     static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes | ||||
|         1e+0,   | ||||
|         1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,  | ||||
|         1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, | ||||
|         1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, | ||||
|         1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, | ||||
|         1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, | ||||
|         1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, | ||||
|         1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, | ||||
|         1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, | ||||
|         1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, | ||||
|         1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, | ||||
|         1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, | ||||
|         1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, | ||||
|         1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, | ||||
|         1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, | ||||
|         1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, | ||||
|         1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 | ||||
|     }; | ||||
|     RAPIDJSON_ASSERT(n >= 0 && n <= 308); | ||||
|     return e[n]; | ||||
| } | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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. | ||||
| // | ||||
| // 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_INTERNAL_STACK_H_ | ||||
| @@ -21,34 +21,61 @@ | ||||
|  | ||||
| #if defined(__clang__) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(c++ 98 - compat) | ||||
| RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////////// | ||||
|     // Stack | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // Stack | ||||
|  | ||||
|     //! A type-unsafe stack for storing different types of data. | ||||
|     /*! \tparam Allocator Allocator for allocating stack memory. | ||||
| //! A type-unsafe stack for storing different types of data. | ||||
| /*! \tparam Allocator Allocator for allocating stack memory. | ||||
| */ | ||||
|     template <typename Allocator> | ||||
|     class Stack { | ||||
|     public: | ||||
|         // Optimization note: Do not allocate memory for stack_ in constructor. | ||||
|         // Do it lazily when first Push() -> Expand() -> Resize(). | ||||
|         Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { | ||||
|         } | ||||
| template <typename Allocator> | ||||
| class Stack { | ||||
| public: | ||||
|     // Optimization note: Do not allocate memory for stack_ in constructor. | ||||
|     // Do it lazily when first Push() -> Expand() -> Resize(). | ||||
|     Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { | ||||
|     } | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|         Stack(Stack&& rhs) | ||||
|             : allocator_(rhs.allocator_), | ||||
|               ownAllocator_(rhs.ownAllocator_), | ||||
|               stack_(rhs.stack_), | ||||
|               stackTop_(rhs.stackTop_), | ||||
|               stackEnd_(rhs.stackEnd_), | ||||
|               initialCapacity_(rhs.initialCapacity_) { | ||||
|     Stack(Stack&& rhs) | ||||
|         : allocator_(rhs.allocator_), | ||||
|           ownAllocator_(rhs.ownAllocator_), | ||||
|           stack_(rhs.stack_), | ||||
|           stackTop_(rhs.stackTop_), | ||||
|           stackEnd_(rhs.stackEnd_), | ||||
|           initialCapacity_(rhs.initialCapacity_) | ||||
|     { | ||||
|         rhs.allocator_ = 0; | ||||
|         rhs.ownAllocator_ = 0; | ||||
|         rhs.stack_ = 0; | ||||
|         rhs.stackTop_ = 0; | ||||
|         rhs.stackEnd_ = 0; | ||||
|         rhs.initialCapacity_ = 0; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     ~Stack() { | ||||
|         Destroy(); | ||||
|     } | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|     Stack& operator=(Stack&& rhs) { | ||||
|         if (&rhs != this) | ||||
|         { | ||||
|             Destroy(); | ||||
|  | ||||
|             allocator_ = rhs.allocator_; | ||||
|             ownAllocator_ = rhs.ownAllocator_; | ||||
|             stack_ = rhs.stack_; | ||||
|             stackTop_ = rhs.stackTop_; | ||||
|             stackEnd_ = rhs.stackEnd_; | ||||
|             initialCapacity_ = rhs.initialCapacity_; | ||||
|  | ||||
|             rhs.allocator_ = 0; | ||||
|             rhs.ownAllocator_ = 0; | ||||
|             rhs.stack_ = 0; | ||||
| @@ -56,170 +83,144 @@ namespace internal { | ||||
|             rhs.stackEnd_ = 0; | ||||
|             rhs.initialCapacity_ = 0; | ||||
|         } | ||||
|         return *this; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|         ~Stack() { | ||||
|             Destroy(); | ||||
|     void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { | ||||
|         internal::Swap(allocator_, rhs.allocator_); | ||||
|         internal::Swap(ownAllocator_, rhs.ownAllocator_); | ||||
|         internal::Swap(stack_, rhs.stack_); | ||||
|         internal::Swap(stackTop_, rhs.stackTop_); | ||||
|         internal::Swap(stackEnd_, rhs.stackEnd_); | ||||
|         internal::Swap(initialCapacity_, rhs.initialCapacity_); | ||||
|     } | ||||
|  | ||||
|     void Clear() { stackTop_ = stack_; } | ||||
|  | ||||
|     void ShrinkToFit() {  | ||||
|         if (Empty()) { | ||||
|             // If the stack is empty, completely deallocate the memory. | ||||
|             Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) | ||||
|             stack_ = 0; | ||||
|             stackTop_ = 0; | ||||
|             stackEnd_ = 0; | ||||
|         } | ||||
|         else | ||||
|             Resize(GetSize()); | ||||
|     } | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|         Stack& operator=(Stack&& rhs) { | ||||
|             if (&rhs != this) { | ||||
|                 Destroy(); | ||||
|     // Optimization note: try to minimize the size of this function for force inline. | ||||
|     // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. | ||||
|     template<typename T> | ||||
|     RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { | ||||
|          // Expand the stack if needed | ||||
|         if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_))) | ||||
|             Expand<T>(count); | ||||
|     } | ||||
|  | ||||
|                 allocator_ = rhs.allocator_; | ||||
|                 ownAllocator_ = rhs.ownAllocator_; | ||||
|                 stack_ = rhs.stack_; | ||||
|                 stackTop_ = rhs.stackTop_; | ||||
|                 stackEnd_ = rhs.stackEnd_; | ||||
|                 initialCapacity_ = rhs.initialCapacity_; | ||||
|     template<typename T> | ||||
|     RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { | ||||
|         Reserve<T>(count); | ||||
|         return PushUnsafe<T>(count); | ||||
|     } | ||||
|  | ||||
|                 rhs.allocator_ = 0; | ||||
|                 rhs.ownAllocator_ = 0; | ||||
|                 rhs.stack_ = 0; | ||||
|                 rhs.stackTop_ = 0; | ||||
|                 rhs.stackEnd_ = 0; | ||||
|                 rhs.initialCapacity_ = 0; | ||||
|             } | ||||
|             return *this; | ||||
|     template<typename T> | ||||
|     RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     T* Pop(size_t count) { | ||||
|         RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); | ||||
|         stackTop_ -= count * sizeof(T); | ||||
|         return reinterpret_cast<T*>(stackTop_); | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     T* Top() {  | ||||
|         RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | ||||
|         return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     const T* Top() const { | ||||
|         RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | ||||
|         return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     T* End() { return reinterpret_cast<T*>(stackTop_); } | ||||
|  | ||||
|     template<typename T> | ||||
|     const T* End() const { return reinterpret_cast<T*>(stackTop_); } | ||||
|  | ||||
|     template<typename T> | ||||
|     T* Bottom() { return reinterpret_cast<T*>(stack_); } | ||||
|  | ||||
|     template<typename T> | ||||
|     const T* Bottom() const { return reinterpret_cast<T*>(stack_); } | ||||
|  | ||||
|     bool HasAllocator() const { | ||||
|         return allocator_ != 0; | ||||
|     } | ||||
|  | ||||
|     Allocator& GetAllocator() { | ||||
|         RAPIDJSON_ASSERT(allocator_); | ||||
|         return *allocator_; | ||||
|     } | ||||
|  | ||||
|     bool Empty() const { return stackTop_ == stack_; } | ||||
|     size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } | ||||
|     size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } | ||||
|  | ||||
| private: | ||||
|     template<typename T> | ||||
|     void Expand(size_t count) { | ||||
|         // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. | ||||
|         size_t newCapacity; | ||||
|         if (stack_ == 0) { | ||||
|             if (!allocator_) | ||||
|                 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); | ||||
|             newCapacity = initialCapacity_; | ||||
|         } else { | ||||
|             newCapacity = GetCapacity(); | ||||
|             newCapacity += (newCapacity + 1) / 2; | ||||
|         } | ||||
| #endif | ||||
|         size_t newSize = GetSize() + sizeof(T) * count; | ||||
|         if (newCapacity < newSize) | ||||
|             newCapacity = newSize; | ||||
|  | ||||
|         void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { | ||||
|             internal::Swap(allocator_, rhs.allocator_); | ||||
|             internal::Swap(ownAllocator_, rhs.ownAllocator_); | ||||
|             internal::Swap(stack_, rhs.stack_); | ||||
|             internal::Swap(stackTop_, rhs.stackTop_); | ||||
|             internal::Swap(stackEnd_, rhs.stackEnd_); | ||||
|             internal::Swap(initialCapacity_, rhs.initialCapacity_); | ||||
|         } | ||||
|         Resize(newCapacity); | ||||
|     } | ||||
|  | ||||
|         void Clear() { stackTop_ = stack_; } | ||||
|     void Resize(size_t newCapacity) { | ||||
|         const size_t size = GetSize();  // Backup the current size | ||||
|         stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); | ||||
|         stackTop_ = stack_ + size; | ||||
|         stackEnd_ = stack_ + newCapacity; | ||||
|     } | ||||
|  | ||||
|         void ShrinkToFit() { | ||||
|             if (Empty()) { | ||||
|                 // If the stack is empty, completely deallocate the memory. | ||||
|                 Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) | ||||
|                 stack_ = 0; | ||||
|                 stackTop_ = 0; | ||||
|                 stackEnd_ = 0; | ||||
|             } | ||||
|             else | ||||
|                 Resize(GetSize()); | ||||
|         } | ||||
|     void Destroy() { | ||||
|         Allocator::Free(stack_); | ||||
|         RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack | ||||
|     } | ||||
|  | ||||
|         // Optimization note: try to minimize the size of this function for force inline. | ||||
|         // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. | ||||
|         template <typename T> | ||||
|         RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { | ||||
|             // Expand the stack if needed | ||||
|             if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_))) | ||||
|                 Expand<T>(count); | ||||
|         } | ||||
|     // Prohibit copy constructor & assignment operator. | ||||
|     Stack(const Stack&); | ||||
|     Stack& operator=(const Stack&); | ||||
|  | ||||
|         template <typename T> | ||||
|         RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { | ||||
|             Reserve<T>(count); | ||||
|             return PushUnsafe<T>(count); | ||||
|         } | ||||
|  | ||||
|         template <typename T> | ||||
|         RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { | ||||
|             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; | ||||
|         } | ||||
|  | ||||
|         template <typename T> | ||||
|         T* Pop(size_t count) { | ||||
|             RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); | ||||
|             stackTop_ -= count * sizeof(T); | ||||
|             return reinterpret_cast<T*>(stackTop_); | ||||
|         } | ||||
|  | ||||
|         template <typename T> | ||||
|         T* Top() { | ||||
|             RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | ||||
|             return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | ||||
|         } | ||||
|  | ||||
|         template <typename T> | ||||
|         const T* Top() const { | ||||
|             RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); | ||||
|             return reinterpret_cast<T*>(stackTop_ - sizeof(T)); | ||||
|         } | ||||
|  | ||||
|         template <typename T> | ||||
|         T* End() { return reinterpret_cast<T*>(stackTop_); } | ||||
|  | ||||
|         template <typename T> | ||||
|         const T* End() const { return reinterpret_cast<T*>(stackTop_); } | ||||
|  | ||||
|         template <typename T> | ||||
|         T* Bottom() { return reinterpret_cast<T*>(stack_); } | ||||
|  | ||||
|         template <typename T> | ||||
|         const T* Bottom() const { return reinterpret_cast<T*>(stack_); } | ||||
|  | ||||
|         bool HasAllocator() const { | ||||
|             return allocator_ != 0; | ||||
|         } | ||||
|  | ||||
|         Allocator& GetAllocator() { | ||||
|             RAPIDJSON_ASSERT(allocator_); | ||||
|             return *allocator_; | ||||
|         } | ||||
|  | ||||
|         bool Empty() const { return stackTop_ == stack_; } | ||||
|         size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } | ||||
|         size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } | ||||
|  | ||||
|     private: | ||||
|         template <typename T> | ||||
|         void Expand(size_t count) { | ||||
|             // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. | ||||
|             size_t newCapacity; | ||||
|             if (stack_ == 0) { | ||||
|                 if (!allocator_) | ||||
|                     ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); | ||||
|                 newCapacity = initialCapacity_; | ||||
|             } | ||||
|             else { | ||||
|                 newCapacity = GetCapacity(); | ||||
|                 newCapacity += (newCapacity + 1) / 2; | ||||
|             } | ||||
|             size_t newSize = GetSize() + sizeof(T) * count; | ||||
|             if (newCapacity < newSize) | ||||
|                 newCapacity = newSize; | ||||
|  | ||||
|             Resize(newCapacity); | ||||
|         } | ||||
|  | ||||
|         void Resize(size_t newCapacity) { | ||||
|             const size_t size = GetSize(); // Backup the current size | ||||
|             stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); | ||||
|             stackTop_ = stack_ + size; | ||||
|             stackEnd_ = stack_ + newCapacity; | ||||
|         } | ||||
|  | ||||
|         void Destroy() { | ||||
|             Allocator::Free(stack_); | ||||
|             RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack | ||||
|         } | ||||
|  | ||||
|         // Prohibit copy constructor & assignment operator. | ||||
|         Stack(const Stack&); | ||||
|         Stack& operator=(const Stack&); | ||||
|  | ||||
|         Allocator* allocator_; | ||||
|         Allocator* ownAllocator_; | ||||
|         char* stack_; | ||||
|         char* stackTop_; | ||||
|         char* stackEnd_; | ||||
|         size_t initialCapacity_; | ||||
|     }; | ||||
|     Allocator* allocator_; | ||||
|     Allocator* ownAllocator_; | ||||
|     char *stack_; | ||||
|     char *stackTop_; | ||||
|     char *stackEnd_; | ||||
|     size_t initialCapacity_; | ||||
| }; | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_INTERNAL_STRFUNC_H_ | ||||
| @@ -21,47 +21,47 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     //! Custom strlen() which works on different character types. | ||||
|     /*! \tparam Ch Character type (e.g. char, wchar_t, short) | ||||
| //! Custom strlen() which works on different character types. | ||||
| /*! \tparam Ch Character type (e.g. char, wchar_t, short) | ||||
|     \param s Null-terminated input string. | ||||
|     \return Number of characters in the string.  | ||||
|     \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. | ||||
| */ | ||||
|     template <typename Ch> | ||||
|     inline SizeType StrLen(const Ch* s) { | ||||
|         RAPIDJSON_ASSERT(s != 0); | ||||
|         const Ch* p = s; | ||||
|         while (*p) ++p; | ||||
|         return SizeType(p - s); | ||||
|     } | ||||
| template <typename Ch> | ||||
| inline SizeType StrLen(const Ch* s) { | ||||
|     RAPIDJSON_ASSERT(s != 0); | ||||
|     const Ch* p = s; | ||||
|     while (*p) ++p; | ||||
|     return SizeType(p - s); | ||||
| } | ||||
|  | ||||
|     template <> | ||||
|     inline SizeType StrLen(const char* s) { | ||||
|         return SizeType(std::strlen(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)); | ||||
|     } | ||||
| template <> | ||||
| inline SizeType StrLen(const wchar_t* s) { | ||||
|     return SizeType(std::wcslen(s)); | ||||
| } | ||||
|  | ||||
|     //! Returns number of code points in a encoded string. | ||||
|     template <typename Encoding> | ||||
|     bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { | ||||
|         RAPIDJSON_ASSERT(s != 0); | ||||
|         RAPIDJSON_ASSERT(outCount != 0); | ||||
|         GenericStringStream<Encoding> is(s); | ||||
|         const typename Encoding::Ch* end = s + length; | ||||
|         SizeType count = 0; | ||||
|         while (is.src_ < end) { | ||||
|             unsigned codepoint; | ||||
|             if (!Encoding::Decode(is, &codepoint)) | ||||
|                 return false; | ||||
|             count++; | ||||
|         } | ||||
|         *outCount = count; | ||||
|         return true; | ||||
| //! Returns number of code points in a encoded string. | ||||
| template<typename Encoding> | ||||
| bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { | ||||
|     RAPIDJSON_ASSERT(s != 0); | ||||
|     RAPIDJSON_ASSERT(outCount != 0); | ||||
|     GenericStringStream<Encoding> is(s); | ||||
|     const typename Encoding::Ch* end = s + length; | ||||
|     SizeType count = 0; | ||||
|     while (is.src_ < end) { | ||||
|         unsigned codepoint; | ||||
|         if (!Encoding::Decode(is, &codepoint)) | ||||
|             return false; | ||||
|         count++; | ||||
|     } | ||||
|     *outCount = count; | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_STRTOD_ | ||||
| @@ -25,265 +25,265 @@ | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     inline double FastPath(double significand, int exp) { | ||||
|         if (exp < -308) | ||||
|             return 0.0; | ||||
|         else if (exp >= 0) | ||||
|             return significand * internal::Pow10(exp); | ||||
|         else | ||||
|             return significand / internal::Pow10(-exp); | ||||
| inline double FastPath(double significand, int exp) { | ||||
|     if (exp < -308) | ||||
|         return 0.0; | ||||
|     else if (exp >= 0) | ||||
|         return significand * internal::Pow10(exp); | ||||
|     else | ||||
|         return significand / internal::Pow10(-exp); | ||||
| } | ||||
|  | ||||
| inline double StrtodNormalPrecision(double d, int p) { | ||||
|     if (p < -308) { | ||||
|         // Prevent expSum < -308, making Pow10(p) = 0 | ||||
|         d = FastPath(d, -308); | ||||
|         d = FastPath(d, p + 308); | ||||
|     } | ||||
|     else | ||||
|         d = FastPath(d, p); | ||||
|     return d; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| inline T Min3(T a, T b, T c) { | ||||
|     T m = a; | ||||
|     if (m > b) m = b; | ||||
|     if (m > c) m = c; | ||||
|     return m; | ||||
| } | ||||
|  | ||||
| inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { | ||||
|     const Double db(b); | ||||
|     const uint64_t bInt = db.IntegerSignificand(); | ||||
|     const int bExp = db.IntegerExponent(); | ||||
|     const int hExp = bExp - 1; | ||||
|  | ||||
|     int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; | ||||
|  | ||||
|     // Adjust for decimal exponent | ||||
|     if (dExp >= 0) { | ||||
|         dS_Exp2 += dExp; | ||||
|         dS_Exp5 += dExp; | ||||
|     } | ||||
|     else { | ||||
|         bS_Exp2 -= dExp; | ||||
|         bS_Exp5 -= dExp; | ||||
|         hS_Exp2 -= dExp; | ||||
|         hS_Exp5 -= dExp; | ||||
|     } | ||||
|  | ||||
|     inline double StrtodNormalPrecision(double d, int p) { | ||||
|         if (p < -308) { | ||||
|             // Prevent expSum < -308, making Pow10(p) = 0 | ||||
|             d = FastPath(d, -308); | ||||
|             d = FastPath(d, p + 308); | ||||
|         } | ||||
|         else | ||||
|             d = FastPath(d, p); | ||||
|         return d; | ||||
|     // Adjust for binary exponent | ||||
|     if (bExp >= 0) | ||||
|         bS_Exp2 += bExp; | ||||
|     else { | ||||
|         dS_Exp2 -= bExp; | ||||
|         hS_Exp2 -= bExp; | ||||
|     } | ||||
|  | ||||
|     template <typename T> | ||||
|     inline T Min3(T a, T b, T c) { | ||||
|         T m = a; | ||||
|         if (m > b) m = b; | ||||
|         if (m > c) m = c; | ||||
|         return m; | ||||
|     // Adjust for half ulp exponent | ||||
|     if (hExp >= 0) | ||||
|         hS_Exp2 += hExp; | ||||
|     else { | ||||
|         dS_Exp2 -= hExp; | ||||
|         bS_Exp2 -= hExp; | ||||
|     } | ||||
|  | ||||
|     inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { | ||||
|         const Double db(b); | ||||
|         const uint64_t bInt = db.IntegerSignificand(); | ||||
|         const int bExp = db.IntegerExponent(); | ||||
|         const int hExp = bExp - 1; | ||||
|     // Remove common power of two factor from all three scaled values | ||||
|     int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); | ||||
|     dS_Exp2 -= common_Exp2; | ||||
|     bS_Exp2 -= common_Exp2; | ||||
|     hS_Exp2 -= common_Exp2; | ||||
|  | ||||
|         int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; | ||||
|     BigInteger dS = d; | ||||
|     dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2); | ||||
|  | ||||
|         // Adjust for decimal exponent | ||||
|         if (dExp >= 0) { | ||||
|             dS_Exp2 += dExp; | ||||
|             dS_Exp5 += dExp; | ||||
|         } | ||||
|         else { | ||||
|             bS_Exp2 -= dExp; | ||||
|             bS_Exp5 -= dExp; | ||||
|             hS_Exp2 -= dExp; | ||||
|             hS_Exp5 -= dExp; | ||||
|         } | ||||
|     BigInteger bS(bInt); | ||||
|     bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2); | ||||
|  | ||||
|         // Adjust for binary exponent | ||||
|         if (bExp >= 0) | ||||
|             bS_Exp2 += bExp; | ||||
|         else { | ||||
|             dS_Exp2 -= bExp; | ||||
|             hS_Exp2 -= bExp; | ||||
|         } | ||||
|     BigInteger hS(1); | ||||
|     hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2); | ||||
|  | ||||
|         // Adjust for half ulp exponent | ||||
|         if (hExp >= 0) | ||||
|             hS_Exp2 += hExp; | ||||
|         else { | ||||
|             dS_Exp2 -= hExp; | ||||
|             bS_Exp2 -= hExp; | ||||
|         } | ||||
|     BigInteger delta(0); | ||||
|     dS.Difference(bS, &delta); | ||||
|  | ||||
|         // Remove common power of two factor from all three scaled values | ||||
|         int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); | ||||
|         dS_Exp2 -= common_Exp2; | ||||
|         bS_Exp2 -= common_Exp2; | ||||
|         hS_Exp2 -= common_Exp2; | ||||
|     return delta.Compare(hS); | ||||
| } | ||||
|  | ||||
|         BigInteger dS = d; | ||||
|         dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2); | ||||
|  | ||||
|         BigInteger bS(bInt); | ||||
|         bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2); | ||||
|  | ||||
|         BigInteger hS(1); | ||||
|         hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2); | ||||
|  | ||||
|         BigInteger delta(0); | ||||
|         dS.Difference(bS, &delta); | ||||
|  | ||||
|         return delta.Compare(hS); | ||||
| inline bool StrtodFast(double d, int p, double* result) { | ||||
|     // Use fast path for string-to-double conversion if possible | ||||
|     // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ | ||||
|     if (p > 22  && p < 22 + 16) { | ||||
|         // Fast Path Cases In Disguise | ||||
|         d *= internal::Pow10(p - 22); | ||||
|         p = 22; | ||||
|     } | ||||
|  | ||||
|     inline bool StrtodFast(double d, int p, double* result) { | ||||
|         // Use fast path for string-to-double conversion if possible | ||||
|         // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ | ||||
|         if (p > 22 && p < 22 + 16) { | ||||
|             // Fast Path Cases In Disguise | ||||
|             d *= internal::Pow10(p - 22); | ||||
|             p = 22; | ||||
|         } | ||||
|     if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 | ||||
|         *result = FastPath(d, p); | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|         return false; | ||||
| } | ||||
|  | ||||
|         if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 | ||||
|             *result = FastPath(d, p); | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|             return false; | ||||
| // Compute an approximation and see if it is within 1/2 ULP | ||||
| inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { | ||||
|     uint64_t significand = 0; | ||||
|     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')) | ||||
|             break; | ||||
|         significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); | ||||
|     } | ||||
|      | ||||
|     if (i < dLen && decimals[i] >= '5') // Rounding | ||||
|         significand++; | ||||
|  | ||||
|     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; | ||||
|  | ||||
|     dExp += remaining; | ||||
|  | ||||
|     int actualExp; | ||||
|     DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); | ||||
|     if (actualExp != dExp) { | ||||
|         static const DiyFp kPow10[] = { | ||||
|             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; | ||||
|         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; | ||||
|     } | ||||
|  | ||||
|     // Compute an approximation and see if it is within 1/2 ULP | ||||
|     inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { | ||||
|         uint64_t significand = 0; | ||||
|         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')) | ||||
|                 break; | ||||
|             significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); | ||||
|         } | ||||
|     v = v * cachedPower; | ||||
|  | ||||
|         if (i < dLen && decimals[i] >= '5') // Rounding | ||||
|             significand++; | ||||
|     error += kUlp + (error == 0 ? 0 : 1); | ||||
|  | ||||
|         int remaining = dLen - i; | ||||
|         const int kUlpShift = 3; | ||||
|         const int kUlp = 1 << kUlpShift; | ||||
|         int64_t error = (remaining == 0) ? 0 : kUlp / 2; | ||||
|     const int oldExp = v.e; | ||||
|     v = v.Normalize(); | ||||
|     error <<= oldExp - v.e; | ||||
|  | ||||
|         DiyFp v(significand, 0); | ||||
|         v = v.Normalize(); | ||||
|         error <<= -v.e; | ||||
|  | ||||
|         dExp += remaining; | ||||
|  | ||||
|         int actualExp; | ||||
|         DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); | ||||
|         if (actualExp != dExp) { | ||||
|             static const DiyFp kPow10[] = { | ||||
|                 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; | ||||
|             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; | ||||
|         } | ||||
|  | ||||
|         v = v * cachedPower; | ||||
|  | ||||
|         error += kUlp + (error == 0 ? 0 : 1); | ||||
|  | ||||
|         const int oldExp = v.e; | ||||
|         v = v.Normalize(); | ||||
|         error <<= oldExp - v.e; | ||||
|  | ||||
|         const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); | ||||
|         int precisionSize = 64 - effectiveSignificandSize; | ||||
|         if (precisionSize + kUlpShift >= 64) { | ||||
|             int scaleExp = (precisionSize + kUlpShift) - 63; | ||||
|             v.f >>= scaleExp; | ||||
|             v.e += scaleExp; | ||||
|             error = (error >> scaleExp) + 1 + kUlp; | ||||
|             precisionSize -= scaleExp; | ||||
|         } | ||||
|  | ||||
|         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)) { | ||||
|             rounded.f++; | ||||
|             if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) | ||||
|                 rounded.f >>= 1; | ||||
|                 rounded.e++; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         *result = rounded.ToDouble(); | ||||
|  | ||||
|         return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); | ||||
|     const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); | ||||
|     int precisionSize = 64 - effectiveSignificandSize; | ||||
|     if (precisionSize + kUlpShift >= 64) { | ||||
|         int scaleExp = (precisionSize + kUlpShift) - 63; | ||||
|         v.f >>= scaleExp; | ||||
|         v.e += scaleExp;  | ||||
|         error = (error >> scaleExp) + 1 + kUlp; | ||||
|         precisionSize -= scaleExp; | ||||
|     } | ||||
|  | ||||
|     inline double StrtodBigInteger(double approx, const char* 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) | ||||
|             return a.Value(); // within half ULP | ||||
|         else if (cmp == 0) { | ||||
|             // Round towards even | ||||
|             if (a.Significand() & 1) | ||||
|                 return a.NextPositiveDouble(); | ||||
|             else | ||||
|                 return a.Value(); | ||||
|     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)) { | ||||
|         rounded.f++; | ||||
|         if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) | ||||
|             rounded.f >>= 1; | ||||
|             rounded.e++; | ||||
|         } | ||||
|         else // adjustment | ||||
|     } | ||||
|  | ||||
|     *result = rounded.ToDouble(); | ||||
|  | ||||
|     return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); | ||||
| } | ||||
|  | ||||
| inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { | ||||
|     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) | ||||
|         return a.Value();  // within half ULP | ||||
|     else if (cmp == 0) { | ||||
|         // Round towards even | ||||
|         if (a.Significand() & 1) | ||||
|             return a.NextPositiveDouble(); | ||||
|         else | ||||
|             return a.Value(); | ||||
|     } | ||||
|     else // adjustment | ||||
|         return a.NextPositiveDouble(); | ||||
| } | ||||
|  | ||||
| inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { | ||||
|     RAPIDJSON_ASSERT(d >= 0.0); | ||||
|     RAPIDJSON_ASSERT(length >= 1); | ||||
|  | ||||
|     double result = 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 (dLen > 0 && *decimals == '0') { | ||||
|         dLen--; | ||||
|         decimals++; | ||||
|     } | ||||
|  | ||||
|     inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { | ||||
|         RAPIDJSON_ASSERT(d >= 0.0); | ||||
|         RAPIDJSON_ASSERT(length >= 1); | ||||
|  | ||||
|         double result = 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 (dLen > 0 && *decimals == '0') { | ||||
|             dLen--; | ||||
|             decimals++; | ||||
|         } | ||||
|  | ||||
|         // Trim trailing zeros | ||||
|         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 = 767 + 1; | ||||
|         if (dLen > kMaxDecimalDigit) { | ||||
|             dExp += dLen - kMaxDecimalDigit; | ||||
|             dLen = kMaxDecimalDigit; | ||||
|         } | ||||
|  | ||||
|         // If too small, underflow to zero. | ||||
|         // Any x <= 10^-324 is interpreted as zero. | ||||
|         if (dLen + dExp <= -324) | ||||
|             return 0.0; | ||||
|  | ||||
|         // 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, dLen, dExp); | ||||
|     // Trim trailing zeros | ||||
|     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 = 767 + 1; | ||||
|     if (dLen > kMaxDecimalDigit) { | ||||
|         dExp += dLen - kMaxDecimalDigit; | ||||
|         dLen = kMaxDecimalDigit; | ||||
|     } | ||||
|  | ||||
|     // If too small, underflow to zero. | ||||
|     // Any x <= 10^-324 is interpreted as zero. | ||||
|     if (dLen + dExp <= -324) | ||||
|         return 0.0; | ||||
|  | ||||
|     // 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, dLen, dExp); | ||||
| } | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
|   | ||||
| @@ -19,22 +19,22 @@ | ||||
|  | ||||
| #if defined(__clang__) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(c++ 98 - compat) | ||||
| RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| namespace internal { | ||||
|  | ||||
|     //! Custom swap() to avoid dependency on C++ <algorithm> header | ||||
|     /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. | ||||
| //! Custom swap() to avoid dependency on C++ <algorithm> header | ||||
| /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. | ||||
|     \note This has the same semantics as std::swap(). | ||||
| */ | ||||
|     template <typename T> | ||||
|     inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { | ||||
|         T tmp = a; | ||||
| template <typename T> | ||||
| inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { | ||||
|     T tmp = a; | ||||
|         a = b; | ||||
|         b = tmp; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace internal | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_ISTREAMWRAPPER_H_ | ||||
| @@ -44,7 +44,7 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
|     \tparam StreamType Class derived from \c std::basic_istream. | ||||
| */ | ||||
|  | ||||
|     | ||||
| template <typename StreamType> | ||||
| class BasicIStreamWrapper { | ||||
| public: | ||||
| @@ -54,7 +54,7 @@ public: | ||||
|     /*! | ||||
|         \param stream stream opened for read. | ||||
|     */ | ||||
|     BasicIStreamWrapper(StreamType& stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { | ||||
|     BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {  | ||||
|         Read(); | ||||
|     } | ||||
|  | ||||
| @@ -64,30 +64,20 @@ public: | ||||
|         \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) { | ||||
|     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(); | ||||
|     } | ||||
|  | ||||
|     Ch Peek() const { return *current_; } | ||||
|     Ch Take() { | ||||
|         Ch c = *current_; | ||||
|         Read(); | ||||
|         return c; | ||||
|     } | ||||
|     Ch Take() { Ch c = *current_; Read(); return c; } | ||||
|     size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } | ||||
|  | ||||
|     // Not implemented | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     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 { | ||||
| @@ -116,13 +106,13 @@ private: | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     StreamType& stream_; | ||||
|     StreamType &stream_; | ||||
|     Ch peekBuffer_[4], *buffer_; | ||||
|     size_t bufferSize_; | ||||
|     Ch* bufferLast_; | ||||
|     Ch* current_; | ||||
|     Ch *bufferLast_; | ||||
|     Ch *current_; | ||||
|     size_t readCount_; | ||||
|     size_t count_; //!< Number of characters read | ||||
|     size_t count_;  //!< Number of characters read | ||||
|     bool eof_; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_MEMORYBUFFER_H_ | ||||
| @@ -60,7 +60,7 @@ struct GenericMemoryBuffer { | ||||
| typedef GenericMemoryBuffer<> MemoryBuffer; | ||||
|  | ||||
| //! Implement specialized version of PutN() with memset() for better performance. | ||||
| template <> | ||||
| template<> | ||||
| inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { | ||||
|     std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c)); | ||||
| } | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_MEMORYSTREAM_H_ | ||||
| @@ -19,8 +19,8 @@ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(unreachable - code) | ||||
| RAPIDJSON_DIAG_OFF(missing - noreturn) | ||||
| RAPIDJSON_DIAG_OFF(unreachable-code) | ||||
| RAPIDJSON_DIAG_OFF(missing-noreturn) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -40,32 +40,26 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| struct MemoryStream { | ||||
|     typedef char Ch; // byte | ||||
|  | ||||
|     MemoryStream(const Ch* src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} | ||||
|     MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} | ||||
|  | ||||
|     Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } | ||||
|     Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } | ||||
|     size_t Tell() const { return static_cast<size_t>(src_ - begin_); } | ||||
|  | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
|     // For encoding detection only. | ||||
|     const Ch* Peek4() const { | ||||
|         return Tell() + 4 <= size_ ? src_ : 0; | ||||
|     } | ||||
|  | ||||
|     const Ch* src_;   //!< Current read position. | ||||
|     const Ch* begin_; //!< Original head of the string. | ||||
|     const Ch* end_;   //!< End of stream. | ||||
|     size_t size_;     //!< Size of the stream. | ||||
|     const Ch* src_;     //!< Current read position. | ||||
|     const Ch* begin_;   //!< Original head of the string. | ||||
|     const Ch* end_;     //!< End of stream. | ||||
|     size_t size_;       //!< Size of the stream. | ||||
| }; | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
| @@ -1,37 +1,37 @@ | ||||
| // ISO C9x  compliant inttypes.h for Microsoft Visual Studio | ||||
| // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 | ||||
| // | ||||
| // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124  | ||||
| //  | ||||
| //  Copyright (c) 2006-2013 Alexander Chemeris | ||||
| // | ||||
| //  | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| // modification, are permitted provided that the following conditions are met: | ||||
| // | ||||
| //  | ||||
| //   1. Redistributions of source code must retain the above copyright notice, | ||||
| //      this list of conditions and the following disclaimer. | ||||
| // | ||||
| //  | ||||
| //   2. Redistributions in binary form must reproduce the above copyright | ||||
| //      notice, this list of conditions and the following disclaimer in the | ||||
| //      documentation and/or other materials provided with the distribution. | ||||
| // | ||||
| //  | ||||
| //   3. Neither the name of the product nor the names of its contributors may | ||||
| //      be used to endorse or promote products derived from this software | ||||
| //      without specific prior written permission. | ||||
| // | ||||
| //  | ||||
| // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||||
| // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
| // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||||
| // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||
| // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||||
| // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||||
| // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  | ||||
| // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
| // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
| // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| //  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| // The above software in this distribution may have been modified by | ||||
| // THL A29 Limited ("Tencent Modifications"). | ||||
| // The above software in this distribution may have been modified by  | ||||
| // THL A29 Limited ("Tencent Modifications").  | ||||
| // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. | ||||
|  | ||||
| #ifndef _MSC_VER // [ | ||||
| @@ -55,8 +55,8 @@ | ||||
| // 7.8 Format conversion of integer types | ||||
|  | ||||
| typedef struct { | ||||
|     intmax_t quot; | ||||
|     intmax_t rem; | ||||
|    intmax_t quot; | ||||
|    intmax_t rem; | ||||
| } imaxdiv_t; | ||||
|  | ||||
| // 7.8.1 Macros for format specifiers | ||||
| @@ -64,212 +64,212 @@ typedef struct { | ||||
| #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198 | ||||
|  | ||||
| // The fprintf macros for signed integers are: | ||||
| #define PRId8      "d" | ||||
| #define PRIi8      "i" | ||||
| #define PRIdLEAST8 "d" | ||||
| #define PRIiLEAST8 "i" | ||||
| #define PRIdFAST8  "d" | ||||
| #define PRIiFAST8  "i" | ||||
| #define PRId8       "d" | ||||
| #define PRIi8       "i" | ||||
| #define PRIdLEAST8  "d" | ||||
| #define PRIiLEAST8  "i" | ||||
| #define PRIdFAST8   "d" | ||||
| #define PRIiFAST8   "i" | ||||
|  | ||||
| #define PRId16      "hd" | ||||
| #define PRIi16      "hi" | ||||
| #define PRIdLEAST16 "hd" | ||||
| #define PRIiLEAST16 "hi" | ||||
| #define PRIdFAST16  "hd" | ||||
| #define PRIiFAST16  "hi" | ||||
| #define PRId16       "hd" | ||||
| #define PRIi16       "hi" | ||||
| #define PRIdLEAST16  "hd" | ||||
| #define PRIiLEAST16  "hi" | ||||
| #define PRIdFAST16   "hd" | ||||
| #define PRIiFAST16   "hi" | ||||
|  | ||||
| #define PRId32      "I32d" | ||||
| #define PRIi32      "I32i" | ||||
| #define PRIdLEAST32 "I32d" | ||||
| #define PRIiLEAST32 "I32i" | ||||
| #define PRIdFAST32  "I32d" | ||||
| #define PRIiFAST32  "I32i" | ||||
| #define PRId32       "I32d" | ||||
| #define PRIi32       "I32i" | ||||
| #define PRIdLEAST32  "I32d" | ||||
| #define PRIiLEAST32  "I32i" | ||||
| #define PRIdFAST32   "I32d" | ||||
| #define PRIiFAST32   "I32i" | ||||
|  | ||||
| #define PRId64      "I64d" | ||||
| #define PRIi64      "I64i" | ||||
| #define PRIdLEAST64 "I64d" | ||||
| #define PRIiLEAST64 "I64i" | ||||
| #define PRIdFAST64  "I64d" | ||||
| #define PRIiFAST64  "I64i" | ||||
| #define PRId64       "I64d" | ||||
| #define PRIi64       "I64i" | ||||
| #define PRIdLEAST64  "I64d" | ||||
| #define PRIiLEAST64  "I64i" | ||||
| #define PRIdFAST64   "I64d" | ||||
| #define PRIiFAST64   "I64i" | ||||
|  | ||||
| #define PRIdMAX "I64d" | ||||
| #define PRIiMAX "I64i" | ||||
| #define PRIdMAX     "I64d" | ||||
| #define PRIiMAX     "I64i" | ||||
|  | ||||
| #define PRIdPTR    "Id" | ||||
| #define PRIiPTR    "Ii" | ||||
| #define PRIdPTR     "Id" | ||||
| #define PRIiPTR     "Ii" | ||||
|  | ||||
| // The fprintf macros for unsigned integers are: | ||||
| #define PRIo8      "o" | ||||
| #define PRIu8      "u" | ||||
| #define PRIx8      "x" | ||||
| #define PRIX8      "X" | ||||
| #define PRIoLEAST8 "o" | ||||
| #define PRIuLEAST8 "u" | ||||
| #define PRIxLEAST8 "x" | ||||
| #define PRIXLEAST8 "X" | ||||
| #define PRIoFAST8  "o" | ||||
| #define PRIuFAST8  "u" | ||||
| #define PRIxFAST8  "x" | ||||
| #define PRIXFAST8  "X" | ||||
| #define PRIo8       "o" | ||||
| #define PRIu8       "u" | ||||
| #define PRIx8       "x" | ||||
| #define PRIX8       "X" | ||||
| #define PRIoLEAST8  "o" | ||||
| #define PRIuLEAST8  "u" | ||||
| #define PRIxLEAST8  "x" | ||||
| #define PRIXLEAST8  "X" | ||||
| #define PRIoFAST8   "o" | ||||
| #define PRIuFAST8   "u" | ||||
| #define PRIxFAST8   "x" | ||||
| #define PRIXFAST8   "X" | ||||
|  | ||||
| #define PRIo16      "ho" | ||||
| #define PRIu16      "hu" | ||||
| #define PRIx16      "hx" | ||||
| #define PRIX16      "hX" | ||||
| #define PRIoLEAST16 "ho" | ||||
| #define PRIuLEAST16 "hu" | ||||
| #define PRIxLEAST16 "hx" | ||||
| #define PRIXLEAST16 "hX" | ||||
| #define PRIoFAST16  "ho" | ||||
| #define PRIuFAST16  "hu" | ||||
| #define PRIxFAST16  "hx" | ||||
| #define PRIXFAST16  "hX" | ||||
| #define PRIo16       "ho" | ||||
| #define PRIu16       "hu" | ||||
| #define PRIx16       "hx" | ||||
| #define PRIX16       "hX" | ||||
| #define PRIoLEAST16  "ho" | ||||
| #define PRIuLEAST16  "hu" | ||||
| #define PRIxLEAST16  "hx" | ||||
| #define PRIXLEAST16  "hX" | ||||
| #define PRIoFAST16   "ho" | ||||
| #define PRIuFAST16   "hu" | ||||
| #define PRIxFAST16   "hx" | ||||
| #define PRIXFAST16   "hX" | ||||
|  | ||||
| #define PRIo32      "I32o" | ||||
| #define PRIu32      "I32u" | ||||
| #define PRIx32      "I32x" | ||||
| #define PRIX32      "I32X" | ||||
| #define PRIoLEAST32 "I32o" | ||||
| #define PRIuLEAST32 "I32u" | ||||
| #define PRIxLEAST32 "I32x" | ||||
| #define PRIXLEAST32 "I32X" | ||||
| #define PRIoFAST32  "I32o" | ||||
| #define PRIuFAST32  "I32u" | ||||
| #define PRIxFAST32  "I32x" | ||||
| #define PRIXFAST32  "I32X" | ||||
| #define PRIo32       "I32o" | ||||
| #define PRIu32       "I32u" | ||||
| #define PRIx32       "I32x" | ||||
| #define PRIX32       "I32X" | ||||
| #define PRIoLEAST32  "I32o" | ||||
| #define PRIuLEAST32  "I32u" | ||||
| #define PRIxLEAST32  "I32x" | ||||
| #define PRIXLEAST32  "I32X" | ||||
| #define PRIoFAST32   "I32o" | ||||
| #define PRIuFAST32   "I32u" | ||||
| #define PRIxFAST32   "I32x" | ||||
| #define PRIXFAST32   "I32X" | ||||
|  | ||||
| #define PRIo64      "I64o" | ||||
| #define PRIu64      "I64u" | ||||
| #define PRIx64      "I64x" | ||||
| #define PRIX64      "I64X" | ||||
| #define PRIoLEAST64 "I64o" | ||||
| #define PRIuLEAST64 "I64u" | ||||
| #define PRIxLEAST64 "I64x" | ||||
| #define PRIXLEAST64 "I64X" | ||||
| #define PRIoFAST64  "I64o" | ||||
| #define PRIuFAST64  "I64u" | ||||
| #define PRIxFAST64  "I64x" | ||||
| #define PRIXFAST64  "I64X" | ||||
| #define PRIo64       "I64o" | ||||
| #define PRIu64       "I64u" | ||||
| #define PRIx64       "I64x" | ||||
| #define PRIX64       "I64X" | ||||
| #define PRIoLEAST64  "I64o" | ||||
| #define PRIuLEAST64  "I64u" | ||||
| #define PRIxLEAST64  "I64x" | ||||
| #define PRIXLEAST64  "I64X" | ||||
| #define PRIoFAST64   "I64o" | ||||
| #define PRIuFAST64   "I64u" | ||||
| #define PRIxFAST64   "I64x" | ||||
| #define PRIXFAST64   "I64X" | ||||
|  | ||||
| #define PRIoMAX "I64o" | ||||
| #define PRIuMAX "I64u" | ||||
| #define PRIxMAX "I64x" | ||||
| #define PRIXMAX "I64X" | ||||
| #define PRIoMAX     "I64o" | ||||
| #define PRIuMAX     "I64u" | ||||
| #define PRIxMAX     "I64x" | ||||
| #define PRIXMAX     "I64X" | ||||
|  | ||||
| #define PRIoPTR    "Io" | ||||
| #define PRIuPTR    "Iu" | ||||
| #define PRIxPTR    "Ix" | ||||
| #define PRIXPTR    "IX" | ||||
| #define PRIoPTR     "Io" | ||||
| #define PRIuPTR     "Iu" | ||||
| #define PRIxPTR     "Ix" | ||||
| #define PRIXPTR     "IX" | ||||
|  | ||||
| // The fscanf macros for signed integers are: | ||||
| #define SCNd8      "d" | ||||
| #define SCNi8      "i" | ||||
| #define SCNdLEAST8 "d" | ||||
| #define SCNiLEAST8 "i" | ||||
| #define SCNdFAST8  "d" | ||||
| #define SCNiFAST8  "i" | ||||
| #define SCNd8       "d" | ||||
| #define SCNi8       "i" | ||||
| #define SCNdLEAST8  "d" | ||||
| #define SCNiLEAST8  "i" | ||||
| #define SCNdFAST8   "d" | ||||
| #define SCNiFAST8   "i" | ||||
|  | ||||
| #define SCNd16      "hd" | ||||
| #define SCNi16      "hi" | ||||
| #define SCNdLEAST16 "hd" | ||||
| #define SCNiLEAST16 "hi" | ||||
| #define SCNdFAST16  "hd" | ||||
| #define SCNiFAST16  "hi" | ||||
| #define SCNd16       "hd" | ||||
| #define SCNi16       "hi" | ||||
| #define SCNdLEAST16  "hd" | ||||
| #define SCNiLEAST16  "hi" | ||||
| #define SCNdFAST16   "hd" | ||||
| #define SCNiFAST16   "hi" | ||||
|  | ||||
| #define SCNd32      "ld" | ||||
| #define SCNi32      "li" | ||||
| #define SCNdLEAST32 "ld" | ||||
| #define SCNiLEAST32 "li" | ||||
| #define SCNdFAST32  "ld" | ||||
| #define SCNiFAST32  "li" | ||||
| #define SCNd32       "ld" | ||||
| #define SCNi32       "li" | ||||
| #define SCNdLEAST32  "ld" | ||||
| #define SCNiLEAST32  "li" | ||||
| #define SCNdFAST32   "ld" | ||||
| #define SCNiFAST32   "li" | ||||
|  | ||||
| #define SCNd64      "I64d" | ||||
| #define SCNi64      "I64i" | ||||
| #define SCNdLEAST64 "I64d" | ||||
| #define SCNiLEAST64 "I64i" | ||||
| #define SCNdFAST64  "I64d" | ||||
| #define SCNiFAST64  "I64i" | ||||
| #define SCNd64       "I64d" | ||||
| #define SCNi64       "I64i" | ||||
| #define SCNdLEAST64  "I64d" | ||||
| #define SCNiLEAST64  "I64i" | ||||
| #define SCNdFAST64   "I64d" | ||||
| #define SCNiFAST64   "I64i" | ||||
|  | ||||
| #define SCNdMAX "I64d" | ||||
| #define SCNiMAX "I64i" | ||||
| #define SCNdMAX     "I64d" | ||||
| #define SCNiMAX     "I64i" | ||||
|  | ||||
| #ifdef _WIN64 // [ | ||||
| #define SCNdPTR "I64d" | ||||
| #define SCNiPTR "I64i" | ||||
| #else // _WIN64 ][ | ||||
| #define SCNdPTR "ld" | ||||
| #define SCNiPTR "li" | ||||
| #endif // _WIN64 ] | ||||
| #  define SCNdPTR     "I64d" | ||||
| #  define SCNiPTR     "I64i" | ||||
| #else  // _WIN64 ][ | ||||
| #  define SCNdPTR     "ld" | ||||
| #  define SCNiPTR     "li" | ||||
| #endif  // _WIN64 ] | ||||
|  | ||||
| // The fscanf macros for unsigned integers are: | ||||
| #define SCNo8      "o" | ||||
| #define SCNu8      "u" | ||||
| #define SCNx8      "x" | ||||
| #define SCNX8      "X" | ||||
| #define SCNoLEAST8 "o" | ||||
| #define SCNuLEAST8 "u" | ||||
| #define SCNxLEAST8 "x" | ||||
| #define SCNXLEAST8 "X" | ||||
| #define SCNoFAST8  "o" | ||||
| #define SCNuFAST8  "u" | ||||
| #define SCNxFAST8  "x" | ||||
| #define SCNXFAST8  "X" | ||||
| #define SCNo8       "o" | ||||
| #define SCNu8       "u" | ||||
| #define SCNx8       "x" | ||||
| #define SCNX8       "X" | ||||
| #define SCNoLEAST8  "o" | ||||
| #define SCNuLEAST8  "u" | ||||
| #define SCNxLEAST8  "x" | ||||
| #define SCNXLEAST8  "X" | ||||
| #define SCNoFAST8   "o" | ||||
| #define SCNuFAST8   "u" | ||||
| #define SCNxFAST8   "x" | ||||
| #define SCNXFAST8   "X" | ||||
|  | ||||
| #define SCNo16      "ho" | ||||
| #define SCNu16      "hu" | ||||
| #define SCNx16      "hx" | ||||
| #define SCNX16      "hX" | ||||
| #define SCNoLEAST16 "ho" | ||||
| #define SCNuLEAST16 "hu" | ||||
| #define SCNxLEAST16 "hx" | ||||
| #define SCNXLEAST16 "hX" | ||||
| #define SCNoFAST16  "ho" | ||||
| #define SCNuFAST16  "hu" | ||||
| #define SCNxFAST16  "hx" | ||||
| #define SCNXFAST16  "hX" | ||||
| #define SCNo16       "ho" | ||||
| #define SCNu16       "hu" | ||||
| #define SCNx16       "hx" | ||||
| #define SCNX16       "hX" | ||||
| #define SCNoLEAST16  "ho" | ||||
| #define SCNuLEAST16  "hu" | ||||
| #define SCNxLEAST16  "hx" | ||||
| #define SCNXLEAST16  "hX" | ||||
| #define SCNoFAST16   "ho" | ||||
| #define SCNuFAST16   "hu" | ||||
| #define SCNxFAST16   "hx" | ||||
| #define SCNXFAST16   "hX" | ||||
|  | ||||
| #define SCNo32      "lo" | ||||
| #define SCNu32      "lu" | ||||
| #define SCNx32      "lx" | ||||
| #define SCNX32      "lX" | ||||
| #define SCNoLEAST32 "lo" | ||||
| #define SCNuLEAST32 "lu" | ||||
| #define SCNxLEAST32 "lx" | ||||
| #define SCNXLEAST32 "lX" | ||||
| #define SCNoFAST32  "lo" | ||||
| #define SCNuFAST32  "lu" | ||||
| #define SCNxFAST32  "lx" | ||||
| #define SCNXFAST32  "lX" | ||||
| #define SCNo32       "lo" | ||||
| #define SCNu32       "lu" | ||||
| #define SCNx32       "lx" | ||||
| #define SCNX32       "lX" | ||||
| #define SCNoLEAST32  "lo" | ||||
| #define SCNuLEAST32  "lu" | ||||
| #define SCNxLEAST32  "lx" | ||||
| #define SCNXLEAST32  "lX" | ||||
| #define SCNoFAST32   "lo" | ||||
| #define SCNuFAST32   "lu" | ||||
| #define SCNxFAST32   "lx" | ||||
| #define SCNXFAST32   "lX" | ||||
|  | ||||
| #define SCNo64      "I64o" | ||||
| #define SCNu64      "I64u" | ||||
| #define SCNx64      "I64x" | ||||
| #define SCNX64      "I64X" | ||||
| #define SCNoLEAST64 "I64o" | ||||
| #define SCNuLEAST64 "I64u" | ||||
| #define SCNxLEAST64 "I64x" | ||||
| #define SCNXLEAST64 "I64X" | ||||
| #define SCNoFAST64  "I64o" | ||||
| #define SCNuFAST64  "I64u" | ||||
| #define SCNxFAST64  "I64x" | ||||
| #define SCNXFAST64  "I64X" | ||||
| #define SCNo64       "I64o" | ||||
| #define SCNu64       "I64u" | ||||
| #define SCNx64       "I64x" | ||||
| #define SCNX64       "I64X" | ||||
| #define SCNoLEAST64  "I64o" | ||||
| #define SCNuLEAST64  "I64u" | ||||
| #define SCNxLEAST64  "I64x" | ||||
| #define SCNXLEAST64  "I64X" | ||||
| #define SCNoFAST64   "I64o" | ||||
| #define SCNuFAST64   "I64u" | ||||
| #define SCNxFAST64   "I64x" | ||||
| #define SCNXFAST64   "I64X" | ||||
|  | ||||
| #define SCNoMAX "I64o" | ||||
| #define SCNuMAX "I64u" | ||||
| #define SCNxMAX "I64x" | ||||
| #define SCNXMAX "I64X" | ||||
| #define SCNoMAX     "I64o" | ||||
| #define SCNuMAX     "I64u" | ||||
| #define SCNxMAX     "I64x" | ||||
| #define SCNXMAX     "I64X" | ||||
|  | ||||
| #ifdef _WIN64 // [ | ||||
| #define SCNoPTR "I64o" | ||||
| #define SCNuPTR "I64u" | ||||
| #define SCNxPTR "I64x" | ||||
| #define SCNXPTR "I64X" | ||||
| #else // _WIN64 ][ | ||||
| #define SCNoPTR "lo" | ||||
| #define SCNuPTR "lu" | ||||
| #define SCNxPTR "lx" | ||||
| #define SCNXPTR "lX" | ||||
| #endif // _WIN64 ] | ||||
| #  define SCNoPTR     "I64o" | ||||
| #  define SCNuPTR     "I64u" | ||||
| #  define SCNxPTR     "I64x" | ||||
| #  define SCNXPTR     "I64X" | ||||
| #else  // _WIN64 ][ | ||||
| #  define SCNoPTR     "lo" | ||||
| #  define SCNuPTR     "lu" | ||||
| #  define SCNxPTR     "lx" | ||||
| #  define SCNXPTR     "lX" | ||||
| #endif  // _WIN64 ] | ||||
|  | ||||
| #endif // __STDC_FORMAT_MACROS ] | ||||
|  | ||||
| @@ -284,22 +284,23 @@ typedef struct { | ||||
| // in %MSVC.NET%\crt\src\div.c | ||||
| #ifdef STATIC_IMAXDIV // [ | ||||
| static | ||||
| #else                 // STATIC_IMAXDIV ][ | ||||
| #else // STATIC_IMAXDIV ][ | ||||
| _inline | ||||
| #endif                // STATIC_IMAXDIV ] | ||||
|     imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { | ||||
|     imaxdiv_t result; | ||||
| #endif // STATIC_IMAXDIV ] | ||||
| imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) | ||||
| { | ||||
|    imaxdiv_t result; | ||||
|  | ||||
|     result.quot = numer / denom; | ||||
|     result.rem = numer % denom; | ||||
|    result.quot = numer / denom; | ||||
|    result.rem = numer % denom; | ||||
|  | ||||
|     if (numer < 0 && result.rem > 0) { | ||||
|         // did division wrong; must fix up | ||||
|         ++result.quot; | ||||
|         result.rem -= denom; | ||||
|     } | ||||
|    if (numer < 0 && result.rem > 0) { | ||||
|       // did division wrong; must fix up | ||||
|       ++result.quot; | ||||
|       result.rem -= denom; | ||||
|    } | ||||
|  | ||||
|     return result; | ||||
|    return result; | ||||
| } | ||||
|  | ||||
| // 7.8.2.3 The strtoimax and strtoumax functions | ||||
|   | ||||
| @@ -1,37 +1,37 @@ | ||||
| // ISO C9x  compliant stdint.h for Microsoft Visual Studio | ||||
| // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 | ||||
| // | ||||
| // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124  | ||||
| //  | ||||
| //  Copyright (c) 2006-2013 Alexander Chemeris | ||||
| // | ||||
| //  | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| // modification, are permitted provided that the following conditions are met: | ||||
| // | ||||
| //  | ||||
| //   1. Redistributions of source code must retain the above copyright notice, | ||||
| //      this list of conditions and the following disclaimer. | ||||
| // | ||||
| //  | ||||
| //   2. Redistributions in binary form must reproduce the above copyright | ||||
| //      notice, this list of conditions and the following disclaimer in the | ||||
| //      documentation and/or other materials provided with the distribution. | ||||
| // | ||||
| //  | ||||
| //   3. Neither the name of the product nor the names of its contributors may | ||||
| //      be used to endorse or promote products derived from this software | ||||
| //      without specific prior written permission. | ||||
| // | ||||
| //  | ||||
| // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||||
| // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
| // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||||
| // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||
| // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||||
| // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||||
| // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  | ||||
| // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
| // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
| // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| //  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| // The above software in this distribution may have been modified by | ||||
| // THL A29 Limited ("Tencent Modifications"). | ||||
| // The above software in this distribution may have been modified by  | ||||
| // THL A29 Limited ("Tencent Modifications").  | ||||
| // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. | ||||
|  | ||||
| #ifndef _MSC_VER // [ | ||||
| @@ -76,10 +76,10 @@ | ||||
| // These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. | ||||
| // Check out Issue 9 for the details. | ||||
| #ifndef INTMAX_C //   [ | ||||
| #define INTMAX_C INT64_C | ||||
| #endif            // INTMAX_C    ] | ||||
| #  define INTMAX_C   INT64_C | ||||
| #endif // INTMAX_C    ] | ||||
| #ifndef UINTMAX_C //  [ | ||||
| #define UINTMAX_C UINT64_C | ||||
| #  define UINTMAX_C  UINT64_C | ||||
| #endif // UINTMAX_C   ] | ||||
|  | ||||
| #endif // __STDC_CONSTANT_MACROS ] | ||||
| @@ -95,18 +95,18 @@ | ||||
| #if defined(__cplusplus) && !defined(_M_ARM) | ||||
| extern "C" { | ||||
| #endif | ||||
| #include <wchar.h> | ||||
| #  include <wchar.h> | ||||
| #if defined(__cplusplus) && !defined(_M_ARM) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // Define _W64 macros to mark types changing their size, like intptr_t. | ||||
| #ifndef _W64 | ||||
| #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 | ||||
| #define _W64 __w64 | ||||
| #else | ||||
| #define _W64 | ||||
| #endif | ||||
| #  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 | ||||
| #     define _W64 __w64 | ||||
| #  else | ||||
| #     define _W64 | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -118,56 +118,56 @@ extern "C" { | ||||
| // realize that, e.g. char has the same size as __int8 | ||||
| // so we give up on __intX for them. | ||||
| #if (_MSC_VER < 1300) | ||||
| typedef signed char int8_t; | ||||
| typedef signed short int16_t; | ||||
| typedef signed int int32_t; | ||||
| typedef unsigned char uint8_t; | ||||
| typedef unsigned short uint16_t; | ||||
| typedef unsigned int uint32_t; | ||||
|    typedef signed char       int8_t; | ||||
|    typedef signed short      int16_t; | ||||
|    typedef signed int        int32_t; | ||||
|    typedef unsigned char     uint8_t; | ||||
|    typedef unsigned short    uint16_t; | ||||
|    typedef unsigned int      uint32_t; | ||||
| #else | ||||
| typedef signed __int8 int8_t; | ||||
| typedef signed __int16 int16_t; | ||||
| typedef signed __int32 int32_t; | ||||
| typedef unsigned __int8 uint8_t; | ||||
| typedef unsigned __int16 uint16_t; | ||||
| typedef unsigned __int32 uint32_t; | ||||
|    typedef signed __int8     int8_t; | ||||
|    typedef signed __int16    int16_t; | ||||
|    typedef signed __int32    int32_t; | ||||
|    typedef unsigned __int8   uint8_t; | ||||
|    typedef unsigned __int16  uint16_t; | ||||
|    typedef unsigned __int32  uint32_t; | ||||
| #endif | ||||
| typedef signed __int64 int64_t; | ||||
| typedef unsigned __int64 uint64_t; | ||||
| typedef signed __int64       int64_t; | ||||
| typedef unsigned __int64     uint64_t; | ||||
|  | ||||
|  | ||||
| // 7.18.1.2 Minimum-width integer types | ||||
| typedef int8_t int_least8_t; | ||||
| typedef int16_t int_least16_t; | ||||
| typedef int32_t int_least32_t; | ||||
| typedef int64_t int_least64_t; | ||||
| typedef uint8_t uint_least8_t; | ||||
| typedef uint16_t uint_least16_t; | ||||
| typedef uint32_t uint_least32_t; | ||||
| typedef uint64_t uint_least64_t; | ||||
| typedef int8_t    int_least8_t; | ||||
| typedef int16_t   int_least16_t; | ||||
| typedef int32_t   int_least32_t; | ||||
| typedef int64_t   int_least64_t; | ||||
| typedef uint8_t   uint_least8_t; | ||||
| typedef uint16_t  uint_least16_t; | ||||
| typedef uint32_t  uint_least32_t; | ||||
| typedef uint64_t  uint_least64_t; | ||||
|  | ||||
| // 7.18.1.3 Fastest minimum-width integer types | ||||
| typedef int8_t int_fast8_t; | ||||
| typedef int16_t int_fast16_t; | ||||
| typedef int32_t int_fast32_t; | ||||
| typedef int64_t int_fast64_t; | ||||
| typedef uint8_t uint_fast8_t; | ||||
| typedef uint16_t uint_fast16_t; | ||||
| typedef uint32_t uint_fast32_t; | ||||
| typedef uint64_t uint_fast64_t; | ||||
| typedef int8_t    int_fast8_t; | ||||
| typedef int16_t   int_fast16_t; | ||||
| typedef int32_t   int_fast32_t; | ||||
| typedef int64_t   int_fast64_t; | ||||
| typedef uint8_t   uint_fast8_t; | ||||
| typedef uint16_t  uint_fast16_t; | ||||
| typedef uint32_t  uint_fast32_t; | ||||
| typedef uint64_t  uint_fast64_t; | ||||
|  | ||||
| // 7.18.1.4 Integer types capable of holding object pointers | ||||
| #ifdef _WIN64 // [ | ||||
| typedef signed __int64 intptr_t; | ||||
| typedef unsigned __int64 uintptr_t; | ||||
| #else         // _WIN64 ][ | ||||
| typedef _W64 signed int intptr_t; | ||||
| typedef _W64 unsigned int uintptr_t; | ||||
| #endif        // _WIN64 ] | ||||
|    typedef signed __int64    intptr_t; | ||||
|    typedef unsigned __int64  uintptr_t; | ||||
| #else // _WIN64 ][ | ||||
|    typedef _W64 signed int   intptr_t; | ||||
|    typedef _W64 unsigned int uintptr_t; | ||||
| #endif // _WIN64 ] | ||||
|  | ||||
| // 7.18.1.5 Greatest-width integer types | ||||
| typedef int64_t intmax_t; | ||||
| typedef uint64_t uintmax_t; | ||||
| typedef int64_t   intmax_t; | ||||
| typedef uint64_t  uintmax_t; | ||||
|  | ||||
|  | ||||
| // 7.18.2 Limits of specified-width integer types | ||||
| @@ -175,32 +175,32 @@ typedef uint64_t uintmax_t; | ||||
| #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259 | ||||
|  | ||||
| // 7.18.2.1 Limits of exact-width integer types | ||||
| #define INT8_MIN         ((int8_t)_I8_MIN) | ||||
| #define INT8_MAX         _I8_MAX | ||||
| #define INT16_MIN        ((int16_t)_I16_MIN) | ||||
| #define INT16_MAX        _I16_MAX | ||||
| #define INT32_MIN        ((int32_t)_I32_MIN) | ||||
| #define INT32_MAX        _I32_MAX | ||||
| #define INT64_MIN        ((int64_t)_I64_MIN) | ||||
| #define INT64_MAX        _I64_MAX | ||||
| #define UINT8_MAX        _UI8_MAX | ||||
| #define UINT16_MAX       _UI16_MAX | ||||
| #define UINT32_MAX       _UI32_MAX | ||||
| #define UINT64_MAX       _UI64_MAX | ||||
| #define INT8_MIN     ((int8_t)_I8_MIN) | ||||
| #define INT8_MAX     _I8_MAX | ||||
| #define INT16_MIN    ((int16_t)_I16_MIN) | ||||
| #define INT16_MAX    _I16_MAX | ||||
| #define INT32_MIN    ((int32_t)_I32_MIN) | ||||
| #define INT32_MAX    _I32_MAX | ||||
| #define INT64_MIN    ((int64_t)_I64_MIN) | ||||
| #define INT64_MAX    _I64_MAX | ||||
| #define UINT8_MAX    _UI8_MAX | ||||
| #define UINT16_MAX   _UI16_MAX | ||||
| #define UINT32_MAX   _UI32_MAX | ||||
| #define UINT64_MAX   _UI64_MAX | ||||
|  | ||||
| // 7.18.2.2 Limits of minimum-width integer types | ||||
| #define INT_LEAST8_MIN   INT8_MIN | ||||
| #define INT_LEAST8_MAX   INT8_MAX | ||||
| #define INT_LEAST16_MIN  INT16_MIN | ||||
| #define INT_LEAST16_MAX  INT16_MAX | ||||
| #define INT_LEAST32_MIN  INT32_MIN | ||||
| #define INT_LEAST32_MAX  INT32_MAX | ||||
| #define INT_LEAST64_MIN  INT64_MIN | ||||
| #define INT_LEAST64_MAX  INT64_MAX | ||||
| #define UINT_LEAST8_MAX  UINT8_MAX | ||||
| #define UINT_LEAST16_MAX UINT16_MAX | ||||
| #define UINT_LEAST32_MAX UINT32_MAX | ||||
| #define UINT_LEAST64_MAX UINT64_MAX | ||||
| #define INT_LEAST8_MIN    INT8_MIN | ||||
| #define INT_LEAST8_MAX    INT8_MAX | ||||
| #define INT_LEAST16_MIN   INT16_MIN | ||||
| #define INT_LEAST16_MAX   INT16_MAX | ||||
| #define INT_LEAST32_MIN   INT32_MIN | ||||
| #define INT_LEAST32_MAX   INT32_MAX | ||||
| #define INT_LEAST64_MIN   INT64_MIN | ||||
| #define INT_LEAST64_MAX   INT64_MAX | ||||
| #define UINT_LEAST8_MAX   UINT8_MAX | ||||
| #define UINT_LEAST16_MAX  UINT16_MAX | ||||
| #define UINT_LEAST32_MAX  UINT32_MAX | ||||
| #define UINT_LEAST64_MAX  UINT64_MAX | ||||
|  | ||||
| // 7.18.2.3 Limits of fastest minimum-width integer types | ||||
| #define INT_FAST8_MIN    INT8_MIN | ||||
| @@ -218,51 +218,51 @@ typedef uint64_t uintmax_t; | ||||
|  | ||||
| // 7.18.2.4 Limits of integer types capable of holding object pointers | ||||
| #ifdef _WIN64 // [ | ||||
| #define INTPTR_MIN  INT64_MIN | ||||
| #define INTPTR_MAX  INT64_MAX | ||||
| #define UINTPTR_MAX UINT64_MAX | ||||
| #  define INTPTR_MIN   INT64_MIN | ||||
| #  define INTPTR_MAX   INT64_MAX | ||||
| #  define UINTPTR_MAX  UINT64_MAX | ||||
| #else // _WIN64 ][ | ||||
| #define INTPTR_MIN  INT32_MIN | ||||
| #define INTPTR_MAX  INT32_MAX | ||||
| #define UINTPTR_MAX UINT32_MAX | ||||
| #  define INTPTR_MIN   INT32_MIN | ||||
| #  define INTPTR_MAX   INT32_MAX | ||||
| #  define UINTPTR_MAX  UINT32_MAX | ||||
| #endif // _WIN64 ] | ||||
|  | ||||
| // 7.18.2.5 Limits of greatest-width integer types | ||||
| #define INTMAX_MIN  INT64_MIN | ||||
| #define INTMAX_MAX  INT64_MAX | ||||
| #define UINTMAX_MAX UINT64_MAX | ||||
| #define INTMAX_MIN   INT64_MIN | ||||
| #define INTMAX_MAX   INT64_MAX | ||||
| #define UINTMAX_MAX  UINT64_MAX | ||||
|  | ||||
| // 7.18.3 Limits of other integer types | ||||
|  | ||||
| #ifdef _WIN64 // [ | ||||
| #define PTRDIFF_MIN _I64_MIN | ||||
| #define PTRDIFF_MAX _I64_MAX | ||||
| #else // _WIN64 ][ | ||||
| #define PTRDIFF_MIN _I32_MIN | ||||
| #define PTRDIFF_MAX _I32_MAX | ||||
| #endif // _WIN64 ] | ||||
| #  define PTRDIFF_MIN  _I64_MIN | ||||
| #  define PTRDIFF_MAX  _I64_MAX | ||||
| #else  // _WIN64 ][ | ||||
| #  define PTRDIFF_MIN  _I32_MIN | ||||
| #  define PTRDIFF_MAX  _I32_MAX | ||||
| #endif  // _WIN64 ] | ||||
|  | ||||
| #define SIG_ATOMIC_MIN INT_MIN | ||||
| #define SIG_ATOMIC_MAX INT_MAX | ||||
| #define SIG_ATOMIC_MIN  INT_MIN | ||||
| #define SIG_ATOMIC_MAX  INT_MAX | ||||
|  | ||||
| #ifndef SIZE_MAX // [ | ||||
| #ifdef _WIN64    // [ | ||||
| #define SIZE_MAX _UI64_MAX | ||||
| #else // _WIN64 ][ | ||||
| #define SIZE_MAX _UI32_MAX | ||||
| #endif            // _WIN64 ] | ||||
| #endif            // SIZE_MAX ] | ||||
| #  ifdef _WIN64 // [ | ||||
| #     define SIZE_MAX  _UI64_MAX | ||||
| #  else // _WIN64 ][ | ||||
| #     define SIZE_MAX  _UI32_MAX | ||||
| #  endif // _WIN64 ] | ||||
| #endif // SIZE_MAX ] | ||||
|  | ||||
| // WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> | ||||
| #ifndef WCHAR_MIN // [ | ||||
| #define WCHAR_MIN 0 | ||||
| #endif            // WCHAR_MIN ] | ||||
| #  define WCHAR_MIN  0 | ||||
| #endif  // WCHAR_MIN ] | ||||
| #ifndef WCHAR_MAX // [ | ||||
| #define WCHAR_MAX _UI16_MAX | ||||
| #endif // WCHAR_MAX ] | ||||
| #  define WCHAR_MAX  _UI16_MAX | ||||
| #endif  // WCHAR_MAX ] | ||||
|  | ||||
| #define WINT_MIN 0 | ||||
| #define WINT_MAX _UI16_MAX | ||||
| #define WINT_MIN  0 | ||||
| #define WINT_MAX  _UI16_MAX | ||||
|  | ||||
| #endif // __STDC_LIMIT_MACROS ] | ||||
|  | ||||
| @@ -287,10 +287,10 @@ typedef uint64_t uintmax_t; | ||||
| // These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. | ||||
| // Check out Issue 9 for the details. | ||||
| #ifndef INTMAX_C //   [ | ||||
| #define INTMAX_C INT64_C | ||||
| #endif            // INTMAX_C    ] | ||||
| #  define INTMAX_C   INT64_C | ||||
| #endif // INTMAX_C    ] | ||||
| #ifndef UINTMAX_C //  [ | ||||
| #define UINTMAX_C UINT64_C | ||||
| #  define UINTMAX_C  UINT64_C | ||||
| #endif // UINTMAX_C   ] | ||||
|  | ||||
| #endif // __STDC_CONSTANT_MACROS ] | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_OSTREAMWRAPPER_H_ | ||||
| @@ -40,7 +40,7 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
|     \tparam StreamType Class derived from \c std::basic_ostream. | ||||
| */ | ||||
|  | ||||
|     | ||||
| template <typename StreamType> | ||||
| class BasicOStreamWrapper { | ||||
| public: | ||||
| @@ -56,26 +56,11 @@ public: | ||||
|     } | ||||
|  | ||||
|     // Not implemented | ||||
|     char Peek() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char Take() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t Tell() const { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(char*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     char Peek() const { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     char Take() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
| private: | ||||
|     BasicOStreamWrapper(const BasicOStreamWrapper&); | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_POINTER_H_ | ||||
| @@ -20,7 +20,7 @@ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(switch - enum) | ||||
| RAPIDJSON_DIAG_OFF(switch-enum) | ||||
| #elif defined(_MSC_VER) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated | ||||
| @@ -28,19 +28,19 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
| static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token | ||||
| 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 | ||||
|     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 | ||||
|     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 | ||||
| }; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -78,8 +78,8 @@ enum PointerParseErrorCode { | ||||
| template <typename ValueType, typename Allocator = CrtAllocator> | ||||
| class GenericPointer { | ||||
| public: | ||||
|     typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value | ||||
|     typedef typename ValueType::Ch Ch;                     //!< Character type from Value | ||||
|     typedef typename ValueType::EncodingType EncodingType;  //!< Encoding type from Value | ||||
|     typedef typename ValueType::Ch Ch;                      //!< Character type from Value | ||||
|  | ||||
|     //! A token is the basic units of internal representation. | ||||
|     /*! | ||||
| @@ -95,9 +95,9 @@ public: | ||||
|         allocation, using a special constructor. | ||||
|     */ | ||||
|     struct Token { | ||||
|         const Ch* name;  //!< Name of the token. It has null character at the end but it can contain null character. | ||||
|         SizeType length; //!< Length of the name. | ||||
|         SizeType index;  //!< A valid array index, if it is not equal to kPointerInvalidIndex. | ||||
|         const Ch* name;             //!< Name of the token. It has null character at the end but it can contain null character. | ||||
|         SizeType length;            //!< Length of the name. | ||||
|         SizeType index;             //!< A valid array index, if it is not equal to kPointerInvalidIndex. | ||||
|     }; | ||||
|  | ||||
|     //!@name Constructors and destructor. | ||||
| @@ -174,7 +174,7 @@ public: | ||||
|  | ||||
|     //! Destructor. | ||||
|     ~GenericPointer() { | ||||
|         if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. | ||||
|         if (nameBuffer_)    // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. | ||||
|             Allocator::Free(tokens_); | ||||
|         RAPIDJSON_DELETE(ownAllocator_); | ||||
|     } | ||||
| @@ -244,7 +244,7 @@ public: | ||||
|     GenericPointer Append(const Token& token, Allocator* allocator = 0) const { | ||||
|         GenericPointer r; | ||||
|         r.allocator_ = allocator; | ||||
|         Ch* p = r.CopyFromRaw(*this, 1, token.length + 1); | ||||
|         Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); | ||||
|         std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); | ||||
|         r.tokens_[tokenCount_].name = p; | ||||
|         r.tokens_[tokenCount_].length = token.length; | ||||
| @@ -271,7 +271,7 @@ public: | ||||
|         \return A new Pointer with appended token. | ||||
|     */ | ||||
|     template <typename T> | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (GenericPointer)) | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer)) | ||||
|     Append(T* name, Allocator* allocator = 0) const { | ||||
|         return Append(name, internal::StrLen(name), allocator); | ||||
|     } | ||||
| @@ -370,8 +370,9 @@ public: | ||||
|  | ||||
|         for (size_t i = 0; i < tokenCount_; i++) { | ||||
|             if (tokens_[i].index != rhs.tokens_[i].index || | ||||
|                 tokens_[i].length != rhs.tokens_[i].length || | ||||
|                 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length) != 0)) { | ||||
|                 tokens_[i].length != rhs.tokens_[i].length ||  | ||||
|                 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| @@ -422,7 +423,7 @@ public: | ||||
|         \tparam OutputStream Type of output stream. | ||||
|         \param os The output stream. | ||||
|     */ | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     bool Stringify(OutputStream& os) const { | ||||
|         return Stringify<false, OutputStream>(os); | ||||
|     } | ||||
| @@ -432,7 +433,7 @@ public: | ||||
|         \tparam OutputStream Type of output stream. | ||||
|         \param os The output stream. | ||||
|     */ | ||||
|     template <typename OutputStream> | ||||
|     template<typename OutputStream> | ||||
|     bool StringifyUriFragment(OutputStream& os) const { | ||||
|         return Stringify<true, OutputStream>(os); | ||||
|     } | ||||
| @@ -461,7 +462,7 @@ public: | ||||
|         RAPIDJSON_ASSERT(IsValid()); | ||||
|         ValueType* v = &root; | ||||
|         bool exist = true; | ||||
|         for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|         for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|             if (v->IsArray() && t->name[0] == '-' && t->length == 1) { | ||||
|                 v->PushBack(ValueType().Move(), allocator); | ||||
|                 v = &((*v)[v->Size() - 1]); | ||||
| @@ -539,14 +540,15 @@ public: | ||||
|     ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { | ||||
|         RAPIDJSON_ASSERT(IsValid()); | ||||
|         ValueType* v = &root; | ||||
|         for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|         for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|             switch (v->GetType()) { | ||||
|             case kObjectType: { | ||||
|                 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); | ||||
|                 if (m == v->MemberEnd()) | ||||
|                     break; | ||||
|                 v = &m->value; | ||||
|             } | ||||
|             case kObjectType: | ||||
|                 { | ||||
|                     typename ValueType::MemberIterator 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()) | ||||
| @@ -570,7 +572,7 @@ public: | ||||
|         \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. | ||||
|         \return Pointer to the value if it can be resolved. Otherwise null. | ||||
|     */ | ||||
|     const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { | ||||
|     const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {  | ||||
|         return Get(const_cast<ValueType&>(root), unresolvedTokenIndex); | ||||
|     } | ||||
|  | ||||
| @@ -616,7 +618,7 @@ public: | ||||
|         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool | ||||
|     */ | ||||
|     template <typename T> | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) | ||||
|     GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { | ||||
|         return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); | ||||
|     } | ||||
| @@ -632,7 +634,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> | ||||
| @@ -646,7 +648,7 @@ public: | ||||
|         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool | ||||
|     */ | ||||
|     template <typename T, typename stackAllocator> | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) | ||||
|     GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const { | ||||
|         return GetWithDefault(document, defaultValue, document.GetAllocator()); | ||||
|     } | ||||
| @@ -692,7 +694,7 @@ public: | ||||
|         \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool | ||||
|     */ | ||||
|     template <typename T> | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) | ||||
|     Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { | ||||
|         return Create(root, allocator) = ValueType(value).Move(); | ||||
|     } | ||||
| @@ -728,9 +730,9 @@ public: | ||||
|     \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool | ||||
|     */ | ||||
|     template <typename T, typename stackAllocator> | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) | ||||
|     Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const { | ||||
|         return Create(document) = value; | ||||
|     RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) | ||||
|         Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const { | ||||
|             return Create(document) = value; | ||||
|     } | ||||
|  | ||||
|     //@} | ||||
| @@ -774,14 +776,16 @@ public: | ||||
|  | ||||
|         ValueType* v = &root; | ||||
|         const Token* last = tokens_ + (tokenCount_ - 1); | ||||
|         for (const Token* t = tokens_; t != last; ++t) { | ||||
|         for (const Token *t = tokens_; t != last; ++t) { | ||||
|             switch (v->GetType()) { | ||||
|             case kObjectType: { | ||||
|                 typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); | ||||
|                 if (m == v->MemberEnd()) | ||||
|                     return false; | ||||
|                 v = &m->value; | ||||
|             } break; | ||||
|             case kObjectType: | ||||
|                 { | ||||
|                     typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); | ||||
|                     if (m == v->MemberEnd()) | ||||
|                         return false; | ||||
|                     v = &m->value; | ||||
|                 } | ||||
|                 break; | ||||
|             case kArrayType: | ||||
|                 if (t->index == kPointerInvalidIndex || t->index >= v->Size()) | ||||
|                     return false; | ||||
| @@ -818,12 +822,12 @@ private: | ||||
|             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) | ||||
|         for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) | ||||
|             nameBufferSize += t->length; | ||||
|  | ||||
|         tokenCount_ = rhs.tokenCount_ + extraToken; | ||||
|         tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); | ||||
|         nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_); | ||||
|         tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); | ||||
|         nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); | ||||
|         if (rhs.tokenCount_ > 0) { | ||||
|             std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); | ||||
|         } | ||||
| @@ -833,7 +837,7 @@ private: | ||||
|  | ||||
|         // Adjust pointers to name buffer | ||||
|         std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; | ||||
|         for (Token* t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) | ||||
|         for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) | ||||
|             t->name += diff; | ||||
|  | ||||
|         return nameBuffer_ + nameBufferSize; | ||||
| @@ -845,7 +849,7 @@ private: | ||||
|         \param c The character (code unit) to be tested. | ||||
|     */ | ||||
|     bool NeedPercentEncode(Ch c) const { | ||||
|         return !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c == '~'); | ||||
|         return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); | ||||
|     } | ||||
|  | ||||
|     //! Parse a JSON String or its URI fragment representation into tokens. | ||||
| @@ -867,12 +871,12 @@ private: | ||||
|  | ||||
|         // Count number of '/' as tokenCount | ||||
|         tokenCount_ = 0; | ||||
|         for (const Ch* s = source; s != source + length; s++) | ||||
|         for (const Ch* s = source; s != source + length; s++)  | ||||
|             if (*s == '/') | ||||
|                 tokenCount_++; | ||||
|  | ||||
|         Token* token = tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); | ||||
|         Ch* name = nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_); | ||||
|         Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); | ||||
|         Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); | ||||
|         size_t i = 0; | ||||
|  | ||||
|         // Detect if it is a URI fragment | ||||
| @@ -924,15 +928,13 @@ private: | ||||
|                 } | ||||
|  | ||||
|                 i++; | ||||
|  | ||||
|                  | ||||
|                 // Escaping "~0" -> '~', "~1" -> '/' | ||||
|                 if (c == '~') { | ||||
|                     if (i < length) { | ||||
|                         c = source[i]; | ||||
|                         if (c == '0') | ||||
|                             c = '~'; | ||||
|                         else if (c == '1') | ||||
|                             c = '/'; | ||||
|                         if (c == '0')       c = '~'; | ||||
|                         else if (c == '1')  c = '/'; | ||||
|                         else { | ||||
|                             parseErrorCode_ = kPointerParseErrorInvalidEscape; | ||||
|                             goto error; | ||||
| @@ -965,7 +967,7 @@ private: | ||||
|             if (isNumber) { | ||||
|                 for (size_t j = 0; j < token->length; j++) { | ||||
|                     SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0'); | ||||
|                     if (m < n) { // overflow detection | ||||
|                     if (m < n) {   // overflow detection | ||||
|                         isNumber = false; | ||||
|                         break; | ||||
|                     } | ||||
| @@ -996,14 +998,14 @@ private: | ||||
|         \tparam OutputStream type of output stream. | ||||
|         \param os The output stream. | ||||
|     */ | ||||
|     template <bool uriFragment, typename OutputStream> | ||||
|     template<bool uriFragment, typename OutputStream> | ||||
|     bool Stringify(OutputStream& os) const { | ||||
|         RAPIDJSON_ASSERT(IsValid()); | ||||
|  | ||||
|         if (uriFragment) | ||||
|             os.Put('#'); | ||||
|  | ||||
|         for (Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|         for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { | ||||
|             os.Put('/'); | ||||
|             for (size_t j = 0; j < t->length; j++) { | ||||
|                 Ch c = t->name[j]; | ||||
| @@ -1015,11 +1017,11 @@ private: | ||||
|                     os.Put('~'); | ||||
|                     os.Put('1'); | ||||
|                 } | ||||
|                 else if (uriFragment && NeedPercentEncode(c)) { | ||||
|                 else if (uriFragment && NeedPercentEncode(c)) {  | ||||
|                     // Transcode to UTF8 sequence | ||||
|                     GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]); | ||||
|                     PercentEncodeStream<OutputStream> target(os); | ||||
|                     if (!Transcoder<EncodingType, UTF8<>>().Validate(source, target)) | ||||
|                     if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target)) | ||||
|                         return false; | ||||
|                     j += source.Tell() - 1; | ||||
|                 } | ||||
| @@ -1057,12 +1059,9 @@ private: | ||||
|             for (int j = 0; j < 2; j++) { | ||||
|                 c = static_cast<Ch>(c << 4); | ||||
|                 Ch h = *src_; | ||||
|                 if (h >= '0' && h <= '9') | ||||
|                     c = static_cast<Ch>(c + h - '0'); | ||||
|                 else if (h >= 'A' && h <= 'F') | ||||
|                     c = static_cast<Ch>(c + h - 'A' + 10); | ||||
|                 else if (h >= 'a' && h <= 'f') | ||||
|                     c = static_cast<Ch>(c + h - 'a' + 10); | ||||
|                 if      (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0'); | ||||
|                 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); | ||||
|                 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10); | ||||
|                 else { | ||||
|                     valid_ = false; | ||||
|                     return 0; | ||||
| @@ -1076,10 +1075,10 @@ private: | ||||
|         bool IsValid() const { return valid_; } | ||||
|  | ||||
|     private: | ||||
|         const Ch* src_;  //!< Current read position. | ||||
|         const Ch* head_; //!< Original head of the string. | ||||
|         const Ch* end_;  //!< Past-the-end position. | ||||
|         bool valid_;     //!< Whether the parsing is valid. | ||||
|         const Ch* src_;     //!< Current read position. | ||||
|         const Ch* head_;    //!< Original head of the string. | ||||
|         const Ch* end_;     //!< Past-the-end position. | ||||
|         bool valid_;        //!< Whether the parsing is valid. | ||||
|     }; | ||||
|  | ||||
|     //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. | ||||
| @@ -1094,18 +1093,17 @@ private: | ||||
|             os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4])); | ||||
|             os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15])); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         OutputStream& os_; | ||||
|     }; | ||||
|  | ||||
|     Allocator* allocator_;                 //!< The current allocator. It is either user-supplied or equal to ownAllocator_. | ||||
|     Allocator* ownAllocator_;              //!< Allocator owned by this Pointer. | ||||
|     Ch* nameBuffer_;                       //!< A buffer containing all names in tokens. | ||||
|     Token* tokens_;                        //!< A list of tokens. | ||||
|     size_t tokenCount_;                    //!< Number of tokens in tokens_. | ||||
|     size_t parseErrorOffset_;              //!< Offset in code unit when parsing fail. | ||||
|     PointerParseErrorCode parseErrorCode_; //!< Parsing error code. | ||||
|     Allocator* allocator_;                  //!< The current allocator. It is either user-supplied or equal to ownAllocator_. | ||||
|     Allocator* ownAllocator_;               //!< Allocator owned by this Pointer. | ||||
|     Ch* nameBuffer_;                        //!< A buffer containing all names in tokens. | ||||
|     Token* tokens_;                         //!< A list of tokens. | ||||
|     size_t tokenCount_;                     //!< Number of tokens in tokens_. | ||||
|     size_t parseErrorOffset_;               //!< Offset in code unit when parsing fail. | ||||
|     PointerParseErrorCode parseErrorCode_;  //!< Parsing error code. | ||||
| }; | ||||
|  | ||||
| //! GenericPointer for Value (UTF-8, default allocator). | ||||
| @@ -1122,7 +1120,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typena | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& CreateValueByPointer(T& root, const CharType (&source)[N], typename T::AllocatorType& a) { | ||||
| typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a); | ||||
| } | ||||
|  | ||||
| @@ -1134,7 +1132,7 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType (&source)[N]) { | ||||
| typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document); | ||||
| } | ||||
|  | ||||
| @@ -1156,7 +1154,7 @@ typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], s | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| const typename T::ValueType* GetValueByPointer(const T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { | ||||
| const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); | ||||
| } | ||||
|  | ||||
| @@ -1180,31 +1178,31 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) | ||||
| GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) { | ||||
|     return pointer.GetWithDefault(root, defaultValue, a); | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); | ||||
| } | ||||
|  | ||||
| #if RAPIDJSON_HAS_STDSTRING | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename CharType, size_t N, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) | ||||
| GetValueByPointerWithDefault(T& root, const CharType (&source)[N], T2 defaultValue, typename T::AllocatorType& a) { | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) | ||||
| GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); | ||||
| } | ||||
|  | ||||
| @@ -1228,31 +1226,31 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc | ||||
| #endif | ||||
|  | ||||
| template <typename DocumentType, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) | ||||
| GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) { | ||||
|     return pointer.GetWithDefault(document, defaultValue); | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& defaultValue) { | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* defaultValue) { | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); | ||||
| } | ||||
|  | ||||
| #if RAPIDJSON_HAS_STDSTRING | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { | ||||
| typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) | ||||
| GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], T2 defaultValue) { | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) | ||||
| GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); | ||||
| } | ||||
|  | ||||
| @@ -1281,36 +1279,36 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) | ||||
| SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) { | ||||
|     return pointer.Set(root, value, a); | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); | ||||
| } | ||||
|  | ||||
| #if RAPIDJSON_HAS_STDSTRING | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename CharType, size_t N, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) | ||||
| SetValueByPointer(T& root, const CharType (&source)[N], T2 value, typename T::AllocatorType& a) { | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) | ||||
| SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); | ||||
| } | ||||
|  | ||||
| @@ -1339,36 +1337,36 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons | ||||
| #endif | ||||
|  | ||||
| template <typename DocumentType, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) | ||||
| SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) { | ||||
|     return pointer.Set(document, value); | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) { | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& value) { | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* value) { | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); | ||||
| } | ||||
|  | ||||
| #if RAPIDJSON_HAS_STDSTRING | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { | ||||
| typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N, typename T2> | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) | ||||
| SetValueByPointer(DocumentType& document, const CharType (&source)[N], T2 value) { | ||||
| RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) | ||||
| SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); | ||||
| } | ||||
|  | ||||
| @@ -1380,7 +1378,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| typename T::ValueType& SwapValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
| typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a); | ||||
| } | ||||
|  | ||||
| @@ -1390,7 +1388,7 @@ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, con | ||||
| } | ||||
|  | ||||
| template <typename DocumentType, typename CharType, size_t N> | ||||
| typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) { | ||||
| typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { | ||||
|     return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value); | ||||
| } | ||||
|  | ||||
| @@ -1402,7 +1400,7 @@ bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& p | ||||
| } | ||||
|  | ||||
| template <typename T, typename CharType, size_t N> | ||||
| bool EraseValueByPointer(T& root, const CharType (&source)[N]) { | ||||
| bool EraseValueByPointer(T& root, const CharType(&source)[N]) { | ||||
|     return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_PRETTYWRITER_H_ | ||||
| @@ -24,7 +24,7 @@ RAPIDJSON_DIAG_OFF(effc++) | ||||
|  | ||||
| #if defined(__clang__) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(c++ 98 - compat) | ||||
| RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -33,8 +33,8 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
| /*! \see PrettyWriter::SetFormatOptions | ||||
|  */ | ||||
| enum PrettyFormatOptions { | ||||
|     kFormatDefault = 0,        //!< Default pretty formatting. | ||||
|     kFormatSingleLineArray = 1 //!< Format arrays on a single line. | ||||
|     kFormatDefault = 0,         //!< Default pretty formatting. | ||||
|     kFormatSingleLineArray = 1  //!< Format arrays on a single line. | ||||
| }; | ||||
|  | ||||
| //! Writer with indentation and spacing. | ||||
| @@ -44,7 +44,7 @@ enum PrettyFormatOptions { | ||||
|     \tparam TargetEncoding Encoding of output stream. | ||||
|     \tparam StackAllocator Type of allocator for allocating memory of stack. | ||||
| */ | ||||
| template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> | ||||
| template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> | ||||
| class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { | ||||
| public: | ||||
|     typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base; | ||||
| @@ -55,13 +55,16 @@ public: | ||||
|         \param allocator User supplied allocator. If it is null, it will create a private one. | ||||
|         \param levelDepth Initial capacity of stack. | ||||
|     */ | ||||
|     explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} | ||||
|     explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :  | ||||
|         Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} | ||||
|  | ||||
|  | ||||
|     explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} | ||||
|     explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :  | ||||
|         Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|     PrettyWriter(PrettyWriter&& rhs) : Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} | ||||
|     PrettyWriter(PrettyWriter&& rhs) : | ||||
|         Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} | ||||
| #endif | ||||
|  | ||||
|     //! Set custom indentation. | ||||
| @@ -89,34 +92,13 @@ public: | ||||
|     */ | ||||
|     //@{ | ||||
|  | ||||
|     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 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); | ||||
| @@ -151,13 +133,13 @@ public: | ||||
|         return Key(str.data(), SizeType(str.size())); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| 	 | ||||
|     bool EndObject(SizeType memberCount = 0) { | ||||
|         (void)memberCount; | ||||
|         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(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) { | ||||
| @@ -240,7 +222,7 @@ protected: | ||||
|                     WriteIndent(); | ||||
|                 } | ||||
|             } | ||||
|             else { // in object | ||||
|             else {  // in object | ||||
|                 if (level->valueCount > 0) { | ||||
|                     if (level->valueCount % 2 == 0) { | ||||
|                         Base::os_->Put(','); | ||||
| @@ -258,16 +240,16 @@ protected: | ||||
|                     WriteIndent(); | ||||
|             } | ||||
|             if (!level->inArray && level->valueCount % 2 == 0) | ||||
|                 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name | ||||
|                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name | ||||
|             level->valueCount++; | ||||
|         } | ||||
|         else { | ||||
|             RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. | ||||
|             RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root. | ||||
|             Base::hasRoot_ = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void WriteIndent() { | ||||
|     void WriteIndent()  { | ||||
|         size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; | ||||
|         PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count); | ||||
|     } | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_RAPIDJSON_H_ | ||||
| @@ -36,8 +36,8 @@ | ||||
|           different translation units of a single application. | ||||
|  */ | ||||
|  | ||||
| #include <cstdlib> // malloc(), realloc(), free(), size_t | ||||
| #include <cstring> // memset(), memcpy(), memmove(), memcmp() | ||||
| #include <cstdlib>  // malloc(), realloc(), free(), size_t | ||||
| #include <cstring>  // memset(), memcpy(), memmove(), memcmp() | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // RAPIDJSON_VERSION_STRING | ||||
| @@ -47,12 +47,12 @@ | ||||
|  | ||||
| //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN | ||||
| // token stringification | ||||
| #define RAPIDJSON_STRINGIFY(x)    RAPIDJSON_DO_STRINGIFY(x) | ||||
| #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_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 | ||||
|  | ||||
| @@ -195,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 | ||||
| @@ -226,8 +226,8 @@ | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // RAPIDJSON_ENDIAN | ||||
| #define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine | ||||
| #define RAPIDJSON_BIGENDIAN    1 //!< Big endian machine | ||||
| #define RAPIDJSON_LITTLEENDIAN  0   //!< Little endian machine | ||||
| #define RAPIDJSON_BIGENDIAN     1   //!< Big endian machine | ||||
|  | ||||
| //! Endianness of the machine. | ||||
| /*! | ||||
| @@ -244,41 +244,41 @@ | ||||
| */ | ||||
| #ifndef RAPIDJSON_ENDIAN | ||||
| // Detect with GCC 4.6's macro | ||||
| #ifdef __BYTE_ORDER__ | ||||
| #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #else | ||||
| #error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. | ||||
| #endif // __BYTE_ORDER__ | ||||
| #  ifdef __BYTE_ORDER__ | ||||
| #    if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||||
| #      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | ||||
| #      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #    else | ||||
| #      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. | ||||
| #    endif // __BYTE_ORDER__ | ||||
| // Detect with GLIBC's endian.h | ||||
| #elif defined(__GLIBC__) | ||||
| #include <endian.h> | ||||
| #if (__BYTE_ORDER == __LITTLE_ENDIAN) | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #elif (__BYTE_ORDER == __BIG_ENDIAN) | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #else | ||||
| #error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. | ||||
| #endif // __GLIBC__ | ||||
| #  elif defined(__GLIBC__) | ||||
| #    include <endian.h> | ||||
| #    if (__BYTE_ORDER == __LITTLE_ENDIAN) | ||||
| #      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #    elif (__BYTE_ORDER == __BIG_ENDIAN) | ||||
| #      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #    else | ||||
| #      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) | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) | ||||
| #    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #  elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) | ||||
| #    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| // Detect with architecture macros | ||||
| #elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) | ||||
| #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) || defined(_M_ARM64)) | ||||
| #define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #elif defined(RAPIDJSON_DOXYGEN_RUNNING) | ||||
| #define RAPIDJSON_ENDIAN | ||||
| #else | ||||
| #error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. | ||||
| #endif | ||||
| #  elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) | ||||
| #    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN | ||||
| #  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) || defined(_M_ARM64)) | ||||
| #    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN | ||||
| #  elif defined(RAPIDJSON_DOXYGEN_RUNNING) | ||||
| #    define RAPIDJSON_ENDIAN | ||||
| #  else | ||||
| #    error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.    | ||||
| #  endif | ||||
| #endif // RAPIDJSON_ENDIAN | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -343,11 +343,11 @@ | ||||
| #if RAPIDJSON_64BIT != 1 | ||||
| #error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 | ||||
| #endif | ||||
| #define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type*>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) | ||||
| #define RAPIDJSON_GETPOINTER(type, p)    (reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) | ||||
| #define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) | ||||
| #define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) | ||||
| #else | ||||
| #define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) | ||||
| #define RAPIDJSON_GETPOINTER(type, p)    (p) | ||||
| #define RAPIDJSON_GETPOINTER(type, p) (p) | ||||
| #endif | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -379,7 +379,8 @@ | ||||
|     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_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) | ||||
| #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ | ||||
|     || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) | ||||
| #define RAPIDJSON_SIMD | ||||
| #endif | ||||
|  | ||||
| @@ -441,9 +442,9 @@ RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
| // Prefer C++11 static_assert, if available | ||||
| #ifndef RAPIDJSON_STATIC_ASSERT | ||||
| #if RAPIDJSON_CPLUSPLUS >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) | ||||
| #if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) | ||||
| #define RAPIDJSON_STATIC_ASSERT(x) \ | ||||
|     static_assert(x, RAPIDJSON_STRINGIFY(x)) | ||||
|    static_assert(x, RAPIDJSON_STRINGIFY(x)) | ||||
| #endif // C++11 | ||||
| #endif // RAPIDJSON_STATIC_ASSERT | ||||
|  | ||||
| @@ -453,20 +454,15 @@ RAPIDJSON_NAMESPACE_END | ||||
| //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN | ||||
| #endif | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| template <bool x> | ||||
| struct STATIC_ASSERTION_FAILURE; | ||||
| template <> | ||||
| struct STATIC_ASSERTION_FAILURE<true> { | ||||
|     enum { value = 1 }; | ||||
| }; | ||||
| template <size_t x> | ||||
| struct StaticAssertTest {}; | ||||
| template <bool x> struct STATIC_ASSERTION_FAILURE; | ||||
| template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; | ||||
| template <size_t x> struct StaticAssertTest {}; | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
| #if defined(__GNUC__) || defined(__clang__) | ||||
| #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) | ||||
| #else | ||||
| #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE | ||||
| #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE  | ||||
| #endif | ||||
| #ifndef __clang__ | ||||
| //!@endcond | ||||
| @@ -477,10 +473,10 @@ RAPIDJSON_NAMESPACE_END | ||||
|     \param x compile-time condition | ||||
|     \hideinitializer | ||||
|  */ | ||||
| #define RAPIDJSON_STATIC_ASSERT(x)                                        \ | ||||
|     typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest<                      \ | ||||
|         sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x)>)> \ | ||||
|         RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE | ||||
| #define RAPIDJSON_STATIC_ASSERT(x) \ | ||||
|     typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ | ||||
|       sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \ | ||||
|     RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE | ||||
| #endif // RAPIDJSON_STATIC_ASSERT | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -517,14 +513,13 @@ 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) | ||||
| } while((void)0, 0) | ||||
|  | ||||
| // adopted from Boost | ||||
| #define RAPIDJSON_VERSION_CODE(x, y, z) \ | ||||
|     (((x)*100000) + ((y)*100) + (z)) | ||||
| #define RAPIDJSON_VERSION_CODE(x,y,z) \ | ||||
|   (((x)*100000) + ((y)*100) + (z)) | ||||
|  | ||||
| #if defined(__has_builtin) | ||||
| #define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x) | ||||
| @@ -537,33 +532,32 @@ RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| #define RAPIDJSON_GNUC \ | ||||
|     RAPIDJSON_VERSION_CODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) | ||||
|     RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) | ||||
| #endif | ||||
|  | ||||
| #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 2, 0)) | ||||
| #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) | ||||
|  | ||||
| #define RAPIDJSON_PRAGMA(x)      _Pragma(RAPIDJSON_STRINGIFY(x)) | ||||
| #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) | ||||
| #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) | ||||
| #define RAPIDJSON_DIAG_OFF(x) \ | ||||
|     RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W, x))) | ||||
|     RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) | ||||
|  | ||||
| // push/pop support in Clang and GCC>=4.6 | ||||
| #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) | ||||
| #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) | ||||
| #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) | ||||
| #define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop) | ||||
| #else                       // GCC >= 4.2, < 4.6 | ||||
| #else // GCC >= 4.2, < 4.6 | ||||
| #define RAPIDJSON_DIAG_PUSH /* ignored */ | ||||
| #define RAPIDJSON_DIAG_POP  /* ignored */ | ||||
| #define RAPIDJSON_DIAG_POP /* ignored */ | ||||
| #endif | ||||
|  | ||||
| #elif defined(_MSC_VER) | ||||
|  | ||||
| // pragma (MSVC specific) | ||||
| #define RAPIDJSON_PRAGMA(x)      __pragma(x) | ||||
| #define RAPIDJSON_PRAGMA(x) __pragma(x) | ||||
| #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) | ||||
|  | ||||
| #define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable \ | ||||
|                                                     : x) | ||||
| #define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) | ||||
| #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) | ||||
| #define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop) | ||||
|  | ||||
| @@ -592,9 +586,9 @@ RAPIDJSON_NAMESPACE_END | ||||
| #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(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) | ||||
| #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ | ||||
|       (defined(_MSC_VER) && _MSC_VER >= 1600) || \ | ||||
|       (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) | ||||
|  | ||||
| #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 | ||||
| #else | ||||
| @@ -611,8 +605,8 @@ RAPIDJSON_NAMESPACE_END | ||||
| #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 >= 1900) ||                                                                                   \ | ||||
| #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 | ||||
| @@ -639,9 +633,9 @@ RAPIDJSON_NAMESPACE_END | ||||
| #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, 6, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ | ||||
|     (defined(_MSC_VER) && _MSC_VER >= 1700) ||                                                                                   \ | ||||
|     (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) | ||||
| #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ | ||||
|       (defined(_MSC_VER) && _MSC_VER >= 1700) || \ | ||||
|       (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) | ||||
| #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 | ||||
| #else | ||||
| #define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 | ||||
| @@ -656,23 +650,23 @@ RAPIDJSON_NAMESPACE_END | ||||
| #endif | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX17 | ||||
| #define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] | ||||
| # 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)) | ||||
| # 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 | ||||
| #else | ||||
| #define RAPIDJSON_DELIBERATE_FALLTHROUGH | ||||
| # define RAPIDJSON_DELIBERATE_FALLTHROUGH | ||||
| #endif | ||||
|  | ||||
| //!@endcond | ||||
|  | ||||
| //! Assertion (in non-throwing contexts). | ||||
| /*! \ingroup RAPIDJSON_CONFIG | ||||
|  /*! \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 | ||||
| @@ -733,13 +727,13 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
| //! Type of JSON value | ||||
| enum Type { | ||||
|     kNullType = 0,   //!< null | ||||
|     kFalseType = 1,  //!< false | ||||
|     kTrueType = 2,   //!< true | ||||
|     kObjectType = 3, //!< object | ||||
|     kArrayType = 4,  //!< array | ||||
|     kStringType = 5, //!< string | ||||
|     kNumberType = 6  //!< number | ||||
|     kNullType = 0,      //!< null | ||||
|     kFalseType = 1,     //!< false | ||||
|     kTrueType = 2,      //!< true | ||||
|     kObjectType = 3,    //!< object | ||||
|     kArrayType = 4,     //!< array  | ||||
|     kStringType = 5,    //!< string | ||||
|     kNumberType = 6     //!< number | ||||
| }; | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -69,7 +69,7 @@ concept Stream { | ||||
|     For custom stream, this type can be specialized for other configuration. | ||||
|     See TEST(Reader, CustomStringStream) in readertest.cpp for example. | ||||
| */ | ||||
| template <typename Stream> | ||||
| template<typename Stream> | ||||
| struct StreamTraits { | ||||
|     //! Whether to make local copy of stream for optimization during parsing. | ||||
|     /*! | ||||
| @@ -80,20 +80,20 @@ struct StreamTraits { | ||||
| }; | ||||
|  | ||||
| //! Reserve n characters for writing to a stream. | ||||
| template <typename Stream> | ||||
| template<typename Stream> | ||||
| inline void PutReserve(Stream& stream, size_t count) { | ||||
|     (void)stream; | ||||
|     (void)count; | ||||
| } | ||||
|  | ||||
| //! Write character to a stream, presuming buffer is reserved. | ||||
| template <typename Stream> | ||||
| template<typename Stream> | ||||
| inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { | ||||
|     stream.Put(c); | ||||
| } | ||||
|  | ||||
| //! Put N copies of a character to a stream. | ||||
| template <typename Stream, typename Ch> | ||||
| template<typename Stream, typename Ch> | ||||
| inline void PutN(Stream& stream, Ch c, size_t n) { | ||||
|     PutReserve(stream, n); | ||||
|     for (size_t i = 0; i < n; i++) | ||||
| @@ -111,15 +111,15 @@ inline void PutN(Stream& stream, Ch c, size_t n) { | ||||
|  | ||||
| #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 | ||||
| RAPIDJSON_DIAG_OFF(4702)  // unreachable code | ||||
| RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated | ||||
| #endif | ||||
|  | ||||
| template <typename InputStream, typename Encoding = UTF8<>> | ||||
| template <typename InputStream, typename Encoding = UTF8<> > | ||||
| class GenericStreamWrapper { | ||||
| public: | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|     GenericStreamWrapper(InputStream& is) : is_(is) {} | ||||
|     GenericStreamWrapper(InputStream& is): is_(is) {} | ||||
|  | ||||
|     Ch Peek() const { return is_.Peek(); } | ||||
|     Ch Take() { return is_.Take(); } | ||||
| @@ -154,34 +154,28 @@ template <typename Encoding> | ||||
| struct GenericStringStream { | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|  | ||||
|     GenericStringStream(const Ch* src) : src_(src), head_(src) {} | ||||
|     GenericStringStream(const Ch *src) : src_(src), head_(src) {} | ||||
|  | ||||
|     Ch Peek() const { return *src_; } | ||||
|     Ch Take() { return *src_++; } | ||||
|     size_t Tell() const { return static_cast<size_t>(src_ - head_); } | ||||
|  | ||||
|     Ch* PutBegin() { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } | ||||
|     void Put(Ch) { RAPIDJSON_ASSERT(false); } | ||||
|     void Flush() { RAPIDJSON_ASSERT(false); } | ||||
|     size_t PutEnd(Ch*) { | ||||
|         RAPIDJSON_ASSERT(false); | ||||
|         return 0; | ||||
|     } | ||||
|     size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } | ||||
|  | ||||
|     const Ch* src_;  //!< Current read position. | ||||
|     const Ch* head_; //!< Original head of the string. | ||||
|     const Ch* src_;     //!< Current read position. | ||||
|     const Ch* head_;    //!< Original head of the string. | ||||
| }; | ||||
|  | ||||
| template <typename Encoding> | ||||
| struct StreamTraits<GenericStringStream<Encoding>> { | ||||
| struct StreamTraits<GenericStringStream<Encoding> > { | ||||
|     enum { copyOptimization = 1 }; | ||||
| }; | ||||
|  | ||||
| //! String stream with UTF8 encoding. | ||||
| typedef GenericStringStream<UTF8<>> StringStream; | ||||
| typedef GenericStringStream<UTF8<> > StringStream; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| // InsituStringStream | ||||
| @@ -194,7 +188,7 @@ template <typename Encoding> | ||||
| struct GenericInsituStringStream { | ||||
|     typedef typename Encoding::Ch Ch; | ||||
|  | ||||
|     GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {} | ||||
|     GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} | ||||
|  | ||||
|     // Read | ||||
|     Ch Peek() { return *src_; } | ||||
| @@ -202,20 +196,13 @@ struct GenericInsituStringStream { | ||||
|     size_t Tell() { return static_cast<size_t>(src_ - head_); } | ||||
|  | ||||
|     // Write | ||||
|     void Put(Ch c) { | ||||
|         RAPIDJSON_ASSERT(dst_ != 0); | ||||
|         *dst_++ = c; | ||||
|     } | ||||
|     void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } | ||||
|  | ||||
|     Ch* PutBegin() { return dst_ = src_; } | ||||
|     size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); } | ||||
|     void Flush() {} | ||||
|  | ||||
|     Ch* Push(size_t count) { | ||||
|         Ch* begin = dst_; | ||||
|         dst_ += count; | ||||
|         return begin; | ||||
|     } | ||||
|     Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } | ||||
|     void Pop(size_t count) { dst_ -= count; } | ||||
|  | ||||
|     Ch* src_; | ||||
| @@ -224,12 +211,12 @@ struct GenericInsituStringStream { | ||||
| }; | ||||
|  | ||||
| template <typename Encoding> | ||||
| struct StreamTraits<GenericInsituStringStream<Encoding>> { | ||||
| struct StreamTraits<GenericInsituStringStream<Encoding> > { | ||||
|     enum { copyOptimization = 1 }; | ||||
| }; | ||||
|  | ||||
| //! Insitu string stream with UTF8 encoding. | ||||
| typedef GenericInsituStringStream<UTF8<>> InsituStringStream; | ||||
| typedef GenericInsituStringStream<UTF8<> > InsituStringStream; | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_END | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_STRINGBUFFER_H_ | ||||
| @@ -26,7 +26,7 @@ | ||||
|  | ||||
| #if defined(__clang__) | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(c++ 98 - compat) | ||||
| RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
| #endif | ||||
|  | ||||
| RAPIDJSON_NAMESPACE_BEGIN | ||||
| @@ -94,21 +94,21 @@ private: | ||||
| }; | ||||
|  | ||||
| //! String buffer with UTF8 encoding | ||||
| typedef GenericStringBuffer<UTF8<>> StringBuffer; | ||||
| typedef GenericStringBuffer<UTF8<> > StringBuffer; | ||||
|  | ||||
| template <typename Encoding, typename Allocator> | ||||
| template<typename Encoding, typename Allocator> | ||||
| inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { | ||||
|     stream.Reserve(count); | ||||
| } | ||||
|  | ||||
| template <typename Encoding, typename Allocator> | ||||
| template<typename Encoding, typename Allocator> | ||||
| inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { | ||||
|     stream.PutUnsafe(c); | ||||
| } | ||||
|  | ||||
| //! Implement specialized version of PutN() with memset() for better performance. | ||||
| template <> | ||||
| inline void PutN(GenericStringBuffer<UTF8<>>& stream, char c, size_t n) { | ||||
| template<> | ||||
| inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { | ||||
|     std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
| // | ||||
| // 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_WRITER_H_ | ||||
| @@ -23,7 +23,7 @@ | ||||
| #include "internal/dtoa.h" | ||||
| #include "internal/itoa.h" | ||||
| #include "stringbuffer.h" | ||||
| #include <new> // placement new | ||||
| #include <new>      // placement new | ||||
|  | ||||
| #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) | ||||
| #include <intrin.h> | ||||
| @@ -40,8 +40,8 @@ | ||||
| #ifdef __clang__ | ||||
| RAPIDJSON_DIAG_PUSH | ||||
| RAPIDJSON_DIAG_OFF(padded) | ||||
| RAPIDJSON_DIAG_OFF(unreachable - code) | ||||
| RAPIDJSON_DIAG_OFF(c++ 98 - compat) | ||||
| 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 | ||||
| @@ -64,10 +64,10 @@ RAPIDJSON_NAMESPACE_BEGIN | ||||
|  | ||||
| //! Combination of writeFlags | ||||
| enum WriteFlag { | ||||
|     kWriteNoFlags = 0,                                 //!< No flags are set. | ||||
|     kWriteValidateEncodingFlag = 1,                    //!< Validate encoding of JSON strings. | ||||
|     kWriteNanAndInfFlag = 2,                           //!< Allow writing of Infinity, -Infinity and NaN. | ||||
|     kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS | ||||
|     kWriteNoFlags = 0,              //!< No flags are set. | ||||
|     kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. | ||||
|     kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN. | ||||
|     kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS | ||||
| }; | ||||
|  | ||||
| //! JSON writer | ||||
| @@ -86,7 +86,7 @@ enum WriteFlag { | ||||
|     \tparam StackAllocator Type of allocator for allocating memory of stack. | ||||
|     \note implements Handler concept | ||||
| */ | ||||
| template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> | ||||
| template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> | ||||
| class Writer { | ||||
| public: | ||||
|     typedef typename SourceEncoding::Ch Ch; | ||||
| @@ -98,12 +98,17 @@ public: | ||||
|         \param stackAllocator User supplied allocator. If it is null, it will create a private one. | ||||
|         \param levelDepth Initial capacity of stack. | ||||
|     */ | ||||
|     explicit Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} | ||||
|     explicit | ||||
|     Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :  | ||||
|         os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} | ||||
|  | ||||
|     explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} | ||||
|     explicit | ||||
|     Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : | ||||
|         os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} | ||||
|  | ||||
| #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
|     Writer(Writer&& rhs) : os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { | ||||
|     Writer(Writer&& rhs) : | ||||
|         os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { | ||||
|         rhs.os_ = 0; | ||||
|     } | ||||
| #endif | ||||
| @@ -174,40 +179,19 @@ public: | ||||
|     */ | ||||
|     //@{ | ||||
|  | ||||
|     bool Null() { | ||||
|         Prefix(kNullType); | ||||
|         return EndValue(WriteNull()); | ||||
|     } | ||||
|     bool Bool(bool b) { | ||||
|         Prefix(b ? kTrueType : kFalseType); | ||||
|         return EndValue(WriteBool(b)); | ||||
|     } | ||||
|     bool Int(int i) { | ||||
|         Prefix(kNumberType); | ||||
|         return EndValue(WriteInt(i)); | ||||
|     } | ||||
|     bool Uint(unsigned u) { | ||||
|         Prefix(kNumberType); | ||||
|         return EndValue(WriteUint(u)); | ||||
|     } | ||||
|     bool Int64(int64_t i64) { | ||||
|         Prefix(kNumberType); | ||||
|         return EndValue(WriteInt64(i64)); | ||||
|     } | ||||
|     bool Uint64(uint64_t u64) { | ||||
|         Prefix(kNumberType); | ||||
|         return EndValue(WriteUint64(u64)); | ||||
|     } | ||||
|     bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); } | ||||
|     bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } | ||||
|     bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); } | ||||
|     bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); } | ||||
|     bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } | ||||
|     bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } | ||||
|  | ||||
|     //! Writes the given \c double value to the stream | ||||
|     /*! | ||||
|         \param d The value to be written. | ||||
|         \return Whether it is succeed. | ||||
|     */ | ||||
|     bool Double(double d) { | ||||
|         Prefix(kNumberType); | ||||
|         return EndValue(WriteDouble(d)); | ||||
|     } | ||||
|     bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); } | ||||
|  | ||||
|     bool RawNumber(const Ch* str, SizeType length, bool copy = false) { | ||||
|         RAPIDJSON_ASSERT(str != 0); | ||||
| @@ -238,15 +222,16 @@ 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())); | ||||
|     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));                 // not inside an Object | ||||
|         RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);            // currently inside an Array, not Object | ||||
|         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()); | ||||
| @@ -273,7 +258,7 @@ public: | ||||
|     //! Simpler but slower overload. | ||||
|     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. | ||||
| @@ -304,34 +289,23 @@ protected: | ||||
|     //! Information for each nested level | ||||
|     struct Level { | ||||
|         Level(bool inArray_) : valueCount(0), inArray(inArray_) {} | ||||
|         size_t valueCount; //!< number of values in this level | ||||
|         bool inArray;      //!< true if in array, otherwise in object | ||||
|         size_t valueCount;  //!< number of values in this level | ||||
|         bool inArray;       //!< true if in array, otherwise in object | ||||
|     }; | ||||
|  | ||||
|     bool WriteNull() { | ||||
|     bool WriteNull()  { | ||||
|         PutReserve(*os_, 4); | ||||
|         PutUnsafe(*os_, 'n'); | ||||
|         PutUnsafe(*os_, 'u'); | ||||
|         PutUnsafe(*os_, 'l'); | ||||
|         PutUnsafe(*os_, 'l'); | ||||
|         return true; | ||||
|         PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; | ||||
|     } | ||||
|  | ||||
|     bool WriteBool(bool b) { | ||||
|     bool WriteBool(bool b)  { | ||||
|         if (b) { | ||||
|             PutReserve(*os_, 4); | ||||
|             PutUnsafe(*os_, 't'); | ||||
|             PutUnsafe(*os_, 'r'); | ||||
|             PutUnsafe(*os_, 'u'); | ||||
|             PutUnsafe(*os_, 'e'); | ||||
|             PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); | ||||
|         } | ||||
|         else { | ||||
|             PutReserve(*os_, 5); | ||||
|             PutUnsafe(*os_, 'f'); | ||||
|             PutUnsafe(*os_, 'a'); | ||||
|             PutUnsafe(*os_, 'l'); | ||||
|             PutUnsafe(*os_, 's'); | ||||
|             PutUnsafe(*os_, 'e'); | ||||
|             PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| @@ -378,9 +352,7 @@ protected: | ||||
|                 return false; | ||||
|             if (internal::Double(d).IsNan()) { | ||||
|                 PutReserve(*os_, 3); | ||||
|                 PutUnsafe(*os_, 'N'); | ||||
|                 PutUnsafe(*os_, 'a'); | ||||
|                 PutUnsafe(*os_, 'N'); | ||||
|                 PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); | ||||
|                 return true; | ||||
|             } | ||||
|             if (internal::Double(d).Sign()) { | ||||
| @@ -389,14 +361,8 @@ protected: | ||||
|             } | ||||
|             else | ||||
|                 PutReserve(*os_, 8); | ||||
|             PutUnsafe(*os_, 'I'); | ||||
|             PutUnsafe(*os_, 'n'); | ||||
|             PutUnsafe(*os_, 'f'); | ||||
|             PutUnsafe(*os_, 'i'); | ||||
|             PutUnsafe(*os_, 'n'); | ||||
|             PutUnsafe(*os_, 'i'); | ||||
|             PutUnsafe(*os_, 't'); | ||||
|             PutUnsafe(*os_, 'y'); | ||||
|             PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); | ||||
|             PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
| @@ -408,16 +374,16 @@ protected: | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool WriteString(const Ch* str, SizeType length) { | ||||
|     bool WriteString(const Ch* str, SizeType length)  { | ||||
|         static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | ||||
|         static const char escape[256] = { | ||||
| #define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||||
| #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | ||||
|             //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F | ||||
|             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 | ||||
|             'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 | ||||
|             0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                               // 20 | ||||
|               0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20 | ||||
|             Z16, Z16,                                                                       // 30~4F | ||||
|             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,                              // 50 | ||||
|               0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50 | ||||
|             Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF | ||||
| #undef Z16 | ||||
|         }; | ||||
| @@ -425,7 +391,7 @@ protected: | ||||
|         if (TargetEncoding::supportUnicode) | ||||
|             PutReserve(*os_, 2 + length * 6); // "\uxxxx..." | ||||
|         else | ||||
|             PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." | ||||
|             PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..." | ||||
|  | ||||
|         PutUnsafe(*os_, '\"'); | ||||
|         GenericStringStream<SourceEncoding> is(str); | ||||
| @@ -440,9 +406,9 @@ protected: | ||||
|                 PutUnsafe(*os_, 'u'); | ||||
|                 if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint)&15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]); | ||||
|                 } | ||||
|                 else { | ||||
|                     RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); | ||||
| @@ -451,18 +417,18 @@ protected: | ||||
|                     unsigned lead = (s >> 10) + 0xD800; | ||||
|                     unsigned trail = (s & 0x3FF) + 0xDC00; | ||||
|                     PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead)&15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(lead      ) & 15]); | ||||
|                     PutUnsafe(*os_, '\\'); | ||||
|                     PutUnsafe(*os_, 'u'); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail)&15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]); | ||||
|                     PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                     | ||||
|                 } | ||||
|             } | ||||
|             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { | ||||
|             else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  { | ||||
|                 is.Take(); | ||||
|                 PutUnsafe(*os_, '\\'); | ||||
|                 PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)])); | ||||
| @@ -473,7 +439,9 @@ protected: | ||||
|                     PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); | ||||
|                 } | ||||
|             } | ||||
|             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) | ||||
|             else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?  | ||||
|                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : | ||||
|                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) | ||||
|                 return false; | ||||
|         } | ||||
|         PutUnsafe(*os_, '\"'); | ||||
| @@ -484,29 +452,19 @@ protected: | ||||
|         return RAPIDJSON_LIKELY(is.Tell() < length); | ||||
|     } | ||||
|  | ||||
|     bool WriteStartObject() { | ||||
|         os_->Put('{'); | ||||
|         return true; | ||||
|     } | ||||
|     bool WriteEndObject() { | ||||
|         os_->Put('}'); | ||||
|         return true; | ||||
|     } | ||||
|     bool WriteStartArray() { | ||||
|         os_->Put('['); | ||||
|         return true; | ||||
|     } | ||||
|     bool WriteEndArray() { | ||||
|         os_->Put(']'); | ||||
|         return true; | ||||
|     } | ||||
|     bool WriteStartObject() { os_->Put('{'); return true; } | ||||
|     bool WriteEndObject()   { os_->Put('}'); return true; } | ||||
|     bool WriteStartArray()  { os_->Put('['); return true; } | ||||
|     bool WriteEndArray()    { os_->Put(']'); return true; } | ||||
|  | ||||
|     bool WriteRawValue(const Ch* json, size_t length) { | ||||
|         PutReserve(*os_, length); | ||||
|         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_)))) | ||||
|             if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?  | ||||
|                 Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : | ||||
|                 Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
| @@ -517,24 +475,24 @@ protected: | ||||
|         if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root | ||||
|             Level* level = level_stack_.template Top<Level>(); | ||||
|             if (level->valueCount > 0) { | ||||
|                 if (level->inArray) | ||||
|                 if (level->inArray)  | ||||
|                     os_->Put(','); // add comma if it is not the first element in array | ||||
|                 else               // in object | ||||
|                 else  // in object | ||||
|                     os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); | ||||
|             } | ||||
|             if (!level->inArray && level->valueCount % 2 == 0) | ||||
|                 RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name | ||||
|                 RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name | ||||
|             level->valueCount++; | ||||
|         } | ||||
|         else { | ||||
|             RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. | ||||
|             RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root. | ||||
|             hasRoot_ = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Flush the value if it is the top level one. | ||||
|     bool EndValue(bool ret) { | ||||
|         if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text | ||||
|         if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text | ||||
|             Flush(); | ||||
|         return ret; | ||||
|     } | ||||
| @@ -552,39 +510,39 @@ private: | ||||
|  | ||||
| // Full specialization for StringStream to prevent memory copying | ||||
|  | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::WriteInt(int i) { | ||||
|     char* buffer = os_->Push(11); | ||||
|     char *buffer = os_->Push(11); | ||||
|     const char* end = internal::i32toa(i, buffer); | ||||
|     os_->Pop(static_cast<size_t>(11 - (end - buffer))); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::WriteUint(unsigned u) { | ||||
|     char* buffer = os_->Push(10); | ||||
|     char *buffer = os_->Push(10); | ||||
|     const char* end = internal::u32toa(u, buffer); | ||||
|     os_->Pop(static_cast<size_t>(10 - (end - buffer))); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { | ||||
|     char* buffer = os_->Push(21); | ||||
|     char *buffer = os_->Push(21); | ||||
|     const char* end = internal::i64toa(i64, buffer); | ||||
|     os_->Pop(static_cast<size_t>(21 - (end - buffer))); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { | ||||
|     char* buffer = os_->Push(20); | ||||
|     char *buffer = os_->Push(20); | ||||
|     const char* end = internal::u64toa(u, buffer); | ||||
|     os_->Pop(static_cast<size_t>(20 - (end - buffer))); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| template <> | ||||
| 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). | ||||
| @@ -592,9 +550,7 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) { | ||||
|             return false; | ||||
|         if (internal::Double(d).IsNan()) { | ||||
|             PutReserve(*os_, 3); | ||||
|             PutUnsafe(*os_, 'N'); | ||||
|             PutUnsafe(*os_, 'a'); | ||||
|             PutUnsafe(*os_, 'N'); | ||||
|             PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); | ||||
|             return true; | ||||
|         } | ||||
|         if (internal::Double(d).Sign()) { | ||||
| @@ -603,25 +559,19 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) { | ||||
|         } | ||||
|         else | ||||
|             PutReserve(*os_, 8); | ||||
|         PutUnsafe(*os_, 'I'); | ||||
|         PutUnsafe(*os_, 'n'); | ||||
|         PutUnsafe(*os_, 'f'); | ||||
|         PutUnsafe(*os_, 'i'); | ||||
|         PutUnsafe(*os_, 'n'); | ||||
|         PutUnsafe(*os_, 'i'); | ||||
|         PutUnsafe(*os_, 't'); | ||||
|         PutUnsafe(*os_, 'y'); | ||||
|         PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); | ||||
|         PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     char* buffer = os_->Push(25); | ||||
|      | ||||
|     char *buffer = os_->Push(25); | ||||
|     char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); | ||||
|     os_->Pop(static_cast<size_t>(25 - (end - buffer))); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { | ||||
|     if (length < 16) | ||||
|         return RAPIDJSON_LIKELY(is.Tell() < length); | ||||
| @@ -647,21 +597,21 @@ 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] = { 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])); | ||||
|     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])); | ||||
|  | ||||
|     for (; p != endAligned; p += 16) { | ||||
|         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); | ||||
|         const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); | ||||
|         const __m128i t1 = _mm_cmpeq_epi8(s, dq); | ||||
|         const __m128i t2 = _mm_cmpeq_epi8(s, bs); | ||||
|         const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F | ||||
|         const __m128i 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 | ||||
|         if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped | ||||
|             SizeType len; | ||||
| #ifdef _MSC_VER // Find the index of first escaped | ||||
| #ifdef _MSC_VER         // Find the index of first escaped | ||||
|             unsigned long offset; | ||||
|             _BitScanForward(&offset, r); | ||||
|             len = offset; | ||||
| @@ -675,14 +625,14 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz | ||||
|             p += len; | ||||
|             break; | ||||
|         } | ||||
|         _mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s); | ||||
|         _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); | ||||
|     } | ||||
|  | ||||
|     is.src_ = p; | ||||
|     return RAPIDJSON_LIKELY(is.Tell() < length); | ||||
| } | ||||
| #elif defined(RAPIDJSON_NEON) | ||||
| template <> | ||||
| template<> | ||||
| inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { | ||||
|     if (length < 16) | ||||
|         return RAPIDJSON_LIKELY(is.Tell() < length); | ||||
| @@ -712,15 +662,15 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz | ||||
|     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)); | ||||
|         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 | ||||
|         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; | ||||
| @@ -730,13 +680,12 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz | ||||
|                 len = 8 + (lz >> 3); | ||||
|                 escaped = true; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|         } else { | ||||
|             uint32_t lz = internal::clzll(low); | ||||
|             len = lz >> 3; | ||||
|             escaped = true; | ||||
|         } | ||||
|         if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped | ||||
|         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]; | ||||
| @@ -744,7 +693,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz | ||||
|             p += len; | ||||
|             break; | ||||
|         } | ||||
|         vst1q_u8(reinterpret_cast<uint8_t*>(os_->PushUnsafe(16)), s); | ||||
|         vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s); | ||||
|     } | ||||
|  | ||||
|     is.src_ = p; | ||||
|   | ||||
| @@ -16,15 +16,22 @@ struct Backoff { | ||||
|     double rand01() { return randDistribution(randGenerator); } | ||||
|  | ||||
|     Backoff(int64_t min, int64_t max) | ||||
|         : minAmount(min), maxAmount(max), current(min), fails(0), randGenerator((uint64_t)time(0)) { | ||||
|       : minAmount(min) | ||||
|       , maxAmount(max) | ||||
|       , current(min) | ||||
|       , fails(0) | ||||
|       , randGenerator((uint64_t)time(0)) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void reset() { | ||||
|     void reset() | ||||
|     { | ||||
|         fails = 0; | ||||
|         current = minAmount; | ||||
|     } | ||||
|  | ||||
|     int64_t nextDelay() { | ||||
|     int64_t nextDelay() | ||||
|     { | ||||
|         ++fails; | ||||
|         int64_t delay = (int64_t)((double)current * 2.0 * rand01()); | ||||
|         current = std::min(current + delay, maxAmount); | ||||
|   | ||||
| @@ -11,7 +11,7 @@ int GetProcessId(); | ||||
| struct BaseConnection { | ||||
|     static BaseConnection* Create(); | ||||
|     static void Destroy(BaseConnection*&); | ||||
|     bool isOpen{ false }; | ||||
|     bool isOpen{false}; | ||||
|     bool Open(); | ||||
|     bool Close(); | ||||
|     bool Write(const void* data, size_t length); | ||||
|   | ||||
| @@ -9,12 +9,13 @@ | ||||
| #include <sys/un.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| int GetProcessId() { | ||||
| int GetProcessId() | ||||
| { | ||||
|     return ::getpid(); | ||||
| } | ||||
|  | ||||
| struct BaseConnectionUnix : public BaseConnection { | ||||
|     int sock{ -1 }; | ||||
|     int sock{-1}; | ||||
| }; | ||||
|  | ||||
| static BaseConnectionUnix Connection; | ||||
| @@ -25,7 +26,8 @@ static int MsgFlags = MSG_NOSIGNAL; | ||||
| static int MsgFlags = 0; | ||||
| #endif | ||||
|  | ||||
| static const char* GetTempPath() { | ||||
| static const char* GetTempPath() | ||||
| { | ||||
|     const char* temp = getenv("XDG_RUNTIME_DIR"); | ||||
|     temp = temp ? temp : getenv("TMPDIR"); | ||||
|     temp = temp ? temp : getenv("TMP"); | ||||
| @@ -34,18 +36,21 @@ static const char* GetTempPath() { | ||||
|     return temp; | ||||
| } | ||||
|  | ||||
| /*static*/ BaseConnection* BaseConnection::Create() { | ||||
| /*static*/ BaseConnection* BaseConnection::Create() | ||||
| { | ||||
|     PipeAddr.sun_family = AF_UNIX; | ||||
|     return &Connection; | ||||
| } | ||||
|  | ||||
| /*static*/ void BaseConnection::Destroy(BaseConnection*& c) { | ||||
| /*static*/ void BaseConnection::Destroy(BaseConnection*& c) | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionUnix*>(c); | ||||
|     self->Close(); | ||||
|     c = nullptr; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Open() { | ||||
| bool BaseConnection::Open() | ||||
| { | ||||
|     const char* tempPath = GetTempPath(); | ||||
|     auto self = reinterpret_cast<BaseConnectionUnix*>(this); | ||||
|     self->sock = socket(AF_UNIX, SOCK_STREAM, 0); | ||||
| @@ -60,7 +65,7 @@ bool BaseConnection::Open() { | ||||
|  | ||||
|     for (int pipeNum = 0; pipeNum < 10; ++pipeNum) { | ||||
|         snprintf( | ||||
|             PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); | ||||
|           PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); | ||||
|         int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr)); | ||||
|         if (err == 0) { | ||||
|             self->isOpen = true; | ||||
| @@ -71,7 +76,8 @@ bool BaseConnection::Open() { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Close() { | ||||
| bool BaseConnection::Close() | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionUnix*>(this); | ||||
|     if (self->sock == -1) { | ||||
|         return false; | ||||
| @@ -82,7 +88,8 @@ bool BaseConnection::Close() { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Write(const void* data, size_t length) { | ||||
| bool BaseConnection::Write(const void* data, size_t length) | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionUnix*>(this); | ||||
|  | ||||
|     if (self->sock == -1) { | ||||
| @@ -96,7 +103,8 @@ bool BaseConnection::Write(const void* data, size_t length) { | ||||
|     return sentBytes == (ssize_t)length; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Read(void* data, size_t length) { | ||||
| bool BaseConnection::Read(void* data, size_t length) | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionUnix*>(this); | ||||
|  | ||||
|     if (self->sock == -1) { | ||||
|   | ||||
| @@ -7,34 +7,38 @@ | ||||
| #include <assert.h> | ||||
| #include <windows.h> | ||||
|  | ||||
| int GetProcessId() { | ||||
| int GetProcessId() | ||||
| { | ||||
|     return (int)::GetCurrentProcessId(); | ||||
| } | ||||
|  | ||||
| struct BaseConnectionWin : public BaseConnection { | ||||
|     HANDLE pipe{ INVALID_HANDLE_VALUE }; | ||||
|     HANDLE pipe{INVALID_HANDLE_VALUE}; | ||||
| }; | ||||
|  | ||||
| static BaseConnectionWin Connection; | ||||
|  | ||||
| /*static*/ BaseConnection* BaseConnection::Create() { | ||||
| /*static*/ BaseConnection* BaseConnection::Create() | ||||
| { | ||||
|     return &Connection; | ||||
| } | ||||
|  | ||||
| /*static*/ void BaseConnection::Destroy(BaseConnection*& c) { | ||||
| /*static*/ void BaseConnection::Destroy(BaseConnection*& c) | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionWin*>(c); | ||||
|     self->Close(); | ||||
|     c = nullptr; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Open() { | ||||
|     wchar_t pipeName[]{ L"\\\\?\\pipe\\discord-ipc-0" }; | ||||
| bool BaseConnection::Open() | ||||
| { | ||||
|     wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"}; | ||||
|     const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; | ||||
|     pipeName[pipeDigit] = L'0'; | ||||
|     auto self = reinterpret_cast<BaseConnectionWin*>(this); | ||||
|     for (;;) { | ||||
|         self->pipe = ::CreateFileW( | ||||
|             pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); | ||||
|           pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); | ||||
|         if (self->pipe != INVALID_HANDLE_VALUE) { | ||||
|             self->isOpen = true; | ||||
|             return true; | ||||
| @@ -57,7 +61,8 @@ bool BaseConnection::Open() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Close() { | ||||
| bool BaseConnection::Close() | ||||
| { | ||||
|     auto self = reinterpret_cast<BaseConnectionWin*>(this); | ||||
|     ::CloseHandle(self->pipe); | ||||
|     self->pipe = INVALID_HANDLE_VALUE; | ||||
| @@ -65,7 +70,8 @@ bool BaseConnection::Close() { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Write(const void* data, size_t length) { | ||||
| bool BaseConnection::Write(const void* data, size_t length) | ||||
| { | ||||
|     if (length == 0) { | ||||
|         return true; | ||||
|     } | ||||
| @@ -84,10 +90,11 @@ bool BaseConnection::Write(const void* data, size_t length) { | ||||
|     const DWORD bytesLength = (DWORD)length; | ||||
|     DWORD bytesWritten = 0; | ||||
|     return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE && | ||||
|            bytesWritten == bytesLength; | ||||
|       bytesWritten == bytesLength; | ||||
| } | ||||
|  | ||||
| bool BaseConnection::Read(void* data, size_t length) { | ||||
| bool BaseConnection::Read(void* data, size_t length) | ||||
| { | ||||
|     assert(data); | ||||
|     if (!data) { | ||||
|         return false; | ||||
|   | ||||
| @@ -9,7 +9,8 @@ | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| static bool Mkdir(const char* path) { | ||||
| static bool Mkdir(const char* path) | ||||
| { | ||||
|     int result = mkdir(path, 0755); | ||||
|     if (result == 0) { | ||||
|         return true; | ||||
| @@ -21,7 +22,8 @@ static bool Mkdir(const char* path) { | ||||
| } | ||||
|  | ||||
| // we want to register games so we can run them from Discord client as discord-<appid>:// | ||||
| extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) { | ||||
| extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) | ||||
| { | ||||
|     // Add a desktop file and update some mime handlers so that xdg-open does the right thing. | ||||
|  | ||||
|     const char* home = getenv("HOME"); | ||||
| @@ -40,15 +42,15 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const | ||||
|     } | ||||
|  | ||||
|     const char* desktopFileFormat = "[Desktop Entry]\n" | ||||
|                                     "Name=Game %s\n" | ||||
|                                     "Exec=%s %%u\n" // note: it really wants that %u in there | ||||
|                                     "Type=Application\n" | ||||
|                                     "NoDisplay=true\n" | ||||
|                                     "Categories=Discord;Games;\n" | ||||
|                                     "MimeType=x-scheme-handler/discord-%s;\n"; | ||||
|                                    "Name=Game %s\n" | ||||
|                                    "Exec=%s %%u\n" // note: it really wants that %u in there | ||||
|                                    "Type=Application\n" | ||||
|                                    "NoDisplay=true\n" | ||||
|                                    "Categories=Discord;Games;\n" | ||||
|                                    "MimeType=x-scheme-handler/discord-%s;\n"; | ||||
|     char desktopFile[2048]; | ||||
|     int fileLen = snprintf( | ||||
|         desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId); | ||||
|       desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId); | ||||
|     if (fileLen <= 0) { | ||||
|         return; | ||||
|     } | ||||
| @@ -92,7 +94,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, | ||||
|                                                          const char* steamId) { | ||||
|                                                          const char* steamId) | ||||
| { | ||||
|     char command[256]; | ||||
|     sprintf(command, "xdg-open steam://rungameid/%s", steamId); | ||||
|     Discord_Register(applicationId, command); | ||||
|   | ||||
| @@ -21,7 +21,8 @@ | ||||
| #ifdef __MINGW32__ | ||||
| #include <wchar.h> | ||||
| /// strsafe.h fixes | ||||
| static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) { | ||||
| static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) | ||||
| { | ||||
|     HRESULT ret; | ||||
|     va_list va; | ||||
|     va_start(va, pszFormat); | ||||
| @@ -50,7 +51,8 @@ static LSTATUS regset(HKEY hkey, | ||||
|                       LPCWSTR name, | ||||
|                       DWORD type, | ||||
|                       const void* data, | ||||
|                       DWORD len) { | ||||
|                       DWORD len) | ||||
| { | ||||
|     HKEY htkey = hkey, hsubkey = nullptr; | ||||
|     LSTATUS ret; | ||||
|     if (subkey && subkey[0]) { | ||||
| @@ -65,7 +67,8 @@ static LSTATUS regset(HKEY hkey, | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) { | ||||
| static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) | ||||
| { | ||||
|     // https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx | ||||
|     // we want to register games so we can run them as discord-<appid>:// | ||||
|     // Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. | ||||
| @@ -86,14 +89,14 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma | ||||
|     StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId); | ||||
|     wchar_t protocolDescription[128]; | ||||
|     StringCbPrintfW( | ||||
|         protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId); | ||||
|       protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId); | ||||
|     wchar_t urlProtocol = 0; | ||||
|  | ||||
|     wchar_t keyName[256]; | ||||
|     StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName); | ||||
|     HKEY key; | ||||
|     auto status = | ||||
|         RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr); | ||||
|       RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr); | ||||
|     if (status != ERROR_SUCCESS) { | ||||
|         fprintf(stderr, "Error creating key\n"); | ||||
|         return; | ||||
| @@ -102,7 +105,7 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma | ||||
|     LSTATUS result; | ||||
|     len = (DWORD)lstrlenW(protocolDescription) + 1; | ||||
|     result = | ||||
|         RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t)); | ||||
|       RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t)); | ||||
|     if (FAILED(result)) { | ||||
|         fprintf(stderr, "Error writing description\n"); | ||||
|     } | ||||
| @@ -114,21 +117,22 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma | ||||
|     } | ||||
|  | ||||
|     result = RegSetKeyValueW( | ||||
|         key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t)); | ||||
|       key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t)); | ||||
|     if (FAILED(result)) { | ||||
|         fprintf(stderr, "Error writing icon\n"); | ||||
|     } | ||||
|  | ||||
|     len = (DWORD)lstrlenW(openCommand) + 1; | ||||
|     result = RegSetKeyValueW( | ||||
|         key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t)); | ||||
|       key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t)); | ||||
|     if (FAILED(result)) { | ||||
|         fprintf(stderr, "Error writing command\n"); | ||||
|     } | ||||
|     RegCloseKey(key); | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) { | ||||
| extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) | ||||
| { | ||||
|     wchar_t appId[32]; | ||||
|     MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); | ||||
|  | ||||
| @@ -144,7 +148,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, | ||||
|                                                          const char* steamId) { | ||||
|                                                          const char* steamId) | ||||
| { | ||||
|     wchar_t appId[32]; | ||||
|     MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); | ||||
|  | ||||
|   | ||||
| @@ -15,15 +15,16 @@ | ||||
| #include <thread> | ||||
| #endif | ||||
|  | ||||
| constexpr size_t MaxMessageSize{ 16 * 1024 }; | ||||
| constexpr size_t MessageQueueSize{ 8 }; | ||||
| constexpr size_t JoinQueueSize{ 8 }; | ||||
| constexpr size_t MaxMessageSize{16 * 1024}; | ||||
| constexpr size_t MessageQueueSize{8}; | ||||
| constexpr size_t JoinQueueSize{8}; | ||||
|  | ||||
| struct QueuedMessage { | ||||
|     size_t length; | ||||
|     char buffer[MaxMessageSize]; | ||||
|  | ||||
|     void Copy(const QueuedMessage& other) { | ||||
|     void Copy(const QueuedMessage& other) | ||||
|     { | ||||
|         length = other.length; | ||||
|         if (length) { | ||||
|             memcpy(buffer, other.buffer, length); | ||||
| @@ -45,20 +46,20 @@ struct User { | ||||
|     // Rounded way up because I'm paranoid about games breaking from future changes in these sizes | ||||
| }; | ||||
|  | ||||
| static RpcConnection* Connection{ nullptr }; | ||||
| static RpcConnection* Connection{nullptr}; | ||||
| static DiscordEventHandlers QueuedHandlers{}; | ||||
| static DiscordEventHandlers Handlers{}; | ||||
| static std::atomic_bool WasJustConnected{ false }; | ||||
| static std::atomic_bool WasJustDisconnected{ false }; | ||||
| static std::atomic_bool GotErrorMessage{ false }; | ||||
| static std::atomic_bool WasJoinGame{ false }; | ||||
| static std::atomic_bool WasSpectateGame{ false }; | ||||
| static std::atomic_bool UpdatePresence{ false }; | ||||
| static std::atomic_bool WasJustConnected{false}; | ||||
| static std::atomic_bool WasJustDisconnected{false}; | ||||
| static std::atomic_bool GotErrorMessage{false}; | ||||
| static std::atomic_bool WasJoinGame{false}; | ||||
| static std::atomic_bool WasSpectateGame{false}; | ||||
| static std::atomic_bool UpdatePresence{false}; | ||||
| static char JoinGameSecret[256]; | ||||
| static char SpectateGameSecret[256]; | ||||
| static int LastErrorCode{ 0 }; | ||||
| static int LastErrorCode{0}; | ||||
| static char LastErrorMessage[256]; | ||||
| static int LastDisconnectErrorCode{ 0 }; | ||||
| static int LastDisconnectErrorCode{0}; | ||||
| static char LastDisconnectErrorMessage[256]; | ||||
| static std::mutex PresenceMutex; | ||||
| static std::mutex HandlerMutex; | ||||
| @@ -71,23 +72,24 @@ static User connectedUser; | ||||
| // backoff from 0.5 seconds to 1 minute | ||||
| static Backoff ReconnectTimeMs(500, 60 * 1000); | ||||
| static auto NextConnect = std::chrono::system_clock::now(); | ||||
| static int Pid{ 0 }; | ||||
| static int Nonce{ 1 }; | ||||
| static int Pid{0}; | ||||
| static int Nonce{1}; | ||||
|  | ||||
| #ifndef DISCORD_DISABLE_IO_THREAD | ||||
| static void Discord_UpdateConnection(void); | ||||
| class IoThreadHolder { | ||||
| private: | ||||
|     std::atomic_bool keepRunning{ true }; | ||||
|     std::atomic_bool keepRunning{true}; | ||||
|     std::mutex waitForIOMutex; | ||||
|     std::condition_variable waitForIOActivity; | ||||
|     std::thread ioThread; | ||||
|  | ||||
| public: | ||||
|     void Start() { | ||||
|     void Start() | ||||
|     { | ||||
|         keepRunning.store(true); | ||||
|         ioThread = std::thread([&]() { | ||||
|             const std::chrono::duration<int64_t, std::milli> maxWait{ 500LL }; | ||||
|             const std::chrono::duration<int64_t, std::milli> maxWait{500LL}; | ||||
|             Discord_UpdateConnection(); | ||||
|             while (keepRunning.load()) { | ||||
|                 std::unique_lock<std::mutex> lock(waitForIOMutex); | ||||
| @@ -99,7 +101,8 @@ public: | ||||
|  | ||||
|     void Notify() { waitForIOActivity.notify_all(); } | ||||
|  | ||||
|     void Stop() { | ||||
|     void Stop() | ||||
|     { | ||||
|         keepRunning.exchange(false); | ||||
|         Notify(); | ||||
|         if (ioThread.joinable()) { | ||||
| @@ -117,11 +120,12 @@ public: | ||||
|     void Notify() {} | ||||
| }; | ||||
| #endif // DISCORD_DISABLE_IO_THREAD | ||||
| static IoThreadHolder* IoThread{ nullptr }; | ||||
| static IoThreadHolder* IoThread{nullptr}; | ||||
|  | ||||
| static void UpdateReconnectTime() { | ||||
| static void UpdateReconnectTime() | ||||
| { | ||||
|     NextConnect = std::chrono::system_clock::now() + | ||||
|                   std::chrono::duration<int64_t, std::milli>{ ReconnectTimeMs.nextDelay() }; | ||||
|       std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()}; | ||||
| } | ||||
|  | ||||
| #ifdef DISCORD_DISABLE_IO_THREAD | ||||
| @@ -233,17 +237,19 @@ static void Discord_UpdateConnection(void) | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void SignalIOActivity() { | ||||
| static void SignalIOActivity() | ||||
| { | ||||
|     if (IoThread != nullptr) { | ||||
|         IoThread->Notify(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static bool RegisterForEvent(const char* evtName) { | ||||
| static bool RegisterForEvent(const char* evtName) | ||||
| { | ||||
|     auto qmessage = SendQueue.GetNextAddMessage(); | ||||
|     if (qmessage) { | ||||
|         qmessage->length = | ||||
|             JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); | ||||
|           JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); | ||||
|         SendQueue.CommitAdd(); | ||||
|         SignalIOActivity(); | ||||
|         return true; | ||||
| @@ -251,11 +257,12 @@ static bool RegisterForEvent(const char* evtName) { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| static bool DeregisterForEvent(const char* evtName) { | ||||
| static bool DeregisterForEvent(const char* evtName) | ||||
| { | ||||
|     auto qmessage = SendQueue.GetNextAddMessage(); | ||||
|     if (qmessage) { | ||||
|         qmessage->length = | ||||
|             JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); | ||||
|           JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); | ||||
|         SendQueue.CommitAdd(); | ||||
|         SignalIOActivity(); | ||||
|         return true; | ||||
| @@ -266,7 +273,8 @@ static bool DeregisterForEvent(const char* evtName) { | ||||
| extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, | ||||
|                                                   DiscordEventHandlers* handlers, | ||||
|                                                   int autoRegister, | ||||
|                                                   const char* optionalSteamId) { | ||||
|                                                   const char* optionalSteamId) | ||||
| { | ||||
|     IoThread = new (std::nothrow) IoThreadHolder(); | ||||
|     if (IoThread == nullptr) { | ||||
|         return; | ||||
| @@ -339,7 +347,8 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, | ||||
|     IoThread->Start(); | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_Shutdown(void) { | ||||
| extern "C" DISCORD_EXPORT void Discord_Shutdown(void) | ||||
| { | ||||
|     if (!Connection) { | ||||
|         return; | ||||
|     } | ||||
| @@ -357,21 +366,24 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown(void) { | ||||
|     RpcConnection::Destroy(Connection); | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) { | ||||
| extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) | ||||
| { | ||||
|     { | ||||
|         std::lock_guard<std::mutex> guard(PresenceMutex); | ||||
|         QueuedPresence.length = JsonWriteRichPresenceObj( | ||||
|             QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); | ||||
|           QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); | ||||
|         UpdatePresence.exchange(true); | ||||
|     } | ||||
|     SignalIOActivity(); | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) { | ||||
| extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) | ||||
| { | ||||
|     Discord_UpdatePresence(nullptr); | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) { | ||||
| extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) | ||||
| { | ||||
|     // if we are not connected, let's not batch up stale messages for later | ||||
|     if (!Connection || !Connection->IsOpen()) { | ||||
|         return; | ||||
| @@ -379,13 +391,14 @@ extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_RE | ||||
|     auto qmessage = SendQueue.GetNextAddMessage(); | ||||
|     if (qmessage) { | ||||
|         qmessage->length = | ||||
|             JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++); | ||||
|           JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++); | ||||
|         SendQueue.CommitAdd(); | ||||
|         SignalIOActivity(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { | ||||
| extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) | ||||
| { | ||||
|     // Note on some weirdness: internally we might connect, get other signals, disconnect any number | ||||
|     // of times inbetween calls here. Externally, we want the sequence to seem sane, so any other | ||||
|     // signals are book-ended by calls to ready and disconnect. | ||||
| @@ -408,10 +421,10 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { | ||||
|     if (WasJustConnected.exchange(false)) { | ||||
|         std::lock_guard<std::mutex> guard(HandlerMutex); | ||||
|         if (Handlers.ready) { | ||||
|             DiscordUser du{ connectedUser.userId, | ||||
|                             connectedUser.username, | ||||
|                             connectedUser.discriminator, | ||||
|                             connectedUser.avatar }; | ||||
|             DiscordUser du{connectedUser.userId, | ||||
|                            connectedUser.username, | ||||
|                            connectedUser.discriminator, | ||||
|                            connectedUser.avatar}; | ||||
|             Handlers.ready(&du); | ||||
|         } | ||||
|     } | ||||
| @@ -447,7 +460,7 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { | ||||
|         { | ||||
|             std::lock_guard<std::mutex> guard(HandlerMutex); | ||||
|             if (Handlers.joinRequest) { | ||||
|                 DiscordUser du{ req->userId, req->username, req->discriminator, req->avatar }; | ||||
|                 DiscordUser du{req->userId, req->username, req->discriminator, req->avatar}; | ||||
|                 Handlers.joinRequest(&du); | ||||
|             } | ||||
|         } | ||||
| @@ -463,7 +476,8 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) { | ||||
| extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) | ||||
| { | ||||
|     if (newHandlers) { | ||||
| #define HANDLE_EVENT_REGISTRATION(handler_name, event)              \ | ||||
|     if (!Handlers.handler_name && newHandlers->handler_name) {      \ | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| // outsmart GCC's missing-declarations warning | ||||
| BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID); | ||||
| BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) { | ||||
| BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) | ||||
| { | ||||
|     return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -8,14 +8,15 @@ | ||||
| template <typename ElementType, size_t QueueSize> | ||||
| class MsgQueue { | ||||
|     ElementType queue_[QueueSize]; | ||||
|     std::atomic_uint nextAdd_{ 0 }; | ||||
|     std::atomic_uint nextSend_{ 0 }; | ||||
|     std::atomic_uint pendingSends_{ 0 }; | ||||
|     std::atomic_uint nextAdd_{0}; | ||||
|     std::atomic_uint nextSend_{0}; | ||||
|     std::atomic_uint pendingSends_{0}; | ||||
|  | ||||
| public: | ||||
|     MsgQueue() {} | ||||
|  | ||||
|     ElementType* GetNextAddMessage() { | ||||
|     ElementType* GetNextAddMessage() | ||||
|     { | ||||
|         // if we are falling behind, bail | ||||
|         if (pendingSends_.load() >= QueueSize) { | ||||
|             return nullptr; | ||||
| @@ -26,7 +27,8 @@ public: | ||||
|     void CommitAdd() { ++pendingSends_; } | ||||
|  | ||||
|     bool HavePendingSends() const { return pendingSends_.load() != 0; } | ||||
|     ElementType* GetNextSendMessage() { | ||||
|     ElementType* GetNextSendMessage() | ||||
|     { | ||||
|         auto index = (nextSend_++) % QueueSize; | ||||
|         return &queue_[index]; | ||||
|     } | ||||
|   | ||||
| @@ -6,19 +6,22 @@ | ||||
| static const int RpcVersion = 1; | ||||
| static RpcConnection Instance; | ||||
|  | ||||
| /*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) { | ||||
| /*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) | ||||
| { | ||||
|     Instance.connection = BaseConnection::Create(); | ||||
|     StringCopy(Instance.appId, applicationId); | ||||
|     return &Instance; | ||||
| } | ||||
|  | ||||
| /*static*/ void RpcConnection::Destroy(RpcConnection*& c) { | ||||
| /*static*/ void RpcConnection::Destroy(RpcConnection*& c) | ||||
| { | ||||
|     c->Close(); | ||||
|     BaseConnection::Destroy(c->connection); | ||||
|     c = nullptr; | ||||
| } | ||||
|  | ||||
| void RpcConnection::Open() { | ||||
| void RpcConnection::Open() | ||||
| { | ||||
|     if (state == State::Connected) { | ||||
|         return; | ||||
|     } | ||||
| @@ -43,7 +46,7 @@ void RpcConnection::Open() { | ||||
|     else { | ||||
|         sendFrame.opcode = Opcode::Handshake; | ||||
|         sendFrame.length = (uint32_t)JsonWriteHandshakeObj( | ||||
|             sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId); | ||||
|           sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId); | ||||
|  | ||||
|         if (connection->Write(&sendFrame, sizeof(MessageFrameHeader) + sendFrame.length)) { | ||||
|             state = State::SentHandshake; | ||||
| @@ -54,7 +57,8 @@ void RpcConnection::Open() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void RpcConnection::Close() { | ||||
| void RpcConnection::Close() | ||||
| { | ||||
|     if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) { | ||||
|         onDisconnect(lastErrorCode, lastErrorMessage); | ||||
|     } | ||||
| @@ -62,7 +66,8 @@ void RpcConnection::Close() { | ||||
|     state = State::Disconnected; | ||||
| } | ||||
|  | ||||
| bool RpcConnection::Write(const void* data, size_t length) { | ||||
| bool RpcConnection::Write(const void* data, size_t length) | ||||
| { | ||||
|     sendFrame.opcode = Opcode::Frame; | ||||
|     memcpy(sendFrame.message, data, length); | ||||
|     sendFrame.length = (uint32_t)length; | ||||
| @@ -73,7 +78,8 @@ bool RpcConnection::Write(const void* data, size_t length) { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool RpcConnection::Read(JsonDocument& message) { | ||||
| bool RpcConnection::Read(JsonDocument& message) | ||||
| { | ||||
|     if (state != State::Connected && state != State::SentHandshake) { | ||||
|         return false; | ||||
|     } | ||||
|   | ||||
| @@ -38,12 +38,12 @@ struct RpcConnection { | ||||
|         Connected, | ||||
|     }; | ||||
|  | ||||
|     BaseConnection* connection{ nullptr }; | ||||
|     State state{ State::Disconnected }; | ||||
|     void (*onConnect)(JsonDocument& message){ nullptr }; | ||||
|     void (*onDisconnect)(int errorCode, const char* message){ nullptr }; | ||||
|     BaseConnection* connection{nullptr}; | ||||
|     State state{State::Disconnected}; | ||||
|     void (*onConnect)(JsonDocument& message){nullptr}; | ||||
|     void (*onDisconnect)(int errorCode, const char* message){nullptr}; | ||||
|     char appId[64]{}; | ||||
|     int lastErrorCode{ 0 }; | ||||
|     int lastErrorCode{0}; | ||||
|     char lastErrorMessage[256]{}; | ||||
|     RpcConnection::MessageFrame sendFrame; | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,8 @@ | ||||
| #include "discord_rpc.h" | ||||
|  | ||||
| template <typename T> | ||||
| void NumberToString(char* dest, T number) { | ||||
| void NumberToString(char* dest, T number) | ||||
| { | ||||
|     if (!number) { | ||||
|         *dest++ = '0'; | ||||
|         *dest++ = 0; | ||||
| @@ -28,19 +29,22 @@ void NumberToString(char* dest, T number) { | ||||
|  | ||||
| // it's ever so slightly faster to not have to strlen the key | ||||
| template <typename T> | ||||
| void WriteKey(JsonWriter& w, T& k) { | ||||
| void WriteKey(JsonWriter& w, T& k) | ||||
| { | ||||
|     w.Key(k, sizeof(T) - 1); | ||||
| } | ||||
|  | ||||
| struct WriteObject { | ||||
|     JsonWriter& writer; | ||||
|     WriteObject(JsonWriter& w) | ||||
|         : writer(w) { | ||||
|       : writer(w) | ||||
|     { | ||||
|         writer.StartObject(); | ||||
|     } | ||||
|     template <typename T> | ||||
|     WriteObject(JsonWriter& w, T& name) | ||||
|         : writer(w) { | ||||
|       : writer(w) | ||||
|     { | ||||
|         WriteKey(writer, name); | ||||
|         writer.StartObject(); | ||||
|     } | ||||
| @@ -51,7 +55,8 @@ struct WriteArray { | ||||
|     JsonWriter& writer; | ||||
|     template <typename T> | ||||
|     WriteArray(JsonWriter& w, T& name) | ||||
|         : writer(w) { | ||||
|       : writer(w) | ||||
|     { | ||||
|         WriteKey(writer, name); | ||||
|         writer.StartArray(); | ||||
|     } | ||||
| @@ -59,14 +64,16 @@ struct WriteArray { | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| void WriteOptionalString(JsonWriter& w, T& k, const char* value) { | ||||
| void WriteOptionalString(JsonWriter& w, T& k, const char* value) | ||||
| { | ||||
|     if (value && value[0]) { | ||||
|         w.Key(k, sizeof(T) - 1); | ||||
|         w.String(value); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void JsonWriteNonce(JsonWriter& writer, int nonce) { | ||||
| static void JsonWriteNonce(JsonWriter& writer, int nonce) | ||||
| { | ||||
|     WriteKey(writer, "nonce"); | ||||
|     char nonceBuffer[32]; | ||||
|     NumberToString(nonceBuffer, nonce); | ||||
| @@ -77,7 +84,8 @@ size_t JsonWriteRichPresenceObj(char* dest, | ||||
|                                 size_t maxLen, | ||||
|                                 int nonce, | ||||
|                                 int pid, | ||||
|                                 const DiscordRichPresence* presence) { | ||||
|                                 const DiscordRichPresence* presence) | ||||
| { | ||||
|     JsonWriter writer(dest, maxLen); | ||||
|  | ||||
|     { | ||||
| @@ -159,7 +167,8 @@ size_t JsonWriteRichPresenceObj(char* dest, | ||||
|     return writer.Size(); | ||||
| } | ||||
|  | ||||
| size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) { | ||||
| size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) | ||||
| { | ||||
|     JsonWriter writer(dest, maxLen); | ||||
|  | ||||
|     { | ||||
| @@ -173,7 +182,8 @@ size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* | ||||
|     return writer.Size(); | ||||
| } | ||||
|  | ||||
| size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) { | ||||
| size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) | ||||
| { | ||||
|     JsonWriter writer(dest, maxLen); | ||||
|  | ||||
|     { | ||||
| @@ -191,7 +201,8 @@ size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const cha | ||||
|     return writer.Size(); | ||||
| } | ||||
|  | ||||
| size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) { | ||||
| size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) | ||||
| { | ||||
|     JsonWriter writer(dest, maxLen); | ||||
|  | ||||
|     { | ||||
| @@ -209,7 +220,8 @@ size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const c | ||||
|     return writer.Size(); | ||||
| } | ||||
|  | ||||
| size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) { | ||||
| size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) | ||||
| { | ||||
|     JsonWriter writer(dest, maxLen); | ||||
|  | ||||
|     { | ||||
|   | ||||
| @@ -22,7 +22,8 @@ | ||||
|  | ||||
| // if only there was a standard library function for this | ||||
| template <size_t Len> | ||||
| inline size_t StringCopy(char (&dest)[Len], const char* src) { | ||||
| inline size_t StringCopy(char (&dest)[Len], const char* src) | ||||
| { | ||||
|     if (!src || !Len) { | ||||
|         return 0; | ||||
|     } | ||||
| @@ -57,14 +58,18 @@ class LinearAllocator { | ||||
| public: | ||||
|     char* buffer_; | ||||
|     char* end_; | ||||
|     LinearAllocator() { | ||||
|     LinearAllocator() | ||||
|     { | ||||
|         assert(0); // needed for some default case in rapidjson, should not use | ||||
|     } | ||||
|     LinearAllocator(char* buffer, size_t size) | ||||
|         : buffer_(buffer), end_(buffer + size) { | ||||
|       : buffer_(buffer) | ||||
|       , end_(buffer + size) | ||||
|     { | ||||
|     } | ||||
|     static const bool kNeedFree = false; | ||||
|     void* Malloc(size_t size) { | ||||
|     void* Malloc(size_t size) | ||||
|     { | ||||
|         char* res = buffer_; | ||||
|         buffer_ += size; | ||||
|         if (buffer_ > end_) { | ||||
| @@ -73,7 +78,8 @@ public: | ||||
|         } | ||||
|         return res; | ||||
|     } | ||||
|     void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { | ||||
|     void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) | ||||
|     { | ||||
|         if (newSize == 0) { | ||||
|             return nullptr; | ||||
|         } | ||||
| @@ -84,7 +90,8 @@ public: | ||||
|         (void)(originalSize); | ||||
|         return Malloc(newSize); | ||||
|     } | ||||
|     static void Free(void* ptr) { | ||||
|     static void Free(void* ptr) | ||||
|     { | ||||
|         /* shrug */ | ||||
|         (void)ptr; | ||||
|     } | ||||
| @@ -95,7 +102,8 @@ class FixedLinearAllocator : public LinearAllocator { | ||||
| public: | ||||
|     char fixedBuffer_[Size]; | ||||
|     FixedLinearAllocator() | ||||
|         : LinearAllocator(fixedBuffer_, Size) { | ||||
|       : LinearAllocator(fixedBuffer_, Size) | ||||
|     { | ||||
|     } | ||||
|     static const bool kNeedFree = false; | ||||
| }; | ||||
| @@ -109,10 +117,14 @@ public: | ||||
|     char* current_; | ||||
|  | ||||
|     DirectStringBuffer(char* buffer, size_t maxLen) | ||||
|         : buffer_(buffer), end_(buffer + maxLen), current_(buffer) { | ||||
|       : buffer_(buffer) | ||||
|       , end_(buffer + maxLen) | ||||
|       , current_(buffer) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void Put(char c) { | ||||
|     void Put(char c) | ||||
|     { | ||||
|         if (current_ < end_) { | ||||
|             *current_++ = c; | ||||
|         } | ||||
| @@ -128,14 +140,17 @@ using UTF8 = rapidjson::UTF8<char>; | ||||
| using StackAllocator = FixedLinearAllocator<2048>; | ||||
| constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t)); | ||||
| using JsonWriterBase = | ||||
|     rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>; | ||||
|   rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>; | ||||
| class JsonWriter : public JsonWriterBase { | ||||
| public: | ||||
|     DirectStringBuffer stringBuffer_; | ||||
|     StackAllocator stackAlloc_; | ||||
|  | ||||
|     JsonWriter(char* dest, size_t maxLen) | ||||
|         : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels), stringBuffer_(dest, maxLen), stackAlloc_() { | ||||
|       : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels) | ||||
|       , stringBuffer_(dest, maxLen) | ||||
|       , stackAlloc_() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     size_t Size() const { return stringBuffer_.GetSize(); } | ||||
| @@ -152,17 +167,20 @@ public: | ||||
|     PoolAllocator poolAllocator_; | ||||
|     StackAllocator stackAllocator_; | ||||
|     JsonDocument() | ||||
|         : JsonDocumentBase(rapidjson::kObjectType, | ||||
|                            &poolAllocator_, | ||||
|                            sizeof(stackAllocator_.fixedBuffer_), | ||||
|                            &stackAllocator_), | ||||
|           poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_), stackAllocator_() { | ||||
|       : JsonDocumentBase(rapidjson::kObjectType, | ||||
|                          &poolAllocator_, | ||||
|                          sizeof(stackAllocator_.fixedBuffer_), | ||||
|                          &stackAllocator_) | ||||
|       , poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_) | ||||
|       , stackAllocator_() | ||||
|     { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>; | ||||
|  | ||||
| inline JsonValue* GetObjMember(JsonValue* obj, const char* name) { | ||||
| inline JsonValue* GetObjMember(JsonValue* obj, const char* name) | ||||
| { | ||||
|     if (obj) { | ||||
|         auto member = obj->FindMember(name); | ||||
|         if (member != obj->MemberEnd() && member->value.IsObject()) { | ||||
| @@ -172,7 +190,8 @@ inline JsonValue* GetObjMember(JsonValue* obj, const char* name) { | ||||
|     return nullptr; | ||||
| } | ||||
|  | ||||
| inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) { | ||||
| inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) | ||||
| { | ||||
|     if (obj) { | ||||
|         auto member = obj->FindMember(name); | ||||
|         if (member != obj->MemberEnd() && member->value.IsInt()) { | ||||
| @@ -184,7 +203,8 @@ inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = | ||||
|  | ||||
| inline const char* GetStrMember(JsonValue* obj, | ||||
|                                 const char* name, | ||||
|                                 const char* notFoundDefault = nullptr) { | ||||
|                                 const char* notFoundDefault = nullptr) | ||||
| { | ||||
|     if (obj) { | ||||
|         auto member = obj->FindMember(name); | ||||
|         if (member != obj->MemberEnd() && member->value.IsString()) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user