Changeset - b48628d3affc
[Not reviewed]
include/rapidjson/allocators.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_ALLOCATORS_H_
 
#define RAPIDJSON_ALLOCATORS_H_
 

	
 
#include "rapidjson.h"
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// Allocator
 

	
 
/*! \class rapidjson::Allocator
 
    \brief Concept for allocating, resizing and freeing memory block.
 
    
 
    Note that Malloc() and Realloc() are non-static but Free() is static.
 
    
 
    So if an allocator need to support Free(), it needs to put its pointer in 
 
    the header of memory block.
 

	
 
\code
 
concept Allocator {
 
    static const bool kNeedFree;    //!< Whether this allocator needs to call Free().
 

	
 
    // Allocate a memory block.
 
    // \param size of the memory block in bytes.
 
    // \returns pointer to the memory block.
 
    void* Malloc(size_t size);
 

	
 
    // Resize a memory block.
 
    // \param originalPtr The pointer to current memory block. Null pointer is permitted.
 
    // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
 
    // \param newSize the new size in bytes.
 
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
 

	
 
    // Free a memory block.
 
    // \param pointer to the memory block. Null pointer is permitted.
 
    static void Free(void *ptr);
 
};
 
\endcode
 
*/
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// CrtAllocator
 

	
 
//! C-runtime library allocator.
 
/*! This class is just wrapper for standard C library memory routines.
 
    \note implements Allocator concept
 
*/
 
class CrtAllocator {
 
public:
 
    static const bool kNeedFree = true;
 
    void* Malloc(size_t size) { 
 
        if (size) //  behavior of malloc(0) is implementation defined.
 
            return std::malloc(size);
 
        else
 
            return NULL; // standardize to returning NULL.
 
    }
 
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
 
        (void)originalSize;
 
        if (newSize == 0) {
 
            std::free(originalPtr);
 
            return NULL;
 
        }
 
        return std::realloc(originalPtr, newSize);
 
    }
 
    static void Free(void *ptr) { std::free(ptr); }
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// MemoryPoolAllocator
 

	
 
//! Default memory allocator used by the parser and DOM.
 
/*! This allocator allocate memory blocks from pre-allocated memory chunks. 
 

	
 
    It does not free memory blocks. And Realloc() only allocate new memory.
 

	
 
    The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
 

	
 
    User may also supply a buffer as the first chunk.
 

	
 
    If the user-buffer is full then additional chunks are allocated by BaseAllocator.
 

	
 
    The user-buffer is not deallocated by this allocator.
 

	
 
    \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
 
    \note implements Allocator concept
 
*/
 
template <typename BaseAllocator = CrtAllocator>
 
class MemoryPoolAllocator {
 
public:
 
    static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
 

	
 
    //! Constructor with chunkSize.
 
    /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
 
        \param baseAllocator The allocator for allocating memory chunks.
 
    */
 
    MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 
 
        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
 
    {
 
    }
 

	
 
    //! Constructor with user-supplied buffer.
 
    /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
 

	
 
        The user buffer will not be deallocated when this allocator is destructed.
 

	
 
        \param buffer User supplied buffer.
 
        \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
 
        \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) :
 
        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
 
    {
 
        RAPIDJSON_ASSERT(buffer != 0);
 
        RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
 
        chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
 
        chunkHead_->capacity = size - sizeof(ChunkHeader);
 
        chunkHead_->size = 0;
 
        chunkHead_->next = 0;
 
    }
 

	
 
    //! Destructor.
 
    /*! This deallocates all memory chunks, excluding the user-supplied buffer.
 
    */
 
    ~MemoryPoolAllocator() {
 
        Clear();
 
        RAPIDJSON_DELETE(ownBaseAllocator_);
 
    }
 

	
 
    //! Deallocates all memory chunks, excluding the user-supplied buffer.
 
    void Clear() {
 
        while (chunkHead_ && chunkHead_ != userBuffer_) {
 
            ChunkHeader* next = chunkHead_->next;
 
            baseAllocator_->Free(chunkHead_);
 
            chunkHead_ = next;
 
        }
 
        if (chunkHead_ && chunkHead_ == userBuffer_)
 
            chunkHead_->size = 0; // Clear user buffer
 
    }
 

	
 
    //! Computes the total capacity of allocated memory chunks.
 
    /*! \return total capacity in bytes.
 
    */
 
    size_t Capacity() const {
 
        size_t capacity = 0;
 
        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
 
            capacity += c->capacity;
 
        return capacity;
 
    }
 

	
 
    //! Computes the memory blocks allocated.
 
    /*! \return total used bytes.
 
    */
 
    size_t Size() const {
 
        size_t size = 0;
 
        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
 
            size += c->size;
 
        return size;
 
    }
 

	
 
    //! Allocates a memory block. (concept Allocator)
 
    void* Malloc(size_t size) {
 
        if (!size)
 
            return NULL;
 

	
 
        size = RAPIDJSON_ALIGN(size);
 
        if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
 
            if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
 
                return NULL;
 

	
 
        void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
 
        chunkHead_->size += size;
 
        return buffer;
 
    }
 

	
 
    //! Resizes a memory block (concept Allocator)
 
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
 
        if (originalPtr == 0)
 
            return Malloc(newSize);
 

	
 
        if (newSize == 0)
 
            return NULL;
 

	
 
        originalSize = RAPIDJSON_ALIGN(originalSize);
 
        newSize = RAPIDJSON_ALIGN(newSize);
 

	
 
        // Do not shrink if new size is smaller than original
 
        if (originalSize >= newSize)
 
            return originalPtr;
 

	
 
        // Simply expand it if it is the last allocation and there is sufficient space
 
        if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
 
            size_t increment = static_cast<size_t>(newSize - originalSize);
 
            if (chunkHead_->size + increment <= chunkHead_->capacity) {
 
                chunkHead_->size += increment;
 
                return originalPtr;
 
            }
 
        }
 

	
 
        // Realloc process: allocate and copy memory, do not free original buffer.
 
        if (void* newBuffer = Malloc(newSize)) {
 
            if (originalSize)
 
                std::memcpy(newBuffer, originalPtr, originalSize);
 
            return newBuffer;
 
        }
 
        else
 
            return NULL;
 
    }
 

	
 
    //! Frees a memory block (concept Allocator)
 
    static void Free(void *ptr) { (void)ptr; } // Do nothing
 

	
 
private:
 
    //! Copy constructor is not permitted.
 
    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
 
    //! Copy assignment operator is not permitted.
 
    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
 

	
 
    //! Creates a new chunk.
 
    /*! \param capacity Capacity of the chunk in bytes.
 
        \return true if success.
 
    */
 
    bool AddChunk(size_t capacity) {
 
        if (!baseAllocator_)
 
            ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
 
        if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
 
            chunk->capacity = capacity;
 
            chunk->size = 0;
 
            chunk->next = chunkHead_;
 
            chunkHead_ =  chunk;
 
            return true;
 
        }
 
        else
 
            return false;
 
    }
 

	
 
    static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
 

	
 
    //! Chunk header for perpending to each chunk.
 
    /*! Chunks are stored as a singly linked list.
 
    */
 
    struct ChunkHeader {
 
        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
 
        size_t size;        //!< Current size of allocated memory in bytes.
 
        ChunkHeader *next;  //!< Next chunk in the linked list.
 
    };
 

	
 
    ChunkHeader *chunkHead_;    //!< Head of the chunk linked-list. Only the head chunk serves allocation.
 
    size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.
 
    void *userBuffer_;          //!< User supplied buffer.
 
    BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.
 
    BaseAllocator* ownBaseAllocator_;   //!< base allocator created by this object.
 
};
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#endif // RAPIDJSON_ENCODINGS_H_
include/rapidjson/cursorstreamwrapper.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
//
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
 
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
 

	
 
#include "stream.h"
 

	
 
#if defined(__GNUC__)
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(effc++)
 
#endif
 

	
 
#if defined(_MSC_VER) && _MSC_VER <= 1800
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 
RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 

	
 
//! Cursor stream wrapper for counting line and column number if error exists.
 
/*!
 
    \tparam InputStream     Any stream that implements Stream Concept
 
*/
 
template <typename InputStream, typename Encoding = UTF8<> >
 
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
 
public:
 
    typedef typename Encoding::Ch Ch;
 

	
 
    CursorStreamWrapper(InputStream& is):
 
        GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
 

	
 
    // counting line and column number
 
    Ch Take() {
 
        Ch ch = this->is_.Take();
 
        if(ch == '\n') {
 
            line_ ++;
 
            col_ = 0;
 
        } else {
 
            col_ ++;
 
        }
 
        return ch;
 
    }
 

	
 
    //! Get the error line number, if error exists.
 
    size_t GetLine() const { return line_; }
 
    //! Get the error column number, if error exists.
 
    size_t GetColumn() const { return col_; }
 

	
 
private:
 
    size_t line_;   //!< Current Line
 
    size_t col_;    //!< Current Column
 
};
 

	
 
#if defined(_MSC_VER) && _MSC_VER <= 1800
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#if defined(__GNUC__)
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
include/rapidjson/document.h
Show inline comments
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_DOCUMENT_H_
 
#define RAPIDJSON_DOCUMENT_H_
 

	
 
/*! \file document.h */
 

	
 
#include "reader.h"
 
#include "internal/meta.h"
 
#include "internal/strfunc.h"
 
#include <new>		// placement new
 
#include "memorystream.h"
 
#include "encodedstream.h"
 
#include <new>      // placement new
 
#include <limits>
 

	
 
RAPIDJSON_DIAG_PUSH
 
#ifdef _MSC_VER
 
#pragma warning(push)
 
#pragma warning(disable : 4127) // conditional expression is constant
 
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
 
#endif
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_OFF(padded)
 
RAPIDJSON_DIAG_OFF(switch-enum)
 
RAPIDJSON_DIAG_OFF(c++98-compat)
 
#endif
 

	
 
#ifdef __GNUC__
 
RAPIDJSON_DIAG_OFF(effc++)
 
#if __GNUC__ >= 6
 
RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
 
#endif
 
#endif // __GNUC__
 

	
 
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
 
#include <iterator> // std::random_access_iterator_tag
 
#endif
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
#include <utility> // std::move
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
// Forward declaration.
 
template <typename Encoding, typename Allocator>
 
class GenericValue;
 

	
 
template <typename Encoding, typename Allocator, typename StackAllocator>
 
class GenericDocument;
 

	
 
//! Name-value pair in a JSON object value.
 
/*!
 
    This class was internal to GenericValue. It used to be a inner struct.
 
    But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
 
    https://code.google.com/p/rapidjson/issues/detail?id=64
 
*/
 
template <typename Encoding, typename Allocator> 
 
struct GenericMember { 
 
    GenericValue<Encoding, Allocator> name;     //!< name of member (must be a string)
 
    GenericValue<Encoding, Allocator> value;    //!< value of member.
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// GenericMemberIterator
 

	
 
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
 

	
 
//! (Constant) member iterator for a JSON object value
 
/*!
 
    \tparam Const Is this a constant iterator?
 
    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
 
    \tparam Allocator   Allocator type for allocating memory of object, array and string.
 

	
 
    This class implements a Random Access Iterator for GenericMember elements
 
    of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
 

	
 
    \note This iterator implementation is mainly intended to avoid implicit
 
        conversions from iterator values to \c NULL,
 
        e.g. from GenericValue::FindMember.
 

	
 
    \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
 
        pointer-based implementation, if your platform doesn't provide
 
        the C++ <iterator> header.
 

	
 
    \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
 
 */
 
template <bool Const, typename Encoding, typename Allocator>
 
class GenericMemberIterator {
 

	
 
    friend class GenericValue<Encoding,Allocator>;
 
    template <bool, typename, typename> friend class GenericMemberIterator;
 

	
 
    typedef GenericMember<Encoding,Allocator> PlainType;
 
    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
 

	
 
public:
 
    //! Iterator type itself
 
    typedef GenericMemberIterator Iterator;
 
    //! Constant iterator type
 
    typedef GenericMemberIterator<true,Encoding,Allocator>  ConstIterator;
 
    //! Non-constant iterator type
 
    typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
 

	
 
    /** \name std::iterator_traits support */
 
    //@{
 
    typedef ValueType      value_type;
 
    typedef ValueType *    pointer;
 
    typedef ValueType &    reference;
 
    typedef std::ptrdiff_t difference_type;
 
    typedef std::random_access_iterator_tag iterator_category;
 
    //@}
 

	
 
    //! Pointer to (const) GenericMember
 
    typedef pointer         Pointer;
 
    //! Reference to (const) GenericMember
 
    typedef reference       Reference;
 
    //! Signed integer type (e.g. \c ptrdiff_t)
 
    typedef difference_type DifferenceType;
 

	
 
    //! Default constructor (singular value)
 
    /*! Creates an iterator pointing to no element.
 
        \note All operations, except for comparisons, are undefined on such values.
 
     */
 
    GenericMemberIterator() : ptr_() {}
 

	
 
    //! Iterator conversions to more const
 
    /*!
 
        \param it (Non-const) iterator to copy from
 

	
 
        Allows the creation of an iterator from another GenericMemberIterator
 
        that is "less const".  Especially, creating a non-constant iterator
 
        from a constant iterator are disabled:
 
        \li const -> non-const (not ok)
 
        \li const -> const (ok)
 
        \li non-const -> const (ok)
 
        \li non-const -> non-const (ok)
 

	
 
        \note If the \c Const template parameter is already \c false, this
 
            constructor effectively defines a regular copy-constructor.
 
            Otherwise, the copy constructor is implicitly defined.
 
    */
 
    GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
 
    Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
 

	
 
    //! @name stepping
 
    //@{
 
    Iterator& operator++(){ ++ptr_; return *this; }
 
    Iterator& operator--(){ --ptr_; return *this; }
 
    Iterator  operator++(int){ Iterator old(*this); ++ptr_; return old; }
 
    Iterator  operator--(int){ Iterator old(*this); --ptr_; return old; }
 
    //@}
 

	
 
    //! @name increment/decrement
 
    //@{
 
    Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
 
    Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
 

	
 
    Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
 
    Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
 
    //@}
 

	
 
    //! @name relations
 
    //@{
 
    bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
 
    bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
 
    bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
 
    bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
 
    bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
 
    bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
 
    //@}
 

	
 
    //! @name dereference
 
    //@{
 
    Reference operator*() const { return *ptr_; }
 
    Pointer   operator->() const { return ptr_; }
 
    Reference operator[](DifferenceType n) const { return ptr_[n]; }
 
    //@}
 

	
 
    //! Distance
 
    DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
 

	
 
private:
 
    //! Internal constructor from plain pointer
 
    explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
 

	
 
    Pointer ptr_; //!< raw pointer
 
};
 

	
 
#else // RAPIDJSON_NOMEMBERITERATORCLASS
 

	
 
// class-based member iterator implementation disabled, use plain pointers
 

	
 
template <bool Const, typename Encoding, typename Allocator>
 
struct GenericMemberIterator;
 

	
 
//! non-const GenericMemberIterator
 
template <typename Encoding, typename Allocator>
 
struct GenericMemberIterator<false,Encoding,Allocator> {
 
    //! use plain pointer as iterator type
 
    typedef GenericMember<Encoding,Allocator>* Iterator;
 
};
 
//! const GenericMemberIterator
 
template <typename Encoding, typename Allocator>
 
struct GenericMemberIterator<true,Encoding,Allocator> {
 
    //! use plain const pointer as iterator type
 
    typedef const GenericMember<Encoding,Allocator>* Iterator;
 
};
 

	
 
#endif // RAPIDJSON_NOMEMBERITERATORCLASS
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// GenericStringRef
 

	
 
//! Reference to a constant string (not taking a copy)
 
/*!
 
    \tparam CharType character type of the string
 

	
 
    This helper class is used to automatically infer constant string
 
    references for string literals, especially from \c const \b (!)
 
    character arrays.
 

	
 
    The main use is for creating JSON string values without copying the
 
    source string via an \ref Allocator.  This requires that the referenced
 
    string pointers have a sufficient lifetime, which exceeds the lifetime
 
    of the associated GenericValue.
 

	
 
    \b Example
 
    \code
 
    Value v("foo");   // ok, no need to copy & calculate length
 
    const char foo[] = "foo";
 
    v.SetString(foo); // ok
 

	
 
    const char* bar = foo;
 
    // Value x(bar); // not ok, can't rely on bar's lifetime
 
    Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
 
    Value y(StringRef(bar, 3));  // ok, explicitly pass length
 
    \endcode
 

	
 
    \see StringRef, GenericValue::SetString
 
*/
 
template<typename CharType>
 
struct GenericStringRef {
 
    typedef CharType Ch; //!< character type of the string
 

	
 
    //! Create string reference from \c const character array
 
#ifndef __clang__ // -Wdocumentation
 
    /*!
 
        This constructor implicitly creates a constant string reference from
 
        a \c const character array.  It has better performance than
 
        \ref StringRef(const CharType*) by inferring the string \ref length
 
        from the array length, and also supports strings containing null
 
        characters.
 

	
 
        \tparam N length of the string, automatically inferred
 

	
 
        \param str Constant character array, lifetime assumed to be longer
 
            than the use of the string in e.g. a GenericValue
 

	
 
        \post \ref s == str
 

	
 
        \note Constant complexity.
 
        \note There is a hidden, private overload to disallow references to
 
            non-const character arrays to be created via this constructor.
 
            By this, e.g. function-scope arrays used to be filled via
 
            \c snprintf are excluded from consideration.
 
            In such cases, the referenced string should be \b copied to the
 
            GenericValue instead.
 
     */
 
#endif
 
    template<SizeType N>
 
    GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
 
        : s(str), length(N-1) {}
 

	
 
    //! Explicitly create string reference from \c const character pointer
 
#ifndef __clang__ // -Wdocumentation
 
    /*!
 
        This constructor can be used to \b explicitly  create a reference to
 
        a constant string pointer.
 

	
 
        \see StringRef(const CharType*)
 

	
 
        \param str Constant character pointer, lifetime assumed to be longer
 
            than the use of the string in e.g. a GenericValue
 

	
 
        \post \ref s == str
 

	
 
        \note There is a hidden, private overload to disallow references to
 
            non-const character arrays to be created via this constructor.
 
            By this, e.g. function-scope arrays used to be filled via
 
            \c snprintf are excluded from consideration.
 
            In such cases, the referenced string should be \b copied to the
 
            GenericValue instead.
 
     */
 
#endif
 
    explicit GenericStringRef(const CharType* str)
 
        : s(str), length(NotNullStrLen(str)) {}
 

	
 
    //! Create constant string reference from pointer and length
 
#ifndef __clang__ // -Wdocumentation
 
    /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
 
        \param len length of the string, excluding the trailing NULL terminator
 

	
 
        \post \ref s == str && \ref length == len
 
        \note Constant complexity.
 
     */
 
#endif
 
    GenericStringRef(const CharType* str, SizeType len)
 
        : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); }
 

	
 
    GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
 

	
 
    //! implicit conversion to plain CharType pointer
 
    operator const Ch *() const { return s; }
 

	
 
    const Ch* const s; //!< plain CharType pointer
 
    const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
 

	
 
private:
 
    SizeType NotNullStrLen(const CharType* str) {
 
        RAPIDJSON_ASSERT(str != 0);
 
        return internal::StrLen(str);
 
    }
 

	
 
    /// Empty string - used when passing in a NULL pointer
 
    static const Ch emptyString[];
 

	
 
    //! Disallow construction from non-const array
 
    template<SizeType N>
 
    GenericStringRef(CharType (&str)[N]) /* = delete */;
 
    //! Copy assignment operator not permitted - immutable type
 
    GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
 
};
 

	
 
template<typename CharType>
 
const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
 

	
 
//! Mark a character pointer as constant string
 
/*! Mark a plain character pointer as a "string literal".  This function
 
    can be used to avoid copying a character string to be referenced as a
 
    value in a JSON GenericValue object, if the string's lifetime is known
 
    to be valid long enough.
 
    \tparam CharType Character type of the string
 
    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
 
    \return GenericStringRef string reference object
 
    \relatesalso GenericStringRef
 

	
 
    \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
 
*/
 
template<typename CharType>
 
inline GenericStringRef<CharType> StringRef(const CharType* str) {
 
    return GenericStringRef<CharType>(str);
 
}
 

	
 
//! Mark a character pointer as constant string
 
/*! Mark a plain character pointer as a "string literal".  This function
 
    can be used to avoid copying a character string to be referenced as a
 
    value in a JSON GenericValue object, if the string's lifetime is known
 
    to be valid long enough.
 

	
 
    This version has better performance with supplied length, and also
 
    supports string containing null characters.
 

	
 
    \tparam CharType character type of the string
 
    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
 
    \param length The length of source string.
 
    \return GenericStringRef string reference object
 
    \relatesalso GenericStringRef
 
*/
 
template<typename CharType>
 
inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
 
    return GenericStringRef<CharType>(str, SizeType(length));
 
}
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
//! Mark a string object as constant string
 
/*! Mark a string object (e.g. \c std::string) as a "string literal".
 
    This function can be used to avoid copying a string to be referenced as a
 
    value in a JSON GenericValue object, if the string's lifetime is known
 
    to be valid long enough.
 

	
 
    \tparam CharType character type of the string
 
    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
 
    \return GenericStringRef string reference object
 
    \relatesalso GenericStringRef
 
    \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
 
*/
 
template<typename CharType>
 
inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
 
    return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
 
}
 
#endif
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// GenericValue type traits
 
namespace internal {
 

	
 
template <typename T, typename Encoding = void, typename Allocator = void>
 
struct IsGenericValueImpl : FalseType {};
 

	
 
// select candidates according to nested encoding and allocator types
 
template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
 
    : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
 

	
 
// helper to match arbitrary GenericValue instantiations, including derived classes
 
template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
 

	
 
} // namespace internal
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// TypeHelper
 

	
 
namespace internal {
 

	
 
template <typename ValueType, typename T>
 
struct TypeHelper {};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, bool> {
 
    static bool Is(const ValueType& v) { return v.IsBool(); }
 
    static bool Get(const ValueType& v) { return v.GetBool(); }
 
    static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
 
    static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, int> {
 
    static bool Is(const ValueType& v) { return v.IsInt(); }
 
    static int Get(const ValueType& v) { return v.GetInt(); }
 
    static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
 
    static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, unsigned> {
 
    static bool Is(const ValueType& v) { return v.IsUint(); }
 
    static unsigned Get(const ValueType& v) { return v.GetUint(); }
 
    static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
 
    static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
 
};
 

	
 
#ifdef _MSC_VER
 
RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int));
 
template<typename ValueType>
 
struct TypeHelper<ValueType, long> {
 
    static bool Is(const ValueType& v) { return v.IsInt(); }
 
    static long Get(const ValueType& v) { return v.GetInt(); }
 
    static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); }
 
    static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
 
};
 

	
 
RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned));
 
template<typename ValueType>
 
struct TypeHelper<ValueType, unsigned long> {
 
    static bool Is(const ValueType& v) { return v.IsUint(); }
 
    static unsigned long Get(const ValueType& v) { return v.GetUint(); }
 
    static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); }
 
    static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
 
};
 
#endif
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, int64_t> {
 
    static bool Is(const ValueType& v) { return v.IsInt64(); }
 
    static int64_t Get(const ValueType& v) { return v.GetInt64(); }
 
    static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
 
    static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, uint64_t> {
 
    static bool Is(const ValueType& v) { return v.IsUint64(); }
 
    static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
 
    static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
 
    static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, double> {
 
    static bool Is(const ValueType& v) { return v.IsDouble(); }
 
    static double Get(const ValueType& v) { return v.GetDouble(); }
 
    static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
 
    static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, float> {
 
    static bool Is(const ValueType& v) { return v.IsFloat(); }
 
    static float Get(const ValueType& v) { return v.GetFloat(); }
 
    static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
 
    static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, const typename ValueType::Ch*> {
 
    typedef const typename ValueType::Ch* StringType;
 
    static bool Is(const ValueType& v) { return v.IsString(); }
 
    static StringType Get(const ValueType& v) { return v.GetString(); }
 
    static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
 
    static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
 
};
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
 
    typedef std::basic_string<typename ValueType::Ch> StringType;
 
    static bool Is(const ValueType& v) { return v.IsString(); }
 
    static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
 
    static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
 
};
 
#endif
 

	
 
namespace rapidjson {
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, typename ValueType::Array> {
 
    typedef typename ValueType::Array ArrayType;
 
    static bool Is(const ValueType& v) { return v.IsArray(); }
 
    static ArrayType Get(ValueType& v) { return v.GetArray(); }
 
    static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
 
    static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
 
    typedef typename ValueType::ConstArray ArrayType;
 
    static bool Is(const ValueType& v) { return v.IsArray(); }
 
    static ArrayType Get(const ValueType& v) { return v.GetArray(); }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, typename ValueType::Object> {
 
    typedef typename ValueType::Object ObjectType;
 
    static bool Is(const ValueType& v) { return v.IsObject(); }
 
    static ObjectType Get(ValueType& v) { return v.GetObject(); }
 
    static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
 
    static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }
 
};
 

	
 
template<typename ValueType> 
 
struct TypeHelper<ValueType, typename ValueType::ConstObject> {
 
    typedef typename ValueType::ConstObject ObjectType;
 
    static bool Is(const ValueType& v) { return v.IsObject(); }
 
    static ObjectType Get(const ValueType& v) { return v.GetObject(); }
 
};
 

	
 
} // namespace internal
 

	
 
// Forward declarations
 
template <bool, typename> class GenericArray;
 
template <bool, typename> class GenericObject;
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// GenericValue
 

	
 
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
 
/*!
 
	A JSON value can be one of 7 types. This class is a variant type supporting
 
	these types.
 
    A JSON value can be one of 7 types. This class is a variant type supporting
 
    these types.
 

	
 
	Use the Value if UTF8 and default allocator
 
    Use the Value if UTF8 and default allocator
 

	
 
	\tparam Encoding	Encoding of the value. (Even non-string values need to have the same encoding in a document)
 
	\tparam Allocator	Allocator type for allocating memory of object, array and string.
 
    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
 
    \tparam Allocator   Allocator type for allocating memory of object, array and string.
 
*/
 
#pragma pack (push, 4)
 
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > 
 
class GenericValue {
 
public:
 
	//! Name-value pair in an object.
 
	struct Member { 
 
		GenericValue<Encoding, Allocator> name;		//!< name of member (must be a string)
 
		GenericValue<Encoding, Allocator> value;	//!< value of member.
 
	};
 

	
 
	typedef Encoding EncodingType;					//!< Encoding type from template parameter.
 
	typedef Allocator AllocatorType;				//!< Allocator type from template parameter.
 
	typedef typename Encoding::Ch Ch;				//!< Character type derived from Encoding.
 
	typedef Member* MemberIterator;					//!< Member iterator for iterating in object.
 
	typedef const Member* ConstMemberIterator;		//!< Constant member iterator for iterating in object.
 
	typedef GenericValue* ValueIterator;			//!< Value iterator for iterating in array.
 
	typedef const GenericValue* ConstValueIterator;	//!< Constant value iterator for iterating in array.
 

	
 
	//!@name Constructors and destructor.
 
	//@{
 

	
 
	//! Default constructor creates a null value.
 
	GenericValue() : flags_(kNullFlag) {}
 

	
 
	//! Copy constructor is not permitted.
 
    //! Name-value pair in an object.
 
    typedef GenericMember<Encoding, Allocator> Member;
 
    typedef Encoding EncodingType;                  //!< Encoding type from template parameter.
 
    typedef Allocator AllocatorType;                //!< Allocator type from template parameter.
 
    typedef typename Encoding::Ch Ch;               //!< Character type derived from Encoding.
 
    typedef GenericStringRef<Ch> StringRefType;     //!< Reference to a constant string
 
    typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;  //!< Member iterator for iterating in object.
 
    typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator;  //!< Constant member iterator for iterating in object.
 
    typedef GenericValue* ValueIterator;            //!< Value iterator for iterating in array.
 
    typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
 
    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of itself.
 
    typedef GenericArray<false, ValueType> Array;
 
    typedef GenericArray<true, ValueType> ConstArray;
 
    typedef GenericObject<false, ValueType> Object;
 
    typedef GenericObject<true, ValueType> ConstObject;
 

	
 
    //!@name Constructors and destructor.
 
    //@{
 

	
 
    //! Default constructor creates a null value.
 
    GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    //! Move constructor in C++11
 
    GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
 
        rhs.data_.f.flags = kNullFlag; // give up contents
 
    }
 
#endif
 

	
 
private:
 
	GenericValue(const GenericValue& rhs);
 
    //! Copy constructor is not permitted.
 
    GenericValue(const GenericValue& rhs);
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    //! Moving from a GenericDocument is not permitted.
 
    template <typename StackAllocator>
 
    GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
 

	
 
    //! Move assignment from a GenericDocument is not permitted.
 
    template <typename StackAllocator>
 
    GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
 
#endif
 

	
 
public:
 

	
 
	//! Constructor with JSON value type.
 
	/*! This creates a Value of specified type with default content.
 
		\param type	Type of the value.
 
		\note Default content for number is zero.
 
	*/
 
	GenericValue(Type type) {
 
		static const unsigned defaultFlags[7] = {
 
			kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
 
			kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag
 
		};
 
		RAPIDJSON_ASSERT(type <= kNumberType);
 
		flags_ = defaultFlags[type];
 
		memset(&data_, 0, sizeof(data_));
 
	}
 

	
 
	//! Constructor for boolean value.
 
	GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {}
 

	
 
	//! Constructor for int value.
 
	GenericValue(int i) : flags_(kNumberIntFlag) { 
 
		data_.n.i64 = i;
 
		if (i >= 0)
 
			flags_ |= kUintFlag | kUint64Flag;
 
	}
 

	
 
	//! Constructor for unsigned value.
 
	GenericValue(unsigned u) : flags_(kNumberUintFlag) {
 
		data_.n.u64 = u; 
 
		if (!(u & 0x80000000))
 
			flags_ |= kIntFlag | kInt64Flag;
 
	}
 

	
 
	//! Constructor for int64_t value.
 
	GenericValue(int64_t i64) : flags_(kNumberInt64Flag) {
 
		data_.n.i64 = i64;
 
		if (i64 >= 0) {
 
			flags_ |= kNumberUint64Flag;
 
			if (!(i64 & 0xFFFFFFFF00000000LL))
 
				flags_ |= kUintFlag;
 
			if (!(i64 & 0xFFFFFFFF80000000LL))
 
				flags_ |= kIntFlag;
 
		}
 
		else if (i64 >= -2147483648LL)
 
			flags_ |= kIntFlag;
 
	}
 

	
 
	//! Constructor for uint64_t value.
 
	GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) {
 
		data_.n.u64 = u64;
 
		if (!(u64 & 0x8000000000000000ULL))
 
			flags_ |= kInt64Flag;
 
		if (!(u64 & 0xFFFFFFFF00000000ULL))
 
			flags_ |= kUintFlag;
 
		if (!(u64 & 0xFFFFFFFF80000000ULL))
 
			flags_ |= kIntFlag;
 
	}
 

	
 
	//! Constructor for double value.
 
	GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; }
 

	
 
	//! Constructor for constant string (i.e. do not make a copy of string)
 
	GenericValue(const Ch* s, SizeType length) { 
 
		RAPIDJSON_ASSERT(s != NULL);
 
		flags_ = kConstStringFlag;
 
		data_.s.str = s;
 
		data_.s.length = length;
 
	}
 

	
 
	//! Constructor for constant string (i.e. do not make a copy of string)
 
	GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); }
 

	
 
	//! Constructor for copy-string (i.e. do make a copy of string)
 
	GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); }
 

	
 
	//! Constructor for copy-string (i.e. do make a copy of string)
 
	GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); }
 

	
 
	//! Destructor.
 
	/*! Need to destruct elements of array, members of object, or copy-string.
 
	*/
 
	~GenericValue() {
 
		if (Allocator::kNeedFree) {	// Shortcut by Allocator's trait
 
			switch(flags_) {
 
			case kArrayFlag:
 
				for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
 
					v->~GenericValue();
 
				Allocator::Free(data_.a.elements);
 
				break;
 

	
 
			case kObjectFlag:
 
				for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
 
					m->name.~GenericValue();
 
					m->value.~GenericValue();
 
				}
 
				Allocator::Free(data_.o.members);
 
				break;
 

	
 
			case kCopyStringFlag:
 
				Allocator::Free(const_cast<Ch*>(data_.s.str));
 
				break;
 
			}
 
		}
 
	}
 

	
 
	//@}
 

	
 
	//!@name Assignment operators
 
	//@{
 

	
 
	//! Assignment with move semantics.
 
	/*! \param rhs Source of the assignment. It will become a null value after assignment.
 
	*/
 
	GenericValue& operator=(GenericValue& rhs) {
 
		RAPIDJSON_ASSERT(this != &rhs);
 
		this->~GenericValue();
 
		memcpy(this, &rhs, sizeof(GenericValue));
 
		rhs.flags_ = kNullFlag;
 
		return *this;
 
	}
 

	
 
	//! Assignment with primitive types.
 
	/*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch*
 
		\param value The value to be assigned.
 
	*/
 
	template <typename T>
 
	GenericValue& operator=(T value) {
 
		this->~GenericValue();
 
		new (this) GenericValue(value);
 
		return *this;
 
	}
 
	//@}
 

	
 
	//!@name Type
 
	//@{
 

	
 
	Type GetType()	const { return static_cast<Type>(flags_ & kTypeMask); }
 
	bool IsNull()	const { return flags_ == kNullFlag; }
 
	bool IsFalse()	const { return flags_ == kFalseFlag; }
 
	bool IsTrue()	const { return flags_ == kTrueFlag; }
 
	bool IsBool()	const { return (flags_ & kBoolFlag) != 0; }
 
	bool IsObject()	const { return flags_ == kObjectFlag; }
 
	bool IsArray()	const { return flags_ == kArrayFlag; }
 
	bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
 
	bool IsInt()	const { return (flags_ & kIntFlag) != 0; }
 
	bool IsUint()	const { return (flags_ & kUintFlag) != 0; }
 
	bool IsInt64()	const { return (flags_ & kInt64Flag) != 0; }
 
	bool IsUint64()	const { return (flags_ & kUint64Flag) != 0; }
 
	bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
 
	bool IsString() const { return (flags_ & kStringFlag) != 0; }
 

	
 
	//@}
 

	
 
	//!@name Null
 
	//@{
 

	
 
	GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
 

	
 
	//@}
 

	
 
	//!@name Bool
 
	//@{
 

	
 
	bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
 
	GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
 

	
 
	//@}
 

	
 
	//!@name Object
 
	//@{
 

	
 
	//! Set this value as an empty object.
 
	GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
 

	
 
	//! Get the value associated with the object's name.
 
	GenericValue& operator[](const Ch* name) {
 
		if (Member* member = FindMember(name))
 
			return member->value;
 
		else {
 
			static GenericValue NullValue;
 
			return NullValue;
 
		}
 
	}
 
	const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
 

	
 
	//! Member iterators.
 
	ConstMemberIterator MemberBegin() const	{ RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
 
	ConstMemberIterator MemberEnd()	const	{ RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
 
	MemberIterator MemberBegin()			{ RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
 
	MemberIterator MemberEnd()				{ RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
 

	
 
	//! Check whether a member exists in the object.
 
	bool HasMember(const Ch* name) const { return FindMember(name) != 0; }
 

	
 
	//! Add a member (name-value pair) to the object.
 
	/*! \param name A string value as name of member.
 
		\param value Value of any type.
 
	    \param allocator Allocator for reallocating memory.
 
	    \return The value itself for fluent API.
 
	    \note The ownership of name and value will be transfered to this object if success.
 
	*/
 
	GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
 
		RAPIDJSON_ASSERT(IsObject());
 
		RAPIDJSON_ASSERT(name.IsString());
 
		Object& o = data_.o;
 
		if (o.size >= o.capacity) {
 
			if (o.capacity == 0) {
 
				o.capacity = kDefaultObjectCapacity;
 
				o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member));
 
			}
 
			else {
 
				SizeType oldCapacity = o.capacity;
 
				o.capacity *= 2;
 
				o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member));
 
			}
 
		}
 
		o.members[o.size].name.RawAssign(name);
 
		o.members[o.size].value.RawAssign(value);
 
		o.size++;
 
		return *this;
 
	}
 

	
 
	GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) {
 
		GenericValue n(name, internal::StrLen(name), nameAllocator);
 
		return AddMember(n, value, allocator);
 
	}
 

	
 
	GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) {
 
		GenericValue n(name, internal::StrLen(name));
 
		return AddMember(n, value, allocator);
 
	}
 

	
 
	template <typename T>
 
	GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) {
 
		GenericValue n(name, internal::StrLen(name));
 
		GenericValue v(value);
 
		return AddMember(n, v, allocator);
 
	}
 

	
 
	//! Remove a member in object by its name.
 
	/*! \param name Name of member to be removed.
 
	    \return Whether the member existed.
 
	    \note Removing member is implemented by moving the last member. So the ordering of members is changed.
 
	*/
 
	bool RemoveMember(const Ch* name) {
 
		RAPIDJSON_ASSERT(IsObject());
 
		if (Member* m = FindMember(name)) {
 
			RAPIDJSON_ASSERT(data_.o.size > 0);
 
			RAPIDJSON_ASSERT(data_.o.members != 0);
 

	
 
			Member* last = data_.o.members + (data_.o.size - 1);
 
			if (data_.o.size > 1 && m != last) {
 
				// Move the last one to this place
 
				m->name = last->name;
 
				m->value = last->value;
 
			}
 
			else {
 
				// Only one left, just destroy
 
				m->name.~GenericValue();
 
				m->value.~GenericValue();
 
			}
 
			--data_.o.size;
 
			return true;
 
		}
 
		return false;
 
	}
 

	
 
	//@}
 

	
 
	//!@name Array
 
	//@{
 

	
 
	//! Set this value as an empty array.
 
	GenericValue& SetArray() {	this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
 

	
 
	//! Get the number of elements in array.
 
	SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
 

	
 
	//! Get the capacity of array.
 
	SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
 

	
 
	//! Check whether the array is empty.
 
	bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
 

	
 
	//! Remove all elements in the array.
 
	/*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
 
	*/
 
	void Clear() {
 
		RAPIDJSON_ASSERT(IsArray()); 
 
		for (SizeType i = 0; i < data_.a.size; ++i)
 
			data_.a.elements[i].~GenericValue();
 
		data_.a.size = 0;
 
	}
 

	
 
	//! Get an element from array by index.
 
	/*! \param index Zero-based index of element.
 
		\note
 
\code
 
Value a(kArrayType);
 
a.PushBack(123);
 
int x = a[0].GetInt();				// Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
 
int y = a[SizeType(0)].GetInt();	// Cast to SizeType will work.
 
int z = a[0u].GetInt();				// This works too.
 
\endcode
 
	*/
 
	GenericValue& operator[](SizeType index) {
 
		RAPIDJSON_ASSERT(IsArray());
 
		RAPIDJSON_ASSERT(index < data_.a.size);
 
		return data_.a.elements[index];
 
	}
 
	const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
 

	
 
	//! Element iterator
 
	ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
 
	ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
 
	ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
 
	ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
 

	
 
	//! Request the array to have enough capacity to store elements.
 
	/*! \param newCapacity	The capacity that the array at least need to have.
 
		\param allocator	The allocator for allocating memory. It must be the same one use previously.
 
		\return The value itself for fluent API.
 
	*/
 
	GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
 
		RAPIDJSON_ASSERT(IsArray());
 
		if (newCapacity > data_.a.capacity) {
 
			data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
 
			data_.a.capacity = newCapacity;
 
		}
 
		return *this;
 
	}
 

	
 
	//! Append a value at the end of the array.
 
	/*! \param value		The value to be appended.
 
	    \param allocator	The allocator for allocating memory. It must be the same one use previously.
 
	    \return The value itself for fluent API.
 
	    \note The ownership of the value will be transfered to this object if success.
 
	    \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
 
	*/
 
	GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
 
		RAPIDJSON_ASSERT(IsArray());
 
		if (data_.a.size >= data_.a.capacity)
 
			Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator);
 
		data_.a.elements[data_.a.size++].RawAssign(value);
 
		return *this;
 
	}
 

	
 
	template <typename T>
 
	GenericValue& PushBack(T value, Allocator& allocator) {
 
		GenericValue v(value);
 
		return PushBack(v, allocator);
 
	}
 

	
 
	//! Remove the last element in the array.
 
	GenericValue& PopBack() {
 
		RAPIDJSON_ASSERT(IsArray());
 
		RAPIDJSON_ASSERT(!Empty());
 
		data_.a.elements[--data_.a.size].~GenericValue();
 
		return *this;
 
	}
 
	//@}
 

	
 
	//!@name Number
 
	//@{
 

	
 
	int GetInt() const			{ RAPIDJSON_ASSERT(flags_ & kIntFlag);   return data_.n.i.i;   }
 
	unsigned GetUint() const	{ RAPIDJSON_ASSERT(flags_ & kUintFlag);  return data_.n.u.u;   }
 
	int64_t GetInt64() const	{ RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
 
	uint64_t GetUint64() const	{ RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
 

	
 
	double GetDouble() const {
 
		RAPIDJSON_ASSERT(IsNumber());
 
		if ((flags_ & kDoubleFlag) != 0)				return data_.n.d;	// exact type, no conversion.
 
		if ((flags_ & kIntFlag) != 0)					return data_.n.i.i;	// int -> double
 
		if ((flags_ & kUintFlag) != 0)					return data_.n.u.u;	// unsigned -> double
 
		if ((flags_ & kInt64Flag) != 0)					return (double)data_.n.i64; // int64_t -> double (may lose precision)
 
		RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0);	return (double)data_.n.u64;	// uint64_t -> double (may lose precision)
 
	}
 

	
 
	GenericValue& SetInt(int i)				{ this->~GenericValue(); new (this) GenericValue(i);	return *this; }
 
	GenericValue& SetUint(unsigned u)		{ this->~GenericValue(); new (this) GenericValue(u);	return *this; }
 
	GenericValue& SetInt64(int64_t i64)		{ this->~GenericValue(); new (this) GenericValue(i64);	return *this; }
 
	GenericValue& SetUint64(uint64_t u64)	{ this->~GenericValue(); new (this) GenericValue(u64);	return *this; }
 
	GenericValue& SetDouble(double d)		{ this->~GenericValue(); new (this) GenericValue(d);	return *this; }
 

	
 
	//@}
 

	
 
	//!@name String
 
	//@{
 

	
 
	const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; }
 

	
 
	//! Get the length of string.
 
	/*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
 
	*/
 
	SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; }
 

	
 
	//! Set this value as a string without copying source string.
 
	/*! This version has better performance with supplied length, and also support string containing null character.
 
		\param s source string pointer. 
 
		\param length The length of source string, excluding the trailing null terminator.
 
		\return The value itself for fluent API.
 
	*/
 
	GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; }
 

	
 
	//! Set this value as a string without copying source string.
 
	/*! \param s source string pointer. 
 
		\return The value itself for fluent API.
 
	*/
 
	GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); }
 

	
 
	//! Set this value as a string by copying from source string.
 
	/*! This version has better performance with supplied length, and also support string containing null character.
 
		\param s source string. 
 
		\param length The length of source string, excluding the trailing null terminator.
 
		\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
 
		\return The value itself for fluent API.
 
	*/
 
	GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; }
 

	
 
	//! Set this value as a string by copying from source string.
 
	/*!	\param s source string. 
 
		\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
 
		\return The value itself for fluent API.
 
	*/
 
	GenericValue& SetString(const Ch* s, Allocator& allocator) {	SetString(s, internal::StrLen(s), allocator); return *this; }
 

	
 
	//@}
 

	
 
	//! Generate events of this value to a Handler.
 
	/*! This function adopts the GoF visitor pattern.
 
		Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
 
		It can also be used to deep clone this value via GenericDocument, which is also a Handler.
 
		\tparam Handler type of handler.
 
		\param handler An object implementing concept Handler.
 
	*/
 
	template <typename Handler>
 
	const GenericValue& Accept(Handler& handler) const {
 
		switch(GetType()) {
 
		case kNullType:		handler.Null(); break;
 
		case kFalseType:	handler.Bool(false); break;
 
		case kTrueType:		handler.Bool(true); break;
 

	
 
		case kObjectType:
 
			handler.StartObject();
 
			for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
 
				handler.String(m->name.data_.s.str, m->name.data_.s.length, false);
 
				m->value.Accept(handler);
 
			}
 
			handler.EndObject(data_.o.size);
 
			break;
 

	
 
		case kArrayType:
 
			handler.StartArray();
 
			for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
 
				v->Accept(handler);
 
			handler.EndArray(data_.a.size);
 
			break;
 

	
 
		case kStringType:
 
			handler.String(data_.s.str, data_.s.length, false);
 
			break;
 

	
 
		case kNumberType:
 
			if (IsInt())			handler.Int(data_.n.i.i);
 
			else if (IsUint())		handler.Uint(data_.n.u.u);
 
			else if (IsInt64())		handler.Int64(data_.n.i64);
 
			else if (IsUint64())	handler.Uint64(data_.n.u64);
 
			else					handler.Double(data_.n.d);
 
			break;
 
		}
 
		return *this;
 
	}
 
    //! Constructor with JSON value type.
 
    /*! This creates a Value of specified type with default content.
 
        \param type Type of the value.
 
        \note Default content for number is zero.
 
    */
 
    explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
 
        static const uint16_t defaultFlags[7] = {
 
            kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
 
            kNumberAnyFlag
 
        };
 
        RAPIDJSON_ASSERT(type >= kNullType && type <= kNumberType);
 
        data_.f.flags = defaultFlags[type];
 

	
 
        // Use ShortString to store empty string.
 
        if (type == kStringType)
 
            data_.ss.SetLength(0);
 
    }
 

	
 
    //! Explicit copy constructor (with allocator)
 
    /*! Creates a copy of a Value by using the given Allocator
 
        \tparam SourceAllocator allocator of \c rhs
 
        \param rhs Value to copy from (read-only)
 
        \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
 
        \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
 
        \see CopyFrom()
 
    */
 
    template <typename SourceAllocator>
 
    GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
 
        switch (rhs.GetType()) {
 
        case kObjectType: {
 
                SizeType count = rhs.data_.o.size;
 
                Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
 
                const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
 
                for (SizeType i = 0; i < count; i++) {
 
                    new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
 
                    new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
 
                }
 
                data_.f.flags = kObjectFlag;
 
                data_.o.size = data_.o.capacity = count;
 
                SetMembersPointer(lm);
 
            }
 
            break;
 
        case kArrayType: {
 
                SizeType count = rhs.data_.a.size;
 
                GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
 
                const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();
 
                for (SizeType i = 0; i < count; i++)
 
                    new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);
 
                data_.f.flags = kArrayFlag;
 
                data_.a.size = data_.a.capacity = count;
 
                SetElementsPointer(le);
 
            }
 
            break;
 
        case kStringType:
 
            if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
 
                data_.f.flags = rhs.data_.f.flags;
 
                data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 
            }
 
            else
 
                SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
 
            break;
 
        default:
 
            data_.f.flags = rhs.data_.f.flags;
 
            data_  = *reinterpret_cast<const Data*>(&rhs.data_);
 
            break;
 
        }
 
    }
 

	
 
    //! Constructor for boolean value.
 
    /*! \param b Boolean value
 
        \note This constructor is limited to \em real boolean values and rejects
 
            implicitly converted types like arbitrary pointers.  Use an explicit cast
 
            to \c bool, if you want to construct a boolean JSON value in such cases.
 
     */
 
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
 
    template <typename T>
 
    explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT  // See #472
 
#else
 
    explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
 
#endif
 
        : data_() {
 
            // safe-guard against failing SFINAE
 
            RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
 
            data_.f.flags = b ? kTrueFlag : kFalseFlag;
 
    }
 

	
 
    //! Constructor for int value.
 
    explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
 
        data_.n.i64 = i;
 
        data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
 
    }
 

	
 
    //! Constructor for unsigned value.
 
    explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
 
        data_.n.u64 = u; 
 
        data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
 
    }
 

	
 
    //! Constructor for int64_t value.
 
    explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
 
        data_.n.i64 = i64;
 
        data_.f.flags = kNumberInt64Flag;
 
        if (i64 >= 0) {
 
            data_.f.flags |= kNumberUint64Flag;
 
            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
 
                data_.f.flags |= kUintFlag;
 
            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
 
                data_.f.flags |= kIntFlag;
 
        }
 
        else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
 
            data_.f.flags |= kIntFlag;
 
    }
 

	
 
    //! Constructor for uint64_t value.
 
    explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
 
        data_.n.u64 = u64;
 
        data_.f.flags = kNumberUint64Flag;
 
        if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
 
            data_.f.flags |= kInt64Flag;
 
        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
 
            data_.f.flags |= kUintFlag;
 
        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
 
            data_.f.flags |= kIntFlag;
 
    }
 

	
 
    //! Constructor for double value.
 
    explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
 

	
 
    //! Constructor for float value.
 
    explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
 

	
 
    //! Constructor for constant string (i.e. do not make a copy of string)
 
    GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
 

	
 
    //! Constructor for constant string (i.e. do not make a copy of string)
 
    explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
 

	
 
    //! Constructor for copy-string (i.e. do make a copy of string)
 
    GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
 

	
 
    //! Constructor for copy-string (i.e. do make a copy of string)
 
    GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Constructor for copy-string from a string object (i.e. do make a copy of string)
 
    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
 
     */
 
    GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
 
#endif
 

	
 
    //! Constructor for Array.
 
    /*!
 
        \param a An array obtained by \c GetArray().
 
        \note \c Array is always pass-by-value.
 
        \note the source array is moved into this value and the sourec array becomes empty.
 
    */
 
    GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
 
        a.value_.data_ = Data();
 
        a.value_.data_.f.flags = kArrayFlag;
 
    }
 

	
 
    //! Constructor for Object.
 
    /*!
 
        \param o An object obtained by \c GetObject().
 
        \note \c Object is always pass-by-value.
 
        \note the source object is moved into this value and the sourec object becomes empty.
 
    */
 
    GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
 
        o.value_.data_ = Data();
 
        o.value_.data_.f.flags = kObjectFlag;
 
    }
 

	
 
    //! Destructor.
 
    /*! Need to destruct elements of array, members of object, or copy-string.
 
    */
 
    ~GenericValue() {
 
        if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
 
            switch(data_.f.flags) {
 
            case kArrayFlag:
 
                {
 
                    GenericValue* e = GetElementsPointer();
 
                    for (GenericValue* v = e; v != e + data_.a.size; ++v)
 
                        v->~GenericValue();
 
                    Allocator::Free(e);
 
                }
 
                break;
 

	
 
            case kObjectFlag:
 
                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 
                    m->~Member();
 
                Allocator::Free(GetMembersPointer());
 
                break;
 

	
 
            case kCopyStringFlag:
 
                Allocator::Free(const_cast<Ch*>(GetStringPointer()));
 
                break;
 

	
 
            default:
 
                break;  // Do nothing for other types.
 
            }
 
        }
 
    }
 

	
 
    //@}
 

	
 
    //!@name Assignment operators
 
    //@{
 

	
 
    //! Assignment with move semantics.
 
    /*! \param rhs Source of the assignment. It will become a null value after assignment.
 
    */
 
    GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
 
        RAPIDJSON_ASSERT(this != &rhs);
 
        this->~GenericValue();
 
        RawAssign(rhs);
 
        return *this;
 
    }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    //! Move assignment in C++11
 
    GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
 
        return *this = rhs.Move();
 
    }
 
#endif
 

	
 
    //! Assignment of constant string reference (no copy)
 
    /*! \param str Constant string reference to be assigned
 
        \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
 
        \see GenericStringRef, operator=(T)
 
    */
 
    GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
 
        GenericValue s(str);
 
        return *this = s;
 
    }
 

	
 
    //! Assignment with primitive types.
 
    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
 
        \param value The value to be assigned.
 

	
 
        \note The source type \c T explicitly disallows all pointer types,
 
            especially (\c const) \ref Ch*.  This helps avoiding implicitly
 
            referencing character strings with insufficient lifetime, use
 
            \ref SetString(const Ch*, Allocator&) (for copying) or
 
            \ref StringRef() (to explicitly mark the pointer as constant) instead.
 
            All other pointer types would implicitly convert to \c bool,
 
            use \ref SetBool() instead.
 
    */
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
 
    operator=(T value) {
 
        GenericValue v(value);
 
        return *this = v;
 
    }
 

	
 
    //! Deep-copy assignment from Value
 
    /*! Assigns a \b copy of the Value to the current Value object
 
        \tparam SourceAllocator Allocator type of \c rhs
 
        \param rhs Value to copy from (read-only)
 
        \param allocator Allocator to use for copying
 
        \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
 
     */
 
    template <typename SourceAllocator>
 
    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
 
        RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
 
        this->~GenericValue();
 
        new (this) GenericValue(rhs, allocator, copyConstStrings);
 
        return *this;
 
    }
 

	
 
    //! Exchange the contents of this value with those of other.
 
    /*!
 
        \param other Another value.
 
        \note Constant complexity.
 
    */
 
    GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
 
        GenericValue temp;
 
        temp.RawAssign(*this);
 
        RawAssign(other);
 
        other.RawAssign(temp);
 
        return *this;
 
    }
 

	
 
    //! free-standing swap function helper
 
    /*!
 
        Helper function to enable support for common swap implementation pattern based on \c std::swap:
 
        \code
 
        void swap(MyClass& a, MyClass& b) {
 
            using std::swap;
 
            swap(a.value, b.value);
 
            // ...
 
        }
 
        \endcode
 
        \see Swap()
 
     */
 
    friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
 

	
 
    //! Prepare Value for move semantics
 
    /*! \return *this */
 
    GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
 
    //@}
 

	
 
    //!@name Equal-to and not-equal-to operators
 
    //@{
 
    //! Equal-to operator
 
    /*!
 
        \note If an object contains duplicated named member, comparing equality with any object is always \c false.
 
        \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
 
    */
 
    template <typename SourceAllocator>
 
    bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
 
        typedef GenericValue<Encoding, SourceAllocator> RhsType;
 
        if (GetType() != rhs.GetType())
 
            return false;
 

	
 
        switch (GetType()) {
 
        case kObjectType: // Warning: O(n^2) inner-loop
 
            if (data_.o.size != rhs.data_.o.size)
 
                return false;           
 
            for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
 
                typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
 
                if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
 
                    return false;
 
            }
 
            return true;
 
            
 
        case kArrayType:
 
            if (data_.a.size != rhs.data_.a.size)
 
                return false;
 
            for (SizeType i = 0; i < data_.a.size; i++)
 
                if ((*this)[i] != rhs[i])
 
                    return false;
 
            return true;
 

	
 
        case kStringType:
 
            return StringEqual(rhs);
 

	
 
        case kNumberType:
 
            if (IsDouble() || rhs.IsDouble()) {
 
                double a = GetDouble();     // May convert from integer to double.
 
                double b = rhs.GetDouble(); // Ditto
 
                return a >= b && a <= b;    // Prevent -Wfloat-equal
 
            }
 
            else
 
                return data_.n.u64 == rhs.data_.n.u64;
 

	
 
        default:
 
            return true;
 
        }
 
    }
 

	
 
    //! Equal-to operator with const C-string pointer
 
    bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Equal-to operator with string object
 
    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
 
     */
 
    bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
 
#endif
 

	
 
    //! Equal-to operator with primitive types
 
    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
 
    */
 
    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
 

	
 
    //! Not-equal-to operator
 
    /*! \return !(*this == rhs)
 
     */
 
    template <typename SourceAllocator>
 
    bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
 

	
 
    //! Not-equal-to operator with const C-string pointer
 
    bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
 

	
 
    //! Not-equal-to operator with arbitrary types
 
    /*! \return !(*this == rhs)
 
     */
 
    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
 

	
 
    //! Equal-to operator with arbitrary types (symmetric version)
 
    /*! \return (rhs == lhs)
 
     */
 
    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
 

	
 
    //! Not-Equal-to operator with arbitrary types (symmetric version)
 
    /*! \return !(rhs == lhs)
 
     */
 
    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
 
    //@}
 

	
 
    //!@name Type
 
    //@{
 

	
 
    Type GetType()  const { return static_cast<Type>(data_.f.flags & kTypeMask); }
 
    bool IsNull()   const { return data_.f.flags == kNullFlag; }
 
    bool IsFalse()  const { return data_.f.flags == kFalseFlag; }
 
    bool IsTrue()   const { return data_.f.flags == kTrueFlag; }
 
    bool IsBool()   const { return (data_.f.flags & kBoolFlag) != 0; }
 
    bool IsObject() const { return data_.f.flags == kObjectFlag; }
 
    bool IsArray()  const { return data_.f.flags == kArrayFlag; }
 
    bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
 
    bool IsInt()    const { return (data_.f.flags & kIntFlag) != 0; }
 
    bool IsUint()   const { return (data_.f.flags & kUintFlag) != 0; }
 
    bool IsInt64()  const { return (data_.f.flags & kInt64Flag) != 0; }
 
    bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
 
    bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
 
    bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
 

	
 
    // Checks whether a number can be losslessly converted to a double.
 
    bool IsLosslessDouble() const {
 
        if (!IsNumber()) return false;
 
        if (IsUint64()) {
 
            uint64_t u = GetUint64();
 
            volatile double d = static_cast<double>(u);
 
            return (d >= 0.0)
 
                && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))
 
                && (u == static_cast<uint64_t>(d));
 
        }
 
        if (IsInt64()) {
 
            int64_t i = GetInt64();
 
            volatile double d = static_cast<double>(i);
 
            return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
 
                && (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
 
                && (i == static_cast<int64_t>(d));
 
        }
 
        return true; // double, int, uint are always lossless
 
    }
 

	
 
    // Checks whether a number is a float (possible lossy).
 
    bool IsFloat() const  {
 
        if ((data_.f.flags & kDoubleFlag) == 0)
 
            return false;
 
        double d = GetDouble();
 
        return d >= -3.4028234e38 && d <= 3.4028234e38;
 
    }
 
    // Checks whether a number can be losslessly converted to a float.
 
    bool IsLosslessFloat() const {
 
        if (!IsNumber()) return false;
 
        double a = GetDouble();
 
        if (a < static_cast<double>(-(std::numeric_limits<float>::max)())
 
                || a > static_cast<double>((std::numeric_limits<float>::max)()))
 
            return false;
 
        double b = static_cast<double>(static_cast<float>(a));
 
        return a >= b && a <= b;    // Prevent -Wfloat-equal
 
    }
 

	
 
    //@}
 

	
 
    //!@name Null
 
    //@{
 

	
 
    GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
 

	
 
    //@}
 

	
 
    //!@name Bool
 
    //@{
 

	
 
    bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
 
    //!< Set boolean value
 
    /*! \post IsBool() == true */
 
    GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
 

	
 
    //@}
 

	
 
    //!@name Object
 
    //@{
 

	
 
    //! Set this value as an empty object.
 
    /*! \post IsObject() == true */
 
    GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
 

	
 
    //! Get the number of members in the object.
 
    SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
 

	
 
    //! Get the capacity of object.
 
    SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }
 

	
 
    //! Check whether the object is empty.
 
    bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
 

	
 
    //! Get a value from an object associated with the name.
 
    /*! \pre IsObject() == true
 
        \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
 
        \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
 
        Since 0.2, if the name is not correct, it will assert.
 
        If user is unsure whether a member exists, user should use HasMember() first.
 
        A better approach is to use FindMember().
 
        \note Linear time complexity.
 
    */
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
 
        GenericValue n(StringRef(name));
 
        return (*this)[n];
 
    }
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
 

	
 
    //! Get a value from an object associated with the name.
 
    /*! \pre IsObject() == true
 
        \tparam SourceAllocator Allocator of the \c name value
 

	
 
        \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
 
        And it can also handle strings with embedded null characters.
 

	
 
        \note Linear time complexity.
 
    */
 
    template <typename SourceAllocator>
 
    GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
 
        MemberIterator member = FindMember(name);
 
        if (member != MemberEnd())
 
            return member->value;
 
        else {
 
            RAPIDJSON_ASSERT(false);    // see above note
 

	
 
            // This will generate -Wexit-time-destructors in clang
 
            // static GenericValue NullValue;
 
            // return NullValue;
 

	
 
            // Use static buffer and placement-new to prevent destruction
 
            static char buffer[sizeof(GenericValue)];
 
            return *new (buffer) GenericValue();
 
        }
 
    }
 
    template <typename SourceAllocator>
 
    const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Get a value from an object associated with name (string object).
 
    GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
 
    const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
 
#endif
 

	
 
    //! Const member iterator
 
    /*! \pre IsObject() == true */
 
    ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
 
    //! Const \em past-the-end member iterator
 
    /*! \pre IsObject() == true */
 
    ConstMemberIterator MemberEnd() const   { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
 
    //! Member iterator
 
    /*! \pre IsObject() == true */
 
    MemberIterator MemberBegin()            { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
 
    //! \em Past-the-end member iterator
 
    /*! \pre IsObject() == true */
 
    MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
 

	
 
    //! Request the object to have enough capacity to store members.
 
    /*! \param newCapacity  The capacity that the object at least need to have.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \note Linear time complexity.
 
    */
 
    GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
 
        RAPIDJSON_ASSERT(IsObject());
 
        if (newCapacity > data_.o.capacity) {
 
            SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member))));
 
            data_.o.capacity = newCapacity;
 
        }
 
        return *this;
 
    }
 

	
 
    //! Check whether a member exists in the object.
 
    /*!
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Whether a member with that name exists.
 
        \note It is better to use FindMember() directly if you need the obtain the value as well.
 
        \note Linear time complexity.
 
    */
 
    bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Check whether a member exists in the object with string object.
 
    /*!
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Whether a member with that name exists.
 
        \note It is better to use FindMember() directly if you need the obtain the value as well.
 
        \note Linear time complexity.
 
    */
 
    bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
 
#endif
 

	
 
    //! Check whether a member exists in the object with GenericValue name.
 
    /*!
 
        This version is faster because it does not need a StrLen(). It can also handle string with null character.
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Whether a member with that name exists.
 
        \note It is better to use FindMember() directly if you need the obtain the value as well.
 
        \note Linear time complexity.
 
    */
 
    template <typename SourceAllocator>
 
    bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
 

	
 
    //! Find member by name.
 
    /*!
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Iterator to member, if it exists.
 
            Otherwise returns \ref MemberEnd().
 

	
 
        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
 
            the requested member doesn't exist. For consistency with e.g.
 
            \c std::map, this has been changed to MemberEnd() now.
 
        \note Linear time complexity.
 
    */
 
    MemberIterator FindMember(const Ch* name) {
 
        GenericValue n(StringRef(name));
 
        return FindMember(n);
 
    }
 

	
 
    ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
 

	
 
    //! Find member by name.
 
    /*!
 
        This version is faster because it does not need a StrLen(). It can also handle string with null character.
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Iterator to member, if it exists.
 
            Otherwise returns \ref MemberEnd().
 

	
 
        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
 
            the requested member doesn't exist. For consistency with e.g.
 
            \c std::map, this has been changed to MemberEnd() now.
 
        \note Linear time complexity.
 
    */
 
    template <typename SourceAllocator>
 
    MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
 
        RAPIDJSON_ASSERT(IsObject());
 
        RAPIDJSON_ASSERT(name.IsString());
 
        MemberIterator member = MemberBegin();
 
        for ( ; member != MemberEnd(); ++member)
 
            if (name.StringEqual(member->name))
 
                break;
 
        return member;
 
    }
 
    template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Find member by string object name.
 
    /*!
 
        \param name Member name to be searched.
 
        \pre IsObject() == true
 
        \return Iterator to member, if it exists.
 
            Otherwise returns \ref MemberEnd().
 
    */
 
    MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
 
    ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
 
#endif
 

	
 
    //! Add a member (name-value pair) to the object.
 
    /*! \param name A string value as name of member.
 
        \param value Value of any type.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \note The ownership of \c name and \c value will be transferred to this object on success.
 
        \pre  IsObject() && name.IsString()
 
        \post name.IsNull() && value.IsNull()
 
        \note Amortized Constant time complexity.
 
    */
 
    GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
 
        RAPIDJSON_ASSERT(IsObject());
 
        RAPIDJSON_ASSERT(name.IsString());
 

	
 
        ObjectData& o = data_.o;
 
        if (o.size >= o.capacity)
 
            MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator);
 
        Member* members = GetMembersPointer();
 
        members[o.size].name.RawAssign(name);
 
        members[o.size].value.RawAssign(value);
 
        o.size++;
 
        return *this;
 
    }
 

	
 
    //! Add a constant string value as member (name-value pair) to the object.
 
    /*! \param name A string value as name of member.
 
        \param value constant string reference as value of member.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \pre  IsObject()
 
        \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
 
        \note Amortized Constant time complexity.
 
    */
 
    GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
 
        GenericValue v(value);
 
        return AddMember(name, v, allocator);
 
    }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Add a string object as member (name-value pair) to the object.
 
    /*! \param name A string value as name of member.
 
        \param value constant string reference as value of member.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \pre  IsObject()
 
        \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
 
        \note Amortized Constant time complexity.
 
    */
 
    GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
 
        GenericValue v(value, allocator);
 
        return AddMember(name, v, allocator);
 
    }
 
#endif
 

	
 
    //! Add any primitive value as member (name-value pair) to the object.
 
    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
 
        \param name A string value as name of member.
 
        \param value Value of primitive type \c T as value of member
 
        \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \pre  IsObject()
 

	
 
        \note The source type \c T explicitly disallows all pointer types,
 
            especially (\c const) \ref Ch*.  This helps avoiding implicitly
 
            referencing character strings with insufficient lifetime, use
 
            \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
 
            AddMember(StringRefType, StringRefType, Allocator&).
 
            All other pointer types would implicitly convert to \c bool,
 
            use an explicit cast instead, if needed.
 
        \note Amortized Constant time complexity.
 
    */
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
 
    AddMember(GenericValue& name, T value, Allocator& allocator) {
 
        GenericValue v(value);
 
        return AddMember(name, v, allocator);
 
    }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
 
        return AddMember(name, value, allocator);
 
    }
 
    GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
 
        return AddMember(name, value, allocator);
 
    }
 
    GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
 
        return AddMember(name, value, allocator);
 
    }
 
    GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
 
        GenericValue n(name);
 
        return AddMember(n, value, allocator);
 
    }
 
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 

	
 

	
 
    //! Add a member (name-value pair) to the object.
 
    /*! \param name A constant string reference as name of member.
 
        \param value Value of any type.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \note The ownership of \c value will be transferred to this object on success.
 
        \pre  IsObject()
 
        \post value.IsNull()
 
        \note Amortized Constant time complexity.
 
    */
 
    GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
 
        GenericValue n(name);
 
        return AddMember(n, value, allocator);
 
    }
 

	
 
    //! Add a constant string value as member (name-value pair) to the object.
 
    /*! \param name A constant string reference as name of member.
 
        \param value constant string reference as value of member.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \pre  IsObject()
 
        \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
 
        \note Amortized Constant time complexity.
 
    */
 
    GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
 
        GenericValue v(value);
 
        return AddMember(name, v, allocator);
 
    }
 

	
 
    //! Add any primitive value as member (name-value pair) to the object.
 
    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
 
        \param name A constant string reference as name of member.
 
        \param value Value of primitive type \c T as value of member
 
        \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \pre  IsObject()
 

	
 
        \note The source type \c T explicitly disallows all pointer types,
 
            especially (\c const) \ref Ch*.  This helps avoiding implicitly
 
            referencing character strings with insufficient lifetime, use
 
            \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
 
            AddMember(StringRefType, StringRefType, Allocator&).
 
            All other pointer types would implicitly convert to \c bool,
 
            use an explicit cast instead, if needed.
 
        \note Amortized Constant time complexity.
 
    */
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
 
    AddMember(StringRefType name, T value, Allocator& allocator) {
 
        GenericValue n(name);
 
        return AddMember(n, value, allocator);
 
    }
 

	
 
    //! Remove all members in the object.
 
    /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
 
        \note Linear time complexity.
 
    */
 
    void RemoveAllMembers() {
 
        RAPIDJSON_ASSERT(IsObject()); 
 
        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
 
            m->~Member();
 
        data_.o.size = 0;
 
    }
 

	
 
    //! Remove a member in object by its name.
 
    /*! \param name Name of member to be removed.
 
        \return Whether the member existed.
 
        \note This function may reorder the object members. Use \ref
 
            EraseMember(ConstMemberIterator) if you need to preserve the
 
            relative order of the remaining members.
 
        \note Linear time complexity.
 
    */
 
    bool RemoveMember(const Ch* name) {
 
        GenericValue n(StringRef(name));
 
        return RemoveMember(n);
 
    }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
 
#endif
 

	
 
    template <typename SourceAllocator>
 
    bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
 
        MemberIterator m = FindMember(name);
 
        if (m != MemberEnd()) {
 
            RemoveMember(m);
 
            return true;
 
        }
 
        else
 
            return false;
 
    }
 

	
 
    //! Remove a member in object by iterator.
 
    /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
 
        \return the new iterator after removal.
 
        \note This function may reorder the object members. Use \ref
 
            EraseMember(ConstMemberIterator) if you need to preserve the
 
            relative order of the remaining members.
 
        \note Constant time complexity.
 
    */
 
    MemberIterator RemoveMember(MemberIterator m) {
 
        RAPIDJSON_ASSERT(IsObject());
 
        RAPIDJSON_ASSERT(data_.o.size > 0);
 
        RAPIDJSON_ASSERT(GetMembersPointer() != 0);
 
        RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
 

	
 
        MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
 
        if (data_.o.size > 1 && m != last)
 
            *m = *last; // Move the last one to this place
 
        else
 
            m->~Member(); // Only one left, just destroy
 
        --data_.o.size;
 
        return m;
 
    }
 

	
 
    //! Remove a member from an object by iterator.
 
    /*! \param pos iterator to the member to remove
 
        \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
 
        \return Iterator following the removed element.
 
            If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
 
        \note This function preserves the relative order of the remaining object
 
            members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
 
        \note Linear time complexity.
 
    */
 
    MemberIterator EraseMember(ConstMemberIterator pos) {
 
        return EraseMember(pos, pos +1);
 
    }
 

	
 
    //! Remove members in the range [first, last) from an object.
 
    /*! \param first iterator to the first member to remove
 
        \param last  iterator following the last member to remove
 
        \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
 
        \return Iterator following the last removed element.
 
        \note This function preserves the relative order of the remaining object
 
            members.
 
        \note Linear time complexity.
 
    */
 
    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
 
        RAPIDJSON_ASSERT(IsObject());
 
        RAPIDJSON_ASSERT(data_.o.size > 0);
 
        RAPIDJSON_ASSERT(GetMembersPointer() != 0);
 
        RAPIDJSON_ASSERT(first >= MemberBegin());
 
        RAPIDJSON_ASSERT(first <= last);
 
        RAPIDJSON_ASSERT(last <= MemberEnd());
 

	
 
        MemberIterator pos = MemberBegin() + (first - MemberBegin());
 
        for (MemberIterator itr = pos; itr != last; ++itr)
 
            itr->~Member();
 
        std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
 
        data_.o.size -= static_cast<SizeType>(last - first);
 
        return pos;
 
    }
 

	
 
    //! Erase a member in object by its name.
 
    /*! \param name Name of member to be removed.
 
        \return Whether the member existed.
 
        \note Linear time complexity.
 
    */
 
    bool EraseMember(const Ch* name) {
 
        GenericValue n(StringRef(name));
 
        return EraseMember(n);
 
    }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
 
#endif
 

	
 
    template <typename SourceAllocator>
 
    bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
 
        MemberIterator m = FindMember(name);
 
        if (m != MemberEnd()) {
 
            EraseMember(m);
 
            return true;
 
        }
 
        else
 
            return false;
 
    }
 

	
 
    Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
 
    ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
 

	
 
    //@}
 

	
 
    //!@name Array
 
    //@{
 

	
 
    //! Set this value as an empty array.
 
    /*! \post IsArray == true */
 
    GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
 

	
 
    //! Get the number of elements in array.
 
    SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
 

	
 
    //! Get the capacity of array.
 
    SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
 

	
 
    //! Check whether the array is empty.
 
    bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
 

	
 
    //! Remove all elements in the array.
 
    /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
 
        \note Linear time complexity.
 
    */
 
    void Clear() {
 
        RAPIDJSON_ASSERT(IsArray()); 
 
        GenericValue* e = GetElementsPointer();
 
        for (GenericValue* v = e; v != e + data_.a.size; ++v)
 
            v->~GenericValue();
 
        data_.a.size = 0;
 
    }
 

	
 
    //! Get an element from array by index.
 
    /*! \pre IsArray() == true
 
        \param index Zero-based index of element.
 
        \see operator[](T*)
 
    */
 
    GenericValue& operator[](SizeType index) {
 
        RAPIDJSON_ASSERT(IsArray());
 
        RAPIDJSON_ASSERT(index < data_.a.size);
 
        return GetElementsPointer()[index];
 
    }
 
    const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
 

	
 
    //! Element iterator
 
    /*! \pre IsArray() == true */
 
    ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
 
    //! \em Past-the-end element iterator
 
    /*! \pre IsArray() == true */
 
    ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
 
    //! Constant element iterator
 
    /*! \pre IsArray() == true */
 
    ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
 
    //! Constant \em past-the-end element iterator
 
    /*! \pre IsArray() == true */
 
    ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
 

	
 
    //! Request the array to have enough capacity to store elements.
 
    /*! \param newCapacity  The capacity that the array at least need to have.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \note Linear time complexity.
 
    */
 
    GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
 
        RAPIDJSON_ASSERT(IsArray());
 
        if (newCapacity > data_.a.capacity) {
 
            SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
 
            data_.a.capacity = newCapacity;
 
        }
 
        return *this;
 
    }
 

	
 
    //! Append a GenericValue at the end of the array.
 
    /*! \param value        Value to be appended.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \pre IsArray() == true
 
        \post value.IsNull() == true
 
        \return The value itself for fluent API.
 
        \note The ownership of \c value will be transferred to this array on success.
 
        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
 
        \note Amortized constant time complexity.
 
    */
 
    GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
 
        RAPIDJSON_ASSERT(IsArray());
 
        if (data_.a.size >= data_.a.capacity)
 
            Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
 
        GetElementsPointer()[data_.a.size++].RawAssign(value);
 
        return *this;
 
    }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
 
        return PushBack(value, allocator);
 
    }
 
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 

	
 
    //! Append a constant string reference at the end of the array.
 
    /*! \param value        Constant string reference to be appended.
 
        \param allocator    Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
 
        \pre IsArray() == true
 
        \return The value itself for fluent API.
 
        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
 
        \note Amortized constant time complexity.
 
        \see GenericStringRef
 
    */
 
    GenericValue& PushBack(StringRefType value, Allocator& allocator) {
 
        return (*this).template PushBack<StringRefType>(value, allocator);
 
    }
 

	
 
    //! Append a primitive value at the end of the array.
 
    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
 
        \param value Value of primitive type T to be appended.
 
        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
 
        \pre IsArray() == true
 
        \return The value itself for fluent API.
 
        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
 

	
 
        \note The source type \c T explicitly disallows all pointer types,
 
            especially (\c const) \ref Ch*.  This helps avoiding implicitly
 
            referencing character strings with insufficient lifetime, use
 
            \ref PushBack(GenericValue&, Allocator&) or \ref
 
            PushBack(StringRefType, Allocator&).
 
            All other pointer types would implicitly convert to \c bool,
 
            use an explicit cast instead, if needed.
 
        \note Amortized constant time complexity.
 
    */
 
    template <typename T>
 
    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
 
    PushBack(T value, Allocator& allocator) {
 
        GenericValue v(value);
 
        return PushBack(v, allocator);
 
    }
 

	
 
    //! Remove the last element in the array.
 
    /*!
 
        \note Constant time complexity.
 
    */
 
    GenericValue& PopBack() {
 
        RAPIDJSON_ASSERT(IsArray());
 
        RAPIDJSON_ASSERT(!Empty());
 
        GetElementsPointer()[--data_.a.size].~GenericValue();
 
        return *this;
 
    }
 

	
 
    //! Remove an element of array by iterator.
 
    /*!
 
        \param pos iterator to the element to remove
 
        \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
 
        \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
 
        \note Linear time complexity.
 
    */
 
    ValueIterator Erase(ConstValueIterator pos) {
 
        return Erase(pos, pos + 1);
 
    }
 

	
 
    //! Remove elements in the range [first, last) of the array.
 
    /*!
 
        \param first iterator to the first element to remove
 
        \param last  iterator following the last element to remove
 
        \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
 
        \return Iterator following the last removed element.
 
        \note Linear time complexity.
 
    */
 
    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
 
        RAPIDJSON_ASSERT(IsArray());
 
        RAPIDJSON_ASSERT(data_.a.size > 0);
 
        RAPIDJSON_ASSERT(GetElementsPointer() != 0);
 
        RAPIDJSON_ASSERT(first >= Begin());
 
        RAPIDJSON_ASSERT(first <= last);
 
        RAPIDJSON_ASSERT(last <= End());
 
        ValueIterator pos = Begin() + (first - Begin());
 
        for (ValueIterator itr = pos; itr != last; ++itr)
 
            itr->~GenericValue();       
 
        std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
 
        data_.a.size -= static_cast<SizeType>(last - first);
 
        return pos;
 
    }
 

	
 
    Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
 
    ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
 

	
 
    //@}
 

	
 
    //!@name Number
 
    //@{
 

	
 
    int GetInt() const          { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag);   return data_.n.i.i;   }
 
    unsigned GetUint() const    { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag);  return data_.n.u.u;   }
 
    int64_t GetInt64() const    { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
 
    uint64_t GetUint64() const  { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
 

	
 
    //! Get the value as double type.
 
    /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
 
    */
 
    double GetDouble() const {
 
        RAPIDJSON_ASSERT(IsNumber());
 
        if ((data_.f.flags & kDoubleFlag) != 0)                return data_.n.d;   // exact type, no conversion.
 
        if ((data_.f.flags & kIntFlag) != 0)                   return data_.n.i.i; // int -> double
 
        if ((data_.f.flags & kUintFlag) != 0)                  return data_.n.u.u; // unsigned -> double
 
        if ((data_.f.flags & kInt64Flag) != 0)                 return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
 
        RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0);  return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
 
    }
 

	
 
    //! Get the value as float type.
 
    /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
 
    */
 
    float GetFloat() const {
 
        return static_cast<float>(GetDouble());
 
    }
 

	
 
    GenericValue& SetInt(int i)             { this->~GenericValue(); new (this) GenericValue(i);    return *this; }
 
    GenericValue& SetUint(unsigned u)       { this->~GenericValue(); new (this) GenericValue(u);    return *this; }
 
    GenericValue& SetInt64(int64_t i64)     { this->~GenericValue(); new (this) GenericValue(i64);  return *this; }
 
    GenericValue& SetUint64(uint64_t u64)   { this->~GenericValue(); new (this) GenericValue(u64);  return *this; }
 
    GenericValue& SetDouble(double d)       { this->~GenericValue(); new (this) GenericValue(d);    return *this; }
 
    GenericValue& SetFloat(float f)         { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
 

	
 
    //@}
 

	
 
    //!@name String
 
    //@{
 

	
 
    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
 

	
 
    //! Get the length of string.
 
    /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
 
    */
 
    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
 

	
 
    //! Set this value as a string without copying source string.
 
    /*! This version has better performance with supplied length, and also support string containing null character.
 
        \param s source string pointer. 
 
        \param length The length of source string, excluding the trailing null terminator.
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() == s && GetStringLength() == length
 
        \see SetString(StringRefType)
 
    */
 
    GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
 

	
 
    //! Set this value as a string without copying source string.
 
    /*! \param s source string reference
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() == s && GetStringLength() == s.length
 
    */
 
    GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
 

	
 
    //! Set this value as a string by copying from source string.
 
    /*! This version has better performance with supplied length, and also support string containing null character.
 
        \param s source string. 
 
        \param length The length of source string, excluding the trailing null terminator.
 
        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 
    */
 
    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }
 

	
 
    //! Set this value as a string by copying from source string.
 
    /*! \param s source string. 
 
        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 
    */
 
    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
 

	
 
    //! Set this value as a string by copying from source string.
 
    /*! \param s source string reference
 
        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
 
    */
 
    GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    //! Set this value as a string by copying from source string.
 
    /*! \param s source string.
 
        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
 
        \return The value itself for fluent API.
 
        \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
 
        \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
 
    */
 
    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
 
#endif
 

	
 
    //@}
 

	
 
    //!@name Array
 
    //@{
 

	
 
    //! Templated version for checking whether this value is type T.
 
    /*!
 
        \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
 
    */
 
    template <typename T>
 
    bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
 

	
 
    template <typename T>
 
    T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
 

	
 
    template <typename T>
 
    T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
 

	
 
    template<typename T>
 
    ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
 

	
 
    template<typename T>
 
    ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
 

	
 
    //@}
 

	
 
    //! Generate events of this value to a Handler.
 
    /*! This function adopts the GoF visitor pattern.
 
        Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
 
        It can also be used to deep clone this value via GenericDocument, which is also a Handler.
 
        \tparam Handler type of handler.
 
        \param handler An object implementing concept Handler.
 
    */
 
    template <typename Handler>
 
    bool Accept(Handler& handler) const {
 
        switch(GetType()) {
 
        case kNullType:     return handler.Null();
 
        case kFalseType:    return handler.Bool(false);
 
        case kTrueType:     return handler.Bool(true);
 

	
 
        case kObjectType:
 
            if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
 
                return false;
 
            for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
 
                RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
 
                if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
 
                    return false;
 
                if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
 
                    return false;
 
            }
 
            return handler.EndObject(data_.o.size);
 

	
 
        case kArrayType:
 
            if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
 
                return false;
 
            for (const GenericValue* v = Begin(); v != End(); ++v)
 
                if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
 
                    return false;
 
            return handler.EndArray(data_.a.size);
 
    
 
        case kStringType:
 
            return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
 
    
 
        default:
 
            RAPIDJSON_ASSERT(GetType() == kNumberType);
 
            if (IsDouble())         return handler.Double(data_.n.d);
 
            else if (IsInt())       return handler.Int(data_.n.i.i);
 
            else if (IsUint())      return handler.Uint(data_.n.u.u);
 
            else if (IsInt64())     return handler.Int64(data_.n.i64);
 
            else                    return handler.Uint64(data_.n.u64);
 
        }
 
    }
 

	
 
private:
 
	template <typename, typename>
 
	friend class GenericDocument;
 

	
 
	enum {
 
		kBoolFlag = 0x100,
 
		kNumberFlag = 0x200,
 
		kIntFlag = 0x400,
 
		kUintFlag = 0x800,
 
		kInt64Flag = 0x1000,
 
		kUint64Flag = 0x2000,
 
		kDoubleFlag = 0x4000,
 
		kStringFlag = 0x100000,
 
		kCopyFlag = 0x200000,
 

	
 
		// Initial flags of different types.
 
		kNullFlag = kNullType,
 
		kTrueFlag = kTrueType | kBoolFlag,
 
		kFalseFlag = kFalseType | kBoolFlag,
 
		kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
 
		kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
 
		kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
 
		kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
 
		kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
 
		kConstStringFlag = kStringType | kStringFlag,
 
		kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
 
		kObjectFlag = kObjectType,
 
		kArrayFlag = kArrayType,
 

	
 
		kTypeMask = 0xFF	// bitwise-and with mask of 0xFF can be optimized by compiler
 
	};
 

	
 
	static const SizeType kDefaultArrayCapacity = 16;
 
	static const SizeType kDefaultObjectCapacity = 16;
 

	
 
	struct String {
 
		const Ch* str;
 
		SizeType length;
 
		unsigned hashcode;	//!< reserved
 
	};	// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
	// By using proper binary layout, retrieval of different integer types do not need conversions.
 
	union Number {
 
    template <typename, typename> friend class GenericValue;
 
    template <typename, typename, typename> friend class GenericDocument;
 

	
 
    enum {
 
        kBoolFlag       = 0x0008,
 
        kNumberFlag     = 0x0010,
 
        kIntFlag        = 0x0020,
 
        kUintFlag       = 0x0040,
 
        kInt64Flag      = 0x0080,
 
        kUint64Flag     = 0x0100,
 
        kDoubleFlag     = 0x0200,
 
        kStringFlag     = 0x0400,
 
        kCopyFlag       = 0x0800,
 
        kInlineStrFlag  = 0x1000,
 

	
 
        // Initial flags of different types.
 
        kNullFlag = kNullType,
 
        kTrueFlag = kTrueType | kBoolFlag,
 
        kFalseFlag = kFalseType | kBoolFlag,
 
        kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
 
        kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
 
        kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
 
        kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
 
        kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
 
        kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
 
        kConstStringFlag = kStringType | kStringFlag,
 
        kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
 
        kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
 
        kObjectFlag = kObjectType,
 
        kArrayFlag = kArrayType,
 

	
 
        kTypeMask = 0x07
 
    };
 

	
 
    static const SizeType kDefaultArrayCapacity = 16;
 
    static const SizeType kDefaultObjectCapacity = 16;
 

	
 
    struct Flag {
 
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
 
        char payload[sizeof(SizeType) * 2 + 6];     // 2 x SizeType + lower 48-bit pointer
 
#elif RAPIDJSON_64BIT
 
        char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
 
#else
 
        char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
 
#endif
 
        uint16_t flags;
 
    };
 

	
 
    struct String {
 
        SizeType length;
 
        SizeType hashcode;  //!< reserved
 
        const Ch* str;
 
    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
    // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
 
    // (excluding the terminating zero) and store a value to determine the length of the contained
 
    // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
 
    // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
 
    // the string terminator as well. For getting the string length back from that value just use
 
    // "MaxSize - str[LenPos]".
 
    // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
 
    // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
 
    struct ShortString {
 
        enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
 
        Ch str[MaxChars];
 

	
 
        inline static bool Usable(SizeType len) { return                       (MaxSize >= len); }
 
        inline void     SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize -  len); }
 
        inline SizeType GetLength() const       { return  static_cast<SizeType>(MaxSize -  str[LenPos]); }
 
    };  // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
    // By using proper binary layout, retrieval of different integer types do not need conversions.
 
    union Number {
 
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
 
		struct I {
 
			int i;
 
			char padding[4];
 
		}i;
 
		struct U {
 
			unsigned u;
 
			char padding2[4];
 
		}u;
 
        struct I {
 
            int i;
 
            char padding[4];
 
        }i;
 
        struct U {
 
            unsigned u;
 
            char padding2[4];
 
        }u;
 
#else
 
		struct I {
 
			char padding[4];
 
			int i;
 
		}i;
 
		struct U {
 
			char padding2[4];
 
			unsigned u;
 
		}u;
 
#endif
 
		int64_t i64;
 
		uint64_t u64;
 
		double d;
 
	};	// 8 bytes
 

	
 
	struct Object {
 
		Member* members;
 
		SizeType size;
 
		SizeType capacity;
 
	};	// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
	struct Array {
 
		GenericValue<Encoding, Allocator>* elements;
 
		SizeType size;
 
		SizeType capacity;
 
	};	// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
	union Data {
 
		String s;
 
		Number n;
 
		Object o;
 
		Array a;
 
	};	// 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
	//! Find member by name.
 
	Member* FindMember(const Ch* name) {
 
		RAPIDJSON_ASSERT(name);
 
		RAPIDJSON_ASSERT(IsObject());
 

	
 
		SizeType length = internal::StrLen(name);
 

	
 
		Object& o = data_.o;
 
		for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member)
 
			if (length == member->name.data_.s.length && memcmp(member->name.data_.s.str, name, length * sizeof(Ch)) == 0)
 
				return member;
 

	
 
		return 0;
 
	}
 
	const Member* FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
 

	
 
	// Initialize this value as array with initial data, without calling destructor.
 
	void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) {
 
		flags_ = kArrayFlag;
 
		data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue));
 
		memcpy(data_.a.elements, values, count * sizeof(GenericValue));
 
		data_.a.size = data_.a.capacity = count;
 
	}
 

	
 
	//! Initialize this value as object with initial data, without calling destructor.
 
	void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) {
 
		flags_ = kObjectFlag;
 
		data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member));
 
		memcpy(data_.o.members, members, count * sizeof(Member));
 
		data_.o.size = data_.o.capacity = count;
 
	}
 

	
 
	//! Initialize this value as constant string, without calling destructor.
 
	void SetStringRaw(const Ch* s, SizeType length) {
 
		RAPIDJSON_ASSERT(s != NULL);
 
		flags_ = kConstStringFlag;
 
		data_.s.str = s;
 
		data_.s.length = length;
 
	}
 

	
 
	//! Initialize this value as copy string with initial data, without calling destructor.
 
	void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) {
 
		RAPIDJSON_ASSERT(s != NULL);
 
		flags_ = kCopyStringFlag;
 
		data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch));
 
		data_.s.length = length;
 
		memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch));
 
		const_cast<Ch*>(data_.s.str)[length] = '\0';
 
	}
 

	
 
	//! Assignment without calling destructor
 
	void RawAssign(GenericValue& rhs) {
 
		memcpy(this, &rhs, sizeof(GenericValue));
 
		rhs.flags_ = kNullFlag;
 
	}
 

	
 
	Data data_;
 
	unsigned flags_;
 
        struct I {
 
            char padding[4];
 
            int i;
 
        }i;
 
        struct U {
 
            char padding2[4];
 
            unsigned u;
 
        }u;
 
#endif
 
        int64_t i64;
 
        uint64_t u64;
 
        double d;
 
    };  // 8 bytes
 

	
 
    struct ObjectData {
 
        SizeType size;
 
        SizeType capacity;
 
        Member* members;
 
    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
    struct ArrayData {
 
        SizeType size;
 
        SizeType capacity;
 
        GenericValue* elements;
 
    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
 

	
 
    union Data {
 
        String s;
 
        ShortString ss;
 
        Number n;
 
        ObjectData o;
 
        ArrayData a;
 
        Flag f;
 
    };  // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
 

	
 
    RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
 
    RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
 
    RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
 
    RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
 
    RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
 
    RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
 

	
 
    // Initialize this value as array with initial data, without calling destructor.
 
    void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
 
        data_.f.flags = kArrayFlag;
 
        if (count) {
 
            GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
 
            SetElementsPointer(e);
 
RAPIDJSON_DIAG_PUSH
 
#if defined(__GNUC__) && __GNUC__ >= 8
 
RAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.
 
#endif
 
            std::memcpy(e, values, count * sizeof(GenericValue));
 
RAPIDJSON_DIAG_POP
 
        }
 
        else
 
            SetElementsPointer(0);
 
        data_.a.size = data_.a.capacity = count;
 
    }
 

	
 
    //! Initialize this value as object with initial data, without calling destructor.
 
    void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
 
        data_.f.flags = kObjectFlag;
 
        if (count) {
 
            Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
 
            SetMembersPointer(m);
 
RAPIDJSON_DIAG_PUSH
 
#if defined(__GNUC__) && __GNUC__ >= 8
 
RAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.
 
#endif
 
            std::memcpy(m, members, count * sizeof(Member));
 
RAPIDJSON_DIAG_POP
 
        }
 
        else
 
            SetMembersPointer(0);
 
        data_.o.size = data_.o.capacity = count;
 
    }
 

	
 
    //! Initialize this value as constant string, without calling destructor.
 
    void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
 
        data_.f.flags = kConstStringFlag;
 
        SetStringPointer(s);
 
        data_.s.length = s.length;
 
    }
 

	
 
    //! Initialize this value as copy string with initial data, without calling destructor.
 
    void SetStringRaw(StringRefType s, Allocator& allocator) {
 
        Ch* str = 0;
 
        if (ShortString::Usable(s.length)) {
 
            data_.f.flags = kShortStringFlag;
 
            data_.ss.SetLength(s.length);
 
            str = data_.ss.str;
 
        } else {
 
            data_.f.flags = kCopyStringFlag;
 
            data_.s.length = s.length;
 
            str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
 
            SetStringPointer(str);
 
        }
 
        std::memcpy(str, s, s.length * sizeof(Ch));
 
        str[s.length] = '\0';
 
    }
 

	
 
    //! Assignment without calling destructor
 
    void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
 
        data_ = rhs.data_;
 
        // data_.f.flags = rhs.data_.f.flags;
 
        rhs.data_.f.flags = kNullFlag;
 
    }
 

	
 
    template <typename SourceAllocator>
 
    bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
 
        RAPIDJSON_ASSERT(IsString());
 
        RAPIDJSON_ASSERT(rhs.IsString());
 

	
 
        const SizeType len1 = GetStringLength();
 
        const SizeType len2 = rhs.GetStringLength();
 
        if(len1 != len2) { return false; }
 

	
 
        const Ch* const str1 = GetString();
 
        const Ch* const str2 = rhs.GetString();
 
        if(str1 == str2) { return true; } // fast path for constant string
 

	
 
        return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
 
    }
 

	
 
    Data data_;
 
};
 
#pragma pack (pop)
 

	
 
//! Value with UTF8 encoding.
 
//! GenericValue with UTF8 encoding
 
typedef GenericValue<UTF8<> > Value;
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
@@ -683,139 +2122,539 @@ typedef GenericValue<UTF8<> > Value;
 

	
 
//! A document for parsing JSON text as DOM.
 
/*!
 
	\implements Handler
 
	\tparam Encoding encoding for both parsing and string storage.
 
	\tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing.
 
    \note implements Handler concept
 
    \tparam Encoding Encoding for both parsing and string storage.
 
    \tparam Allocator Allocator for allocating memory for the DOM
 
    \tparam StackAllocator Allocator for allocating memory for stack during parsing.
 
    \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor.  To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
 
*/
 
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
 
template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
 
class GenericDocument : public GenericValue<Encoding, Allocator> {
 
public:
 
	typedef typename Encoding::Ch Ch;						//!< Character type derived from Encoding.
 
	typedef GenericValue<Encoding, Allocator> ValueType;	//!< Value type of the document.
 
	typedef Allocator AllocatorType;						//!< Allocator type from template parameter.
 

	
 
	//! Constructor
 
	/*! \param allocator		Optional allocator for allocating stack memory.
 
		\param stackCapacity	Initial capacity of stack in bytes.
 
	*/
 
	GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
 

	
 
	//! Parse JSON text from an input stream.
 
	/*! \tparam parseFlags Combination of ParseFlag.
 
		\param stream Input stream to be parsed.
 
		\return The document itself for fluent API.
 
	*/
 
	template <unsigned parseFlags, typename Stream>
 
	GenericDocument& ParseStream(Stream& stream) {
 
		ValueType::SetNull(); // Remove existing root if exist
 
		GenericReader<Encoding, Allocator> reader;
 
		if (reader.template Parse<parseFlags>(stream, *this)) {
 
			RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
 
			this->RawAssign(*stack_.template Pop<ValueType>(1));	// Add this-> to prevent issue 13.
 
			parseError_ = 0;
 
			errorOffset_ = 0;
 
		}
 
		else {
 
			parseError_ = reader.GetParseError();
 
			errorOffset_ = reader.GetErrorOffset();
 
			ClearStack();
 
		}
 
		return *this;
 
	}
 

	
 
	//! Parse JSON text from a mutable string.
 
	/*! \tparam parseFlags Combination of ParseFlag.
 
		\param str Mutable zero-terminated string to be parsed.
 
		\return The document itself for fluent API.
 
	*/
 
	template <unsigned parseFlags>
 
	GenericDocument& ParseInsitu(Ch* str) {
 
		GenericInsituStringStream<Encoding> s(str);
 
		return ParseStream<parseFlags | kParseInsituFlag>(s);
 
	}
 

	
 
	//! Parse JSON text from a read-only string.
 
	/*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag).
 
		\param str Read-only zero-terminated string to be parsed.
 
	*/
 
	template <unsigned parseFlags>
 
	GenericDocument& Parse(const Ch* str) {
 
		RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
 
		GenericStringStream<Encoding> s(str);
 
		return ParseStream<parseFlags>(s);
 
	}
 

	
 
	//! Whether a parse error was occured in the last parsing.
 
	bool HasParseError() const { return parseError_ != 0; }
 

	
 
	//! Get the message of parsing error.
 
	const char* GetParseError() const { return parseError_; }
 

	
 
	//! Get the offset in character of the parsing error.
 
	size_t GetErrorOffset() const { return errorOffset_; }
 

	
 
	//! Get the allocator of this document.
 
	Allocator& GetAllocator() {	return stack_.GetAllocator(); }
 

	
 
	//! Get the capacity of stack in bytes.
 
	size_t GetStackCapacity() const { return stack_.GetCapacity(); }
 
    typedef typename Encoding::Ch Ch;                       //!< Character type derived from Encoding.
 
    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of the document.
 
    typedef Allocator AllocatorType;                        //!< Allocator type from template parameter.
 

	
 
    //! Constructor
 
    /*! Creates an empty document of specified type.
 
        \param type             Mandatory type of object to create.
 
        \param allocator        Optional allocator for allocating memory.
 
        \param stackCapacity    Optional initial capacity of stack in bytes.
 
        \param stackAllocator   Optional allocator for allocating memory for stack.
 
    */
 
    explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
 
        GenericValue<Encoding, Allocator>(type),  allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
 
    {
 
        if (!allocator_)
 
            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 
    }
 

	
 
    //! Constructor
 
    /*! Creates an empty document which type is Null. 
 
        \param allocator        Optional allocator for allocating memory.
 
        \param stackCapacity    Optional initial capacity of stack in bytes.
 
        \param stackAllocator   Optional allocator for allocating memory for stack.
 
    */
 
    GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : 
 
        allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
 
    {
 
        if (!allocator_)
 
            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 
    }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    //! Move constructor in C++11
 
    GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
 
        : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
 
          allocator_(rhs.allocator_),
 
          ownAllocator_(rhs.ownAllocator_),
 
          stack_(std::move(rhs.stack_)),
 
          parseResult_(rhs.parseResult_)
 
    {
 
        rhs.allocator_ = 0;
 
        rhs.ownAllocator_ = 0;
 
        rhs.parseResult_ = ParseResult();
 
    }
 
#endif
 

	
 
    ~GenericDocument() {
 
        Destroy();
 
    }
 

	
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    //! Move assignment in C++11
 
    GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
 
    {
 
        // The cast to ValueType is necessary here, because otherwise it would
 
        // attempt to call GenericValue's templated assignment operator.
 
        ValueType::operator=(std::forward<ValueType>(rhs));
 

	
 
        // Calling the destructor here would prematurely call stack_'s destructor
 
        Destroy();
 

	
 
        allocator_ = rhs.allocator_;
 
        ownAllocator_ = rhs.ownAllocator_;
 
        stack_ = std::move(rhs.stack_);
 
        parseResult_ = rhs.parseResult_;
 

	
 
        rhs.allocator_ = 0;
 
        rhs.ownAllocator_ = 0;
 
        rhs.parseResult_ = ParseResult();
 

	
 
        return *this;
 
    }
 
#endif
 

	
 
    //! Exchange the contents of this document with those of another.
 
    /*!
 
        \param rhs Another document.
 
        \note Constant complexity.
 
        \see GenericValue::Swap
 
    */
 
    GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
 
        ValueType::Swap(rhs);
 
        stack_.Swap(rhs.stack_);
 
        internal::Swap(allocator_, rhs.allocator_);
 
        internal::Swap(ownAllocator_, rhs.ownAllocator_);
 
        internal::Swap(parseResult_, rhs.parseResult_);
 
        return *this;
 
    }
 

	
 
    // Allow Swap with ValueType.
 
    // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.
 
    using ValueType::Swap;
 

	
 
    //! free-standing swap function helper
 
    /*!
 
        Helper function to enable support for common swap implementation pattern based on \c std::swap:
 
        \code
 
        void swap(MyClass& a, MyClass& b) {
 
            using std::swap;
 
            swap(a.doc, b.doc);
 
            // ...
 
        }
 
        \endcode
 
        \see Swap()
 
     */
 
    friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
 

	
 
    //! Populate this document by a generator which produces SAX events.
 
    /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
 
        \param g Generator functor which sends SAX events to the parameter.
 
        \return The document itself for fluent API.
 
    */
 
    template <typename Generator>
 
    GenericDocument& Populate(Generator& g) {
 
        ClearStackOnExit scope(*this);
 
        if (g(*this)) {
 
            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
 
            ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
 
        }
 
        return *this;
 
    }
 

	
 
    //!@name Parse from stream
 
    //!@{
 

	
 
    //! Parse JSON text from an input stream (with Encoding conversion)
 
    /*! \tparam parseFlags Combination of \ref ParseFlag.
 
        \tparam SourceEncoding Encoding of input stream
 
        \tparam InputStream Type of input stream, implementing Stream concept
 
        \param is Input stream to be parsed.
 
        \return The document itself for fluent API.
 
    */
 
    template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
 
    GenericDocument& ParseStream(InputStream& is) {
 
        GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
 
            stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
 
        ClearStackOnExit scope(*this);
 
        parseResult_ = reader.template Parse<parseFlags>(is, *this);
 
        if (parseResult_) {
 
            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
 
            ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
 
        }
 
        return *this;
 
    }
 

	
 
    //! Parse JSON text from an input stream
 
    /*! \tparam parseFlags Combination of \ref ParseFlag.
 
        \tparam InputStream Type of input stream, implementing Stream concept
 
        \param is Input stream to be parsed.
 
        \return The document itself for fluent API.
 
    */
 
    template <unsigned parseFlags, typename InputStream>
 
    GenericDocument& ParseStream(InputStream& is) {
 
        return ParseStream<parseFlags, Encoding, InputStream>(is);
 
    }
 

	
 
    //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
 
    /*! \tparam InputStream Type of input stream, implementing Stream concept
 
        \param is Input stream to be parsed.
 
        \return The document itself for fluent API.
 
    */
 
    template <typename InputStream>
 
    GenericDocument& ParseStream(InputStream& is) {
 
        return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
 
    }
 
    //!@}
 

	
 
    //!@name Parse in-place from mutable string
 
    //!@{
 

	
 
    //! Parse JSON text from a mutable string
 
    /*! \tparam parseFlags Combination of \ref ParseFlag.
 
        \param str Mutable zero-terminated string to be parsed.
 
        \return The document itself for fluent API.
 
    */
 
    template <unsigned parseFlags>
 
    GenericDocument& ParseInsitu(Ch* str) {
 
        GenericInsituStringStream<Encoding> s(str);
 
        return ParseStream<parseFlags | kParseInsituFlag>(s);
 
    }
 

	
 
    //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
 
    /*! \param str Mutable zero-terminated string to be parsed.
 
        \return The document itself for fluent API.
 
    */
 
    GenericDocument& ParseInsitu(Ch* str) {
 
        return ParseInsitu<kParseDefaultFlags>(str);
 
    }
 
    //!@}
 

	
 
    //!@name Parse from read-only string
 
    //!@{
 

	
 
    //! Parse JSON text from a read-only string (with Encoding conversion)
 
    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
 
        \tparam SourceEncoding Transcoding from input Encoding
 
        \param str Read-only zero-terminated string to be parsed.
 
    */
 
    template <unsigned parseFlags, typename SourceEncoding>
 
    GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
 
        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
 
        GenericStringStream<SourceEncoding> s(str);
 
        return ParseStream<parseFlags, SourceEncoding>(s);
 
    }
 

	
 
    //! Parse JSON text from a read-only string
 
    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
 
        \param str Read-only zero-terminated string to be parsed.
 
    */
 
    template <unsigned parseFlags>
 
    GenericDocument& Parse(const Ch* str) {
 
        return Parse<parseFlags, Encoding>(str);
 
    }
 

	
 
    //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
 
    /*! \param str Read-only zero-terminated string to be parsed.
 
    */
 
    GenericDocument& Parse(const Ch* str) {
 
        return Parse<kParseDefaultFlags>(str);
 
    }
 

	
 
    template <unsigned parseFlags, typename SourceEncoding>
 
    GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
 
        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
 
        MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
 
        EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
 
        ParseStream<parseFlags, SourceEncoding>(is);
 
        return *this;
 
    }
 

	
 
    template <unsigned parseFlags>
 
    GenericDocument& Parse(const Ch* str, size_t length) {
 
        return Parse<parseFlags, Encoding>(str, length);
 
    }
 
    
 
    GenericDocument& Parse(const Ch* str, size_t length) {
 
        return Parse<kParseDefaultFlags>(str, length);
 
    }
 

	
 
#if RAPIDJSON_HAS_STDSTRING
 
    template <unsigned parseFlags, typename SourceEncoding>
 
    GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
 
        // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
 
        return Parse<parseFlags, SourceEncoding>(str.c_str());
 
    }
 

	
 
    template <unsigned parseFlags>
 
    GenericDocument& Parse(const std::basic_string<Ch>& str) {
 
        return Parse<parseFlags, Encoding>(str.c_str());
 
    }
 

	
 
    GenericDocument& Parse(const std::basic_string<Ch>& str) {
 
        return Parse<kParseDefaultFlags>(str);
 
    }
 
#endif // RAPIDJSON_HAS_STDSTRING    
 

	
 
    //!@}
 

	
 
    //!@name Handling parse errors
 
    //!@{
 

	
 
    //! Whether a parse error has occurred in the last parsing.
 
    bool HasParseError() const { return parseResult_.IsError(); }
 

	
 
    //! Get the \ref ParseErrorCode of last parsing.
 
    ParseErrorCode GetParseError() const { return parseResult_.Code(); }
 

	
 
    //! Get the position of last parsing error in input, 0 otherwise.
 
    size_t GetErrorOffset() const { return parseResult_.Offset(); }
 

	
 
    //! Implicit conversion to get the last parse result
 
#ifndef __clang // -Wdocumentation
 
    /*! \return \ref ParseResult of the last parse operation
 

	
 
        \code
 
          Document doc;
 
          ParseResult ok = doc.Parse(json);
 
          if (!ok)
 
            printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
 
        \endcode
 
     */
 
#endif
 
    operator ParseResult() const { return parseResult_; }
 
    //!@}
 

	
 
    //! Get the allocator of this document.
 
    Allocator& GetAllocator() {
 
        RAPIDJSON_ASSERT(allocator_);
 
        return *allocator_;
 
    }
 

	
 
    //! Get the capacity of stack in bytes.
 
    size_t GetStackCapacity() const { return stack_.GetCapacity(); }
 

	
 
private:
 
    // clear stack on any exit from ParseStream, e.g. due to exception
 
    struct ClearStackOnExit {
 
        explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
 
        ~ClearStackOnExit() { d_.ClearStack(); }
 
    private:
 
        ClearStackOnExit(const ClearStackOnExit&);
 
        ClearStackOnExit& operator=(const ClearStackOnExit&);
 
        GenericDocument& d_;
 
    };
 

	
 
    // callers of the following private Handler functions
 
    // template <typename,typename,typename> friend class GenericReader; // for parsing
 
    template <typename, typename> friend class GenericValue; // for deep copying
 

	
 
public:
 
    // Implementation of Handler
 
    bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
 
    bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
 
    bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
 
    bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
 
    bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
 
    bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
 
    bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
 

	
 
    bool RawNumber(const Ch* str, SizeType length, bool copy) { 
 
        if (copy) 
 
            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
 
        else
 
            new (stack_.template Push<ValueType>()) ValueType(str, length);
 
        return true;
 
    }
 

	
 
    bool String(const Ch* str, SizeType length, bool copy) { 
 
        if (copy) 
 
            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
 
        else
 
            new (stack_.template Push<ValueType>()) ValueType(str, length);
 
        return true;
 
    }
 

	
 
    bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
 
    
 
    bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
 

	
 
    bool EndObject(SizeType memberCount) {
 
        typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
 
        stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
 
        return true;
 
    }
 

	
 
    bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
 
    
 
    bool EndArray(SizeType elementCount) {
 
        ValueType* elements = stack_.template Pop<ValueType>(elementCount);
 
        stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
 
        return true;
 
    }
 

	
 
private:
 
	// Prohibit assignment
 
	GenericDocument& operator=(const GenericDocument&);
 

	
 
	friend class GenericReader<Encoding, Allocator>;	// for Reader to call the following private handler functions
 

	
 
	// Implementation of Handler
 
	void Null()	{ new (stack_.template Push<ValueType>()) ValueType(); }
 
	void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); }
 
	void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); }
 
	void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); }
 
	void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
 
	void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
 
	void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); }
 

	
 
	void String(const Ch* str, SizeType length, bool copy) { 
 
		if (copy) 
 
			new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
 
		else
 
			new (stack_.template Push<ValueType>()) ValueType(str, length);
 
	}
 

	
 
	void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); }
 
	
 
	void EndObject(SizeType memberCount) {
 
		typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
 
		stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
 
	}
 

	
 
	void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); }
 
	
 
	void EndArray(SizeType elementCount) {
 
		ValueType* elements = stack_.template Pop<ValueType>(elementCount);
 
		stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
 
	}
 

	
 
	void ClearStack() {
 
		if (Allocator::kNeedFree)
 
			while (stack_.GetSize() > 0)	// Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
 
				(stack_.template Pop<ValueType>(1))->~ValueType();
 
		else
 
			stack_.Clear();
 
	}
 

	
 
	static const size_t kDefaultStackCapacity = 1024;
 
	internal::Stack<Allocator> stack_;
 
	const char* parseError_;
 
	size_t errorOffset_;
 
    //! Prohibit copying
 
    GenericDocument(const GenericDocument&);
 
    //! Prohibit assignment
 
    GenericDocument& operator=(const GenericDocument&);
 

	
 
    void ClearStack() {
 
        if (Allocator::kNeedFree)
 
            while (stack_.GetSize() > 0)    // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
 
                (stack_.template Pop<ValueType>(1))->~ValueType();
 
        else
 
            stack_.Clear();
 
        stack_.ShrinkToFit();
 
    }
 

	
 
    void Destroy() {
 
        RAPIDJSON_DELETE(ownAllocator_);
 
    }
 

	
 
    static const size_t kDefaultStackCapacity = 1024;
 
    Allocator* allocator_;
 
    Allocator* ownAllocator_;
 
    internal::Stack<StackAllocator> stack_;
 
    ParseResult parseResult_;
 
};
 

	
 
//! GenericDocument with UTF8 encoding
 
typedef GenericDocument<UTF8<> > Document;
 

	
 
} // namespace rapidjson
 
//! Helper class for accessing Value of array type.
 
/*!
 
    Instance of this helper class is obtained by \c GenericValue::GetArray().
 
    In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
 
*/
 
template <bool Const, typename ValueT>
 
class GenericArray {
 
public:
 
    typedef GenericArray<true, ValueT> ConstArray;
 
    typedef GenericArray<false, ValueT> Array;
 
    typedef ValueT PlainType;
 
    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
 
    typedef ValueType* ValueIterator;  // This may be const or non-const iterator
 
    typedef const ValueT* ConstValueIterator;
 
    typedef typename ValueType::AllocatorType AllocatorType;
 
    typedef typename ValueType::StringRefType StringRefType;
 

	
 
    template <typename, typename>
 
    friend class GenericValue;
 

	
 
    GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
 
    GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
 
    ~GenericArray() {}
 

	
 
    SizeType Size() const { return value_.Size(); }
 
    SizeType Capacity() const { return value_.Capacity(); }
 
    bool Empty() const { return value_.Empty(); }
 
    void Clear() const { value_.Clear(); }
 
    ValueType& operator[](SizeType index) const {  return value_[index]; }
 
    ValueIterator Begin() const { return value_.Begin(); }
 
    ValueIterator End() const { return value_.End(); }
 
    GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
 
    GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
 
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
 
    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
 
    GenericArray PopBack() const { value_.PopBack(); return *this; }
 
    ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
 
    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
 

	
 
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
 
    ValueIterator begin() const { return value_.Begin(); }
 
    ValueIterator end() const { return value_.End(); }
 
#endif
 

	
 
#ifdef _MSC_VER
 
#pragma warning(pop)
 
private:
 
    GenericArray();
 
    GenericArray(ValueType& value) : value_(value) {}
 
    ValueType& value_;
 
};
 

	
 
//! Helper class for accessing Value of object type.
 
/*!
 
    Instance of this helper class is obtained by \c GenericValue::GetObject().
 
    In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
 
*/
 
template <bool Const, typename ValueT>
 
class GenericObject {
 
public:
 
    typedef GenericObject<true, ValueT> ConstObject;
 
    typedef GenericObject<false, ValueT> Object;
 
    typedef ValueT PlainType;
 
    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
 
    typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator;  // This may be const or non-const iterator
 
    typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
 
    typedef typename ValueType::AllocatorType AllocatorType;
 
    typedef typename ValueType::StringRefType StringRefType;
 
    typedef typename ValueType::EncodingType EncodingType;
 
    typedef typename ValueType::Ch Ch;
 

	
 
    template <typename, typename>
 
    friend class GenericValue;
 

	
 
    GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
 
    GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
 
    ~GenericObject() {}
 

	
 
    SizeType MemberCount() const { return value_.MemberCount(); }
 
    SizeType MemberCapacity() const { return value_.MemberCapacity(); }
 
    bool ObjectEmpty() const { return value_.ObjectEmpty(); }
 
    template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
 
    template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
 
#if RAPIDJSON_HAS_STDSTRING
 
    ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
 
#endif
 
    MemberIterator MemberBegin() const { return value_.MemberBegin(); }
 
    MemberIterator MemberEnd() const { return value_.MemberEnd(); }
 
    GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }
 
    bool HasMember(const Ch* name) const { return value_.HasMember(name); }
 
#if RAPIDJSON_HAS_STDSTRING
 
    bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
 
#endif
 
    template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
 
    MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
 
    template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
 
#if RAPIDJSON_HAS_STDSTRING
 
    MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
 
#endif
 
    GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
#if RAPIDJSON_HAS_STDSTRING
 
    GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
#endif
 
    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 
    GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
 
    void RemoveAllMembers() { value_.RemoveAllMembers(); }
 
    bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
 
#if RAPIDJSON_HAS_STDSTRING
 
    bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
 
#endif
 
    template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
 
    MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
 
    MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
 
    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
 
    bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
 
#if RAPIDJSON_HAS_STDSTRING
 
    bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
 
#endif
 
    template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
 

	
 
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
 
    MemberIterator begin() const { return value_.MemberBegin(); }
 
    MemberIterator end() const { return value_.MemberEnd(); }
 
#endif
 

	
 
private:
 
    GenericObject();
 
    GenericObject(ValueType& value) : value_(value) {}
 
    ValueType& value_;
 
};
 

	
 
RAPIDJSON_NAMESPACE_END
 
RAPIDJSON_DIAG_POP
 

	
 
#endif // RAPIDJSON_DOCUMENT_H_
include/rapidjson/encodedstream.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
 
#define RAPIDJSON_ENCODEDSTREAM_H_
 

	
 
#include "stream.h"
 
#include "memorystream.h"
 

	
 
#ifdef __GNUC__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(effc++)
 
#endif
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(padded)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
//! Input byte stream wrapper with a statically bound encoding.
 
/*!
 
    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
 
    \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
 
*/
 
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) { 
 
        current_ = Encoding::TakeBOM(is_);
 
    }
 

	
 
    Ch Peek() const { return current_; }
 
    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; }
 

	
 
private:
 
    EncodedInputStream(const EncodedInputStream&);
 
    EncodedInputStream& operator=(const EncodedInputStream&);
 

	
 
    InputByteStream& is_;
 
    Ch current_;
 
};
 

	
 
//! Specialized for UTF8 MemoryStream.
 
template <>
 
class EncodedInputStream<UTF8<>, MemoryStream> {
 
public:
 
    typedef UTF8<>::Ch Ch;
 

	
 
    EncodedInputStream(MemoryStream& is) : is_(is) {
 
        if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
 
        if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
 
        if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
 
    }
 
    Ch Peek() const { return is_.Peek(); }
 
    Ch Take() { return is_.Take(); }
 
    size_t Tell() const { return is_.Tell(); }
 

	
 
    // Not implemented
 
    void Put(Ch) {}
 
    void Flush() {} 
 
    Ch* PutBegin() { return 0; }
 
    size_t PutEnd(Ch*) { return 0; }
 

	
 
    MemoryStream& is_;
 

	
 
private:
 
    EncodedInputStream(const EncodedInputStream&);
 
    EncodedInputStream& operator=(const EncodedInputStream&);
 
};
 

	
 
//! Output byte stream wrapper with statically bound encoding.
 
/*!
 
    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
 
    \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
 
*/
 
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) { 
 
        if (putBOM)
 
            Encoding::PutBOM(os_);
 
    }
 

	
 
    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; }
 

	
 
private:
 
    EncodedOutputStream(const EncodedOutputStream&);
 
    EncodedOutputStream& operator=(const EncodedOutputStream&);
 

	
 
    OutputByteStream& os_;
 
};
 

	
 
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
 

	
 
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
 
/*!
 
    \tparam CharType Type of character for reading.
 
    \tparam InputByteStream type of input byte stream to be wrapped.
 
*/
 
template <typename CharType, typename InputByteStream>
 
class AutoUTFInputStream {
 
    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
public:
 
    typedef CharType Ch;
 

	
 
    //! Constructor.
 
    /*!
 
        \param is input stream to be wrapped.
 
        \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);        
 
        DetectType();
 
        static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
 
        takeFunc_ = f[type_];
 
        current_ = takeFunc_(*is_);
 
    }
 

	
 
    UTFType GetType() const { return type_; }
 
    bool HasBOM() const { return hasBOM_; }
 

	
 
    Ch Peek() const { return current_; }
 
    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; }
 

	
 
private:
 
    AutoUTFInputStream(const AutoUTFInputStream&);
 
    AutoUTFInputStream& operator=(const AutoUTFInputStream&);
 

	
 
    // Detect encoding type with BOM or RFC 4627
 
    void DetectType() {
 
        // BOM (Byte Order Mark):
 
        // 00 00 FE FF  UTF-32BE
 
        // FF FE 00 00  UTF-32LE
 
        // FE FF        UTF-16BE
 
        // FF FE        UTF-16LE
 
        // EF BB BF     UTF-8
 

	
 
        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();              }
 

	
 
        // RFC 4627: Section 3
 
        // "Since the first two characters of a JSON text will always be ASCII
 
        // characters [RFC0020], it is possible to determine whether an octet
 
        // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
 
        // at the pattern of nulls in the first four octets."
 
        // 00 00 00 xx  UTF-32BE
 
        // 00 xx 00 xx  UTF-16BE
 
        // xx 00 00 00  UTF-32LE
 
        // xx 00 xx 00  UTF-16LE
 
        // xx xx xx xx  UTF-8
 

	
 
        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.
 
            }
 
        }
 

	
 
        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
 
        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
 
        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
 
    }
 

	
 
    typedef Ch (*TakeFunc)(InputByteStream& is);
 
    InputByteStream* is_;
 
    UTFType type_;
 
    Ch current_;
 
    TakeFunc takeFunc_;
 
    bool hasBOM_;
 
};
 

	
 
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
 
/*!
 
    \tparam CharType Type of character for writing.
 
    \tparam OutputByteStream type of output byte stream to be wrapped.
 
*/
 
template <typename CharType, typename OutputByteStream>
 
class AutoUTFOutputStream {
 
    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
public:
 
    typedef CharType Ch;
 

	
 
    //! Constructor.
 
    /*!
 
        \param os output stream to be wrapped.
 
        \param type UTF encoding type.
 
        \param putBOM Whether to write BOM at the beginning of the stream.
 
    */
 
    AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
 
        RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
 

	
 
        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
 
        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
 
        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
 

	
 
        static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
 
        putFunc_ = f[type_];
 

	
 
        if (putBOM)
 
            PutBOM();
 
    }
 

	
 
    UTFType GetType() const { return type_; }
 

	
 
    void Put(Ch c) { putFunc_(*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; }
 

	
 
private:
 
    AutoUTFOutputStream(const AutoUTFOutputStream&);
 
    AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
 

	
 
    void PutBOM() { 
 
        typedef void (*PutBOMFunc)(OutputByteStream&);
 
        static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
 
        f[type_](*os_);
 
    }
 

	
 
    typedef void (*PutFunc)(OutputByteStream&, Ch);
 

	
 
    OutputByteStream* os_;
 
    UTFType type_;
 
    PutFunc putFunc_;
 
};
 

	
 
#undef RAPIDJSON_ENCODINGS_FUNC
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#ifdef __GNUC__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_FILESTREAM_H_
include/rapidjson/encodings.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_ENCODINGS_H_
 
#define RAPIDJSON_ENCODINGS_H_
 

	
 
#include "rapidjson.h"
 

	
 
#ifdef _MSC_VER
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
 
RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 
#elif defined(__GNUC__)
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(effc++)
 
RAPIDJSON_DIAG_OFF(overflow)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// Encoding
 

	
 
/*! \class rapidjson::Encoding
 
    \brief Concept for encoding of Unicode characters.
 

	
 
\code
 
concept Encoding {
 
    typename Ch;    //! Type of character. A "character" is actually a code unit in unicode's definition.
 

	
 
    enum { supportUnicode = 1 }; // or 0 if not supporting unicode
 

	
 
    //! \brief Encode a Unicode codepoint to an output stream.
 
    //! \param os Output stream.
 
    //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
 
    template<typename OutputStream>
 
    static void Encode(OutputStream& os, unsigned codepoint);
 

	
 
    //! \brief Decode a Unicode codepoint from an input stream.
 
    //! \param is Input stream.
 
    //! \param codepoint Output of the unicode codepoint.
 
    //! \return true if a valid codepoint can be decoded from the stream.
 
    template <typename InputStream>
 
    static bool Decode(InputStream& is, unsigned* codepoint);
 

	
 
    //! \brief Validate one Unicode codepoint from an encoded stream.
 
    //! \param is Input stream to obtain codepoint.
 
    //! \param os Output for copying one codepoint.
 
    //! \return true if it is valid.
 
    //! \note This function just validating and copying the codepoint without actually decode it.
 
    template <typename InputStream, typename OutputStream>
 
    static bool Validate(InputStream& is, OutputStream& os);
 

	
 
    // The following functions are deal with byte streams.
 

	
 
    //! Take a character from input byte stream, skip BOM if exist.
 
    template <typename InputByteStream>
 
    static CharType TakeBOM(InputByteStream& is);
 

	
 
    //! Take a character from input byte stream.
 
    template <typename InputByteStream>
 
    static Ch Take(InputByteStream& is);
 

	
 
    //! Put BOM to output byte stream.
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os);
 

	
 
    //! Put a character to output byte stream.
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, Ch c);
 
};
 
\endcode
 
*/
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// UTF8
 

	
 
//! UTF-8 encoding.
 
/*! http://en.wikipedia.org/wiki/UTF-8
 
    http://tools.ietf.org/html/rfc3629
 
    \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
 
    \note implements Encoding concept
 
*/
 
template<typename CharType = char>
 
struct UTF8 {
 
    typedef CharType Ch;
 

	
 
    enum { supportUnicode = 1 };
 

	
 
    template<typename OutputStream>
 
    static void Encode(OutputStream& os, unsigned codepoint) {
 
        if (codepoint <= 0x7F) 
 
            os.Put(static_cast<Ch>(codepoint & 0xFF));
 
        else if (codepoint <= 0x7FF) {
 
            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
 
            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
 
        }
 
        else if (codepoint <= 0xFFFF) {
 
            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
 
            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 
            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 
        }
 
        else {
 
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 
            os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
 
            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
 
            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 
            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 
        }
 
    }
 

	
 
    template<typename OutputStream>
 
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 
        if (codepoint <= 0x7F) 
 
            PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
 
        else if (codepoint <= 0x7FF) {
 
            PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
 
        }
 
        else if (codepoint <= 0xFFFF) {
 
            PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 
        }
 
        else {
 
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 
            PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 
            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 
        }
 
    }
 

	
 
    template <typename InputStream>
 
    static bool Decode(InputStream& is, unsigned* codepoint) {
 
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
 
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 
#define TAIL() COPY(); TRANS(0x70)
 
        typename InputStream::Ch c = is.Take();
 
        if (!(c & 0x80)) {
 
            *codepoint = static_cast<unsigned char>(c);
 
            return true;
 
        }
 

	
 
        unsigned char type = GetRange(static_cast<unsigned char>(c));
 
        if (type >= 32) {
 
            *codepoint = 0;
 
        } else {
 
            *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
 
        }
 
        bool result = true;
 
        switch (type) {
 
        case 2: TAIL(); return result;
 
        case 3: TAIL(); TAIL(); return result;
 
        case 4: COPY(); TRANS(0x50); TAIL(); return result;
 
        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
 
        case 6: TAIL(); TAIL(); TAIL(); return result;
 
        case 10: COPY(); TRANS(0x20); TAIL(); return result;
 
        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
 
        default: return false;
 
        }
 
#undef COPY
 
#undef TRANS
 
#undef TAIL
 
    }
 

	
 
    template <typename InputStream, typename OutputStream>
 
    static bool Validate(InputStream& is, OutputStream& os) {
 
#define COPY() os.Put(c = is.Take())
 
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 
#define TAIL() COPY(); TRANS(0x70)
 
        Ch c;
 
        COPY();
 
        if (!(c & 0x80))
 
            return true;
 

	
 
        bool result = true;
 
        switch (GetRange(static_cast<unsigned char>(c))) {
 
        case 2: TAIL(); return result;
 
        case 3: TAIL(); TAIL(); return result;
 
        case 4: COPY(); TRANS(0x50); TAIL(); return result;
 
        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
 
        case 6: TAIL(); TAIL(); TAIL(); return result;
 
        case 10: COPY(); TRANS(0x20); TAIL(); return result;
 
        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
 
        default: return false;
 
        }
 
#undef COPY
 
#undef TRANS
 
#undef TAIL
 
    }
 

	
 
    static unsigned char GetRange(unsigned char c) {
 
        // 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,
 
        };
 
        return type[c];
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType TakeBOM(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        typename InputByteStream::Ch c = Take(is);
 
        if (static_cast<unsigned char>(c) != 0xEFu) return c;
 
        c = is.Take();
 
        if (static_cast<unsigned char>(c) != 0xBBu) return c;
 
        c = is.Take();
 
        if (static_cast<unsigned char>(c) != 0xBFu) return c;
 
        c = is.Take();
 
        return c;
 
    }
 

	
 
    template <typename InputByteStream>
 
    static Ch Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        return static_cast<Ch>(is.Take());
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, Ch c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(c));
 
    }
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// UTF16
 

	
 
//! UTF-16 encoding.
 
/*! http://en.wikipedia.org/wiki/UTF-16
 
    http://tools.ietf.org/html/rfc2781
 
    \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
 
    \note implements Encoding concept
 

	
 
    \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>
 
struct UTF16 {
 
    typedef CharType Ch;
 
    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
 

	
 
    enum { supportUnicode = 1 };
 

	
 
    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 
 
            os.Put(static_cast<typename OutputStream::Ch>(codepoint));
 
        }
 
        else {
 
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 
            unsigned v = codepoint - 0x10000;
 
            os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 
            os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 
        }
 
    }
 

	
 

	
 
    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 
 
            PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
 
        }
 
        else {
 
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 
            unsigned v = codepoint - 0x10000;
 
            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 
            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 
        }
 
    }
 

	
 
    template <typename InputStream>
 
    static bool Decode(InputStream& is, unsigned* codepoint) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
 
        typename InputStream::Ch c = is.Take();
 
        if (c < 0xD800 || c > 0xDFFF) {
 
            *codepoint = static_cast<unsigned>(c);
 
            return true;
 
        }
 
        else if (c <= 0xDBFF) {
 
            *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
 
            c = is.Take();
 
            *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
 
            *codepoint += 0x10000;
 
            return c >= 0xDC00 && c <= 0xDFFF;
 
        }
 
        return false;
 
    }
 

	
 
    template <typename InputStream, typename OutputStream>
 
    static bool Validate(InputStream& is, OutputStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
 
        typename InputStream::Ch c;
 
        os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
 
        if (c < 0xD800 || c > 0xDFFF)
 
            return true;
 
        else if (c <= 0xDBFF) {
 
            os.Put(c = is.Take());
 
            return c >= 0xDC00 && c <= 0xDFFF;
 
        }
 
        return false;
 
    }
 
};
 

	
 
//! UTF-16 little endian encoding.
 
template<typename CharType = wchar_t>
 
struct UTF16LE : UTF16<CharType> {
 
    template <typename InputByteStream>
 
    static CharType TakeBOM(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        CharType c = Take(is);
 
        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        unsigned c = static_cast<uint8_t>(is.Take());
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 
        return static_cast<CharType>(c);
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, CharType c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
 
    }
 
};
 

	
 
//! UTF-16 big endian encoding.
 
template<typename CharType = wchar_t>
 
struct UTF16BE : UTF16<CharType> {
 
    template <typename InputByteStream>
 
    static CharType TakeBOM(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        CharType c = Take(is);
 
        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
 
        return static_cast<CharType>(c);
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, CharType c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
 
    }
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// UTF32
 

	
 
//! 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
 

	
 
    \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>
 
struct UTF32 {
 
    typedef CharType Ch;
 
    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
 

	
 
    enum { supportUnicode = 1 };
 

	
 
    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>
 
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
 
        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 
        PutUnsafe(os, codepoint);
 
    }
 

	
 
    template <typename InputStream>
 
    static bool Decode(InputStream& is, unsigned* codepoint) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
 
        Ch c = is.Take();
 
        *codepoint = c;
 
        return c <= 0x10FFFF;
 
    }
 

	
 
    template <typename InputStream, typename OutputStream>
 
    static bool Validate(InputStream& is, OutputStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
 
        Ch c;
 
        os.Put(c = is.Take());
 
        return c <= 0x10FFFF;
 
    }
 
};
 

	
 
//! UTF-32 little endian enocoding.
 
template<typename CharType = unsigned>
 
struct UTF32LE : 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;
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        unsigned c = static_cast<uint8_t>(is.Take());
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
 
        return static_cast<CharType>(c);
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, CharType c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
 
    }
 
};
 

	
 
//! UTF-32 big endian encoding.
 
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; 
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
 
        return static_cast<CharType>(c);
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, CharType c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
 
        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
 
    }
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// ASCII
 

	
 
//! ASCII encoding.
 
/*! http://en.wikipedia.org/wiki/ASCII
 
    \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
 
    \note implements Encoding concept
 
*/
 
template<typename CharType = char>
 
struct ASCII {
 
    typedef CharType Ch;
 

	
 
    enum { supportUnicode = 0 };
 

	
 
    template<typename OutputStream>
 
    static void Encode(OutputStream& os, unsigned codepoint) {
 
        RAPIDJSON_ASSERT(codepoint <= 0x7F);
 
        os.Put(static_cast<Ch>(codepoint & 0xFF));
 
    }
 

	
 
    template<typename OutputStream>
 
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 
        RAPIDJSON_ASSERT(codepoint <= 0x7F);
 
        PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
 
    }
 

	
 
    template <typename InputStream>
 
    static bool Decode(InputStream& is, unsigned* codepoint) {
 
        uint8_t c = static_cast<uint8_t>(is.Take());
 
        *codepoint = c;
 
        return c <= 0X7F;
 
    }
 

	
 
    template <typename InputStream, typename OutputStream>
 
    static bool Validate(InputStream& is, OutputStream& os) {
 
        uint8_t c = static_cast<uint8_t>(is.Take());
 
        os.Put(static_cast<typename OutputStream::Ch>(c));
 
        return c <= 0x7F;
 
    }
 

	
 
    template <typename InputByteStream>
 
    static CharType TakeBOM(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        uint8_t c = static_cast<uint8_t>(Take(is));
 
        return static_cast<Ch>(c);
 
    }
 

	
 
    template <typename InputByteStream>
 
    static Ch Take(InputByteStream& is) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 
        return static_cast<Ch>(is.Take());
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void PutBOM(OutputByteStream& os) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        (void)os;
 
    }
 

	
 
    template <typename OutputByteStream>
 
    static void Put(OutputByteStream& os, Ch c) {
 
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 
        os.Put(static_cast<typename OutputByteStream::Ch>(c));
 
    }
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// AutoUTF
 

	
 
//! 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.
 
};
 

	
 
//! 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>
 
struct AutoUTF {
 
    typedef CharType Ch;
 

	
 
    enum { supportUnicode = 1 };
 

	
 
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
 

	
 
    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>
 
    static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 
        typedef void (*EncodeFunc)(OutputStream&, unsigned);
 
        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
 
        (*f[os.GetType()])(os, codepoint);
 
    }
 

	
 
    template <typename InputStream>
 
    static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
 
        typedef bool (*DecodeFunc)(InputStream&, unsigned*);
 
        static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
 
        return (*f[is.GetType()])(is, codepoint);
 
    }
 

	
 
    template <typename InputStream, typename OutputStream>
 
    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
 
        typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
 
        static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
 
        return (*f[is.GetType()])(is, os);
 
    }
 

	
 
#undef RAPIDJSON_ENCODINGS_FUNC
 
};
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// Transcoder
 

	
 
//! Encoding conversion.
 
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>
 
    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
 
        unsigned codepoint;
 
        if (!SourceEncoding::Decode(is, &codepoint))
 
            return false;
 
        TargetEncoding::Encode(os, codepoint);
 
        return true;
 
    }
 

	
 
    template<typename InputStream, typename OutputStream>
 
    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
 
        unsigned codepoint;
 
        if (!SourceEncoding::Decode(is, &codepoint))
 
            return false;
 
        TargetEncoding::EncodeUnsafe(os, codepoint);
 
        return true;
 
    }
 

	
 
    //! Validate one Unicode codepoint from an encoded stream.
 
    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.
 
    }
 
};
 

	
 
// Forward declaration.
 
template<typename Stream>
 
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
 

	
 
//! Specialization of Transcoder with same source and target encoding.
 
template<typename Encoding>
 
struct Transcoder<Encoding, Encoding> {
 
    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.
 
        return true;
 
    }
 
    
 
    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.
 
        return true;
 
    }
 
    
 
    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
 
    }
 
};
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#if defined(__GNUC__) || defined(_MSC_VER)
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_ENCODINGS_H_
include/rapidjson/error/en.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_ERROR_EN_H_
 
#define RAPIDJSON_ERROR_EN_H_
 

	
 
#include "error.h"
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(switch-enum)
 
RAPIDJSON_DIAG_OFF(covered-switch-default)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
//! Maps error code of parsing into error message.
 
/*!
 
    \ingroup RAPIDJSON_ERRORS
 
    \param parseErrorCode Error code obtained in parsing.
 
    \return the error message.
 
    \note User can make a copy of this function for localization.
 
        Using switch-case is safer for future modification of error codes.
 
*/
 
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
 
    switch (parseErrorCode) {
 
        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 kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
 
    
 
        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
 
        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
 
        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
 
    
 
        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
 

	
 
        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
 
        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.");
 
    }
 
}
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_ERROR_EN_H_
include/rapidjson/error/error.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_ERROR_ERROR_H_
 
#define RAPIDJSON_ERROR_ERROR_H_
 

	
 
#include "../rapidjson.h"
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(padded)
 
#endif
 

	
 
/*! \file error.h */
 

	
 
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// RAPIDJSON_ERROR_CHARTYPE
 

	
 
//! Character type of error messages.
 
/*! \ingroup RAPIDJSON_ERRORS
 
    The default character type is \c char.
 
    On Windows, user can define this macro as \c TCHAR for supporting both
 
    unicode/non-unicode settings.
 
*/
 
#ifndef RAPIDJSON_ERROR_CHARTYPE
 
#define RAPIDJSON_ERROR_CHARTYPE char
 
#endif
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// RAPIDJSON_ERROR_STRING
 

	
 
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
 
/*! \ingroup RAPIDJSON_ERRORS
 
    By default this conversion macro does nothing.
 
    On Windows, user can define this macro as \c _T(x) for supporting both
 
    unicode/non-unicode settings.
 
*/
 
#ifndef RAPIDJSON_ERROR_STRING
 
#define RAPIDJSON_ERROR_STRING(x) x
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
///////////////////////////////////////////////////////////////////////////////
 
// ParseErrorCode
 

	
 
//! Error code of parsing.
 
/*! \ingroup RAPIDJSON_ERRORS
 
    \see GenericReader::Parse, GenericReader::GetParseErrorCode
 
*/
 
enum ParseErrorCode {
 
    kParseErrorNone = 0,                        //!< No error.
 

	
 
    kParseErrorDocumentEmpty,                   //!< The document is empty.
 
    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.
 

	
 
    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.
 

	
 
    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.
 

	
 
    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.
 
};
 

	
 
//! Result of parsing (wraps ParseErrorCode)
 
/*!
 
    \ingroup RAPIDJSON_ERRORS
 
    \code
 
        Document doc;
 
        ParseResult ok = doc.Parse("[42]");
 
        if (!ok) {
 
            fprintf(stderr, "JSON parse error: %s (%u)",
 
                    GetParseError_En(ok.Code()), ok.Offset());
 
            exit(EXIT_FAILURE);
 
        }
 
    \endcode
 
    \see GenericReader::Parse, GenericDocument::Parse
 
*/
 
struct ParseResult {
 
    //!! Unspecified boolean type
 
    typedef bool (ParseResult::*BooleanType)() const;
 
public:
 
    //! Default constructor, no error.
 
    ParseResult() : code_(kParseErrorNone), offset_(0) {}
 
    //! Constructor to set an error.
 
    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
 

	
 
    //! Get the error code.
 
    ParseErrorCode Code() const { return code_; }
 
    //! Get the error offset, if \ref IsError(), 0 otherwise.
 
    size_t Offset() const { return offset_; }
 

	
 
    //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
 
    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
 
    //! Whether the result is an error.
 
    bool IsError() const { return code_ != kParseErrorNone; }
 

	
 
    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_; }
 

	
 
    bool operator!=(const ParseResult& that) const { return !(*this == that); }
 
    bool operator!=(ParseErrorCode code) const { return !(*this == code); }
 
    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
 

	
 
    //! Reset error code.
 
    void Clear() { Set(kParseErrorNone); }
 
    //! Update error code and offset.
 
    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
 

	
 
private:
 
    ParseErrorCode code_;
 
    size_t offset_;
 
};
 

	
 
//! Function pointer type of GetParseError().
 
/*! \ingroup RAPIDJSON_ERRORS
 

	
 
    This is the prototype for \c GetParseError_X(), where \c X is a locale.
 
    User can dynamically change locale in runtime, e.g.:
 
\code
 
    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
 
    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
 
\endcode
 
*/
 
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_ERROR_ERROR_H_
include/rapidjson/filereadstream.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_FILEREADSTREAM_H_
 
#define RAPIDJSON_FILEREADSTREAM_H_
 

	
 
#include "stream.h"
 
#include <cstdio>
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(padded)
 
RAPIDJSON_DIAG_OFF(unreachable-code)
 
RAPIDJSON_DIAG_OFF(missing-noreturn)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
//! File byte stream for input using fread().
 
/*!
 
    \note implements Stream concept
 
*/
 
class FileReadStream {
 
public:
 
    typedef char Ch;    //!< Character type (byte).
 

	
 
    //! Constructor.
 
    /*!
 
        \param fp File pointer opened for read.
 
        \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) { 
 
        RAPIDJSON_ASSERT(fp_ != 0);
 
        RAPIDJSON_ASSERT(bufferSize >= 4);
 
        Read();
 
    }
 

	
 
    Ch Peek() const { return *current_; }
 
    Ch Take() { Ch c = *current_; Read(); return c; }
 
    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
 

	
 
    // 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; }
 

	
 
    // For encoding detection only.
 
    const Ch* Peek4() const {
 
        return (current_ + 4 <= bufferLast_) ? current_ : 0;
 
    }
 

	
 
private:
 
    void Read() {
 
        if (current_ < bufferLast_)
 
            ++current_;
 
        else if (!eof_) {
 
            count_ += readCount_;
 
            readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
 
            bufferLast_ = buffer_ + readCount_ - 1;
 
            current_ = buffer_;
 

	
 
            if (readCount_ < bufferSize_) {
 
                buffer_[readCount_] = '\0';
 
                ++bufferLast_;
 
                eof_ = true;
 
            }
 
        }
 
    }
 

	
 
    std::FILE* fp_;
 
    Ch *buffer_;
 
    size_t bufferSize_;
 
    Ch *bufferLast_;
 
    Ch *current_;
 
    size_t readCount_;
 
    size_t count_;  //!< Number of characters read
 
    bool eof_;
 
};
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_FILESTREAM_H_
include/rapidjson/filestream.h
Show inline comments
 
deleted file
include/rapidjson/filewritestream.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
 
#define RAPIDJSON_FILEWRITESTREAM_H_
 

	
 
#include "stream.h"
 
#include <cstdio>
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(unreachable-code)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 

	
 
//! Wrapper of C file stream for output using fwrite().
 
/*!
 
    \note implements Stream concept
 
*/
 
class FileWriteStream {
 
public:
 
    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_) { 
 
        RAPIDJSON_ASSERT(fp_ != 0);
 
    }
 

	
 
    void Put(char c) { 
 
        if (current_ >= bufferEnd_)
 
            Flush();
 

	
 
        *current_++ = c;
 
    }
 

	
 
    void PutN(char c, size_t n) {
 
        size_t avail = static_cast<size_t>(bufferEnd_ - current_);
 
        while (n > avail) {
 
            std::memset(current_, c, avail);
 
            current_ += avail;
 
            Flush();
 
            n -= avail;
 
            avail = static_cast<size_t>(bufferEnd_ - current_);
 
        }
 

	
 
        if (n > 0) {
 
            std::memset(current_, c, n);
 
            current_ += n;
 
        }
 
    }
 

	
 
    void Flush() {
 
        if (current_ != buffer_) {
 
            size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
 
            if (result < static_cast<size_t>(current_ - buffer_)) {
 
                // failure deliberately ignored at this time
 
                // added to avoid warn_unused_result build errors
 
            }
 
            current_ = buffer_;
 
        }
 
    }
 

	
 
    // 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; }
 

	
 
private:
 
    // Prohibit copy constructor & assignment operator.
 
    FileWriteStream(const FileWriteStream&);
 
    FileWriteStream& operator=(const FileWriteStream&);
 

	
 
    std::FILE* fp_;
 
    char *buffer_;
 
    char *bufferEnd_;
 
    char *current_;
 
};
 

	
 
//! Implement specialized version of PutN() with memset() for better performance.
 
template<>
 
inline void PutN(FileWriteStream& stream, char c, size_t n) {
 
    stream.PutN(c, n);
 
}
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#endif // RAPIDJSON_FILESTREAM_H_
include/rapidjson/fwd.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_FWD_H_
 
#define RAPIDJSON_FWD_H_
 

	
 
#include "rapidjson.h"
 

	
 
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 SourceEncoding, typename TargetEncoding>
 
struct Transcoder;
 

	
 
// allocators.h
 

	
 
class CrtAllocator;
 

	
 
template <typename BaseAllocator>
 
class MemoryPoolAllocator;
 

	
 
// stream.h
 

	
 
template <typename Encoding>
 
struct GenericStringStream;
 

	
 
typedef GenericStringStream<UTF8<char> > StringStream;
 

	
 
template <typename Encoding>
 
struct GenericInsituStringStream;
 

	
 
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
 

	
 
// stringbuffer.h
 

	
 
template <typename Encoding, typename Allocator>
 
class GenericStringBuffer;
 

	
 
typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
 

	
 
// filereadstream.h
 

	
 
class FileReadStream;
 

	
 
// filewritestream.h
 

	
 
class FileWriteStream;
 

	
 
// memorybuffer.h
 

	
 
template <typename Allocator>
 
struct GenericMemoryBuffer;
 

	
 
typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
 

	
 
// memorystream.h
 

	
 
struct MemoryStream;
 

	
 
// reader.h
 

	
 
template<typename Encoding, typename Derived>
 
struct BaseReaderHandler;
 

	
 
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
 
class GenericReader;
 

	
 
typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
 

	
 
// writer.h
 

	
 
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>
 
class PrettyWriter;
 

	
 
// document.h
 

	
 
template <typename Encoding, typename Allocator> 
 
struct GenericMember;
 

	
 
template <bool Const, typename Encoding, typename Allocator>
 
class GenericMemberIterator;
 

	
 
template<typename CharType>
 
struct GenericStringRef;
 

	
 
template <typename Encoding, typename Allocator> 
 
class GenericValue;
 

	
 
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
 

	
 
template <typename Encoding, typename Allocator, typename StackAllocator>
 
class GenericDocument;
 

	
 
typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
 

	
 
// pointer.h
 

	
 
template <typename ValueType, typename Allocator>
 
class GenericPointer;
 

	
 
typedef GenericPointer<Value, CrtAllocator> Pointer;
 

	
 
// schema.h
 

	
 
template <typename SchemaDocumentType>
 
class IGenericRemoteSchemaDocumentProvider;
 

	
 
template <typename ValueT, typename Allocator>
 
class GenericSchemaDocument;
 

	
 
typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
 
typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
 

	
 
template <
 
    typename SchemaDocumentType,
 
    typename OutputHandler,
 
    typename StateAllocator>
 
class GenericSchemaValidator;
 

	
 
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
 

	
 
RAPIDJSON_NAMESPACE_END
 

	
 
#endif // RAPIDJSON_RAPIDJSONFWD_H_
include/rapidjson/internal/biginteger.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
#ifndef RAPIDJSON_BIGINTEGER_H_
 
#define RAPIDJSON_BIGINTEGER_H_
 

	
 
#include "../rapidjson.h"
 

	
 
#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)
 
#include <intrin.h> // for _umul128
 
#pragma intrinsic(_umul128)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 
namespace internal {
 

	
 
class BigInteger {
 
public:
 
    typedef uint64_t Type;
 

	
 
    BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
 
        std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
 
    }
 

	
 
    explicit BigInteger(uint64_t u) : count_(1) {
 
        digits_[0] = u;
 
    }
 

	
 
    BigInteger(const char* decimals, size_t length) : count_(1) {
 
        RAPIDJSON_ASSERT(length > 0);
 
        digits_[0] = 0;
 
        size_t i = 0;
 
        const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19
 
        while (length >= kMaxDigitPerIteration) {
 
            AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
 
            length -= kMaxDigitPerIteration;
 
            i += kMaxDigitPerIteration;
 
        }
 

	
 
        if (length > 0)
 
            AppendDecimal64(decimals + i, decimals + i + length);
 
    }
 
    
 
    BigInteger& operator=(const BigInteger &rhs)
 
    {
 
        if (this != &rhs) {
 
            count_ = rhs.count_;
 
            std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
 
        }
 
        return *this;
 
    }
 
    
 
    BigInteger& operator=(uint64_t u) {
 
        digits_[0] = u;            
 
        count_ = 1;
 
        return *this;
 
    }
 

	
 
    BigInteger& operator+=(uint64_t u) {
 
        Type backup = digits_[0];
 
        digits_[0] += u;
 
        for (size_t i = 0; i < count_ - 1; i++) {
 
            if (digits_[i] >= backup)
 
                return *this; // no carry
 
            backup = digits_[i + 1];
 
            digits_[i + 1] += 1;
 
        }
 

	
 
        // Last carry
 
        if (digits_[count_ - 1] < backup)
 
            PushBack(1);
 

	
 
        return *this;
 
    }
 

	
 
    BigInteger& operator*=(uint64_t u) {
 
        if (u == 0) return *this = 0;
 
        if (u == 1) return *this;
 
        if (*this == 1) return *this = u;
 

	
 
        uint64_t k = 0;
 
        for (size_t i = 0; i < count_; i++) {
 
            uint64_t hi;
 
            digits_[i] = MulAdd64(digits_[i], u, k, &hi);
 
            k = hi;
 
        }
 
        
 
        if (k > 0)
 
            PushBack(k);
 

	
 
        return *this;
 
    }
 

	
 
    BigInteger& operator*=(uint32_t u) {
 
        if (u == 0) return *this = 0;
 
        if (u == 1) return *this;
 
        if (*this == 1) return *this = u;
 

	
 
        uint64_t k = 0;
 
        for (size_t i = 0; i < count_; i++) {
 
            const uint64_t c = digits_[i] >> 32;
 
            const uint64_t d = digits_[i] & 0xFFFFFFFF;
 
            const uint64_t uc = u * c;
 
            const uint64_t ud = u * d;
 
            const uint64_t p0 = ud + k;
 
            const uint64_t p1 = uc + (p0 >> 32);
 
            digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
 
            k = p1 >> 32;
 
        }
 
        
 
        if (k > 0)
 
            PushBack(k);
 

	
 
        return *this;
 
    }
 

	
 
    BigInteger& operator<<=(size_t shift) {
 
        if (IsZero() || shift == 0) return *this;
 

	
 
        size_t offset = shift / kTypeBit;
 
        size_t interShift = shift % kTypeBit;
 
        RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
 

	
 
        if (interShift == 0) {
 
            std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
 
            count_ += offset;
 
        }
 
        else {
 
            digits_[count_] = 0;
 
            for (size_t i = count_; i > 0; i--)
 
                digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
 
            digits_[offset] = digits_[0] << interShift;
 
            count_ += offset;
 
            if (digits_[count_])
 
                count_++;
 
        }
 

	
 
        std::memset(digits_, 0, offset * sizeof(Type));
 

	
 
        return *this;
 
    }
 

	
 
    bool operator==(const BigInteger& rhs) const {
 
        return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
 
    }
 

	
 
    bool operator==(const Type rhs) const {
 
        return count_ == 1 && digits_[0] == rhs;
 
    }
 

	
 
    BigInteger& MultiplyPow5(unsigned exp) {
 
        static const uint32_t kPow5[12] = {
 
            5,
 
            5 * 5,
 
            5 * 5 * 5,
 
            5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
 
            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
 
        };
 
        if (exp == 0) return *this;
 
        for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
 
        for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
 
        if (exp > 0)                 *this *= kPow5[exp - 1];
 
        return *this;
 
    }
 

	
 
    // Compute absolute difference of this and rhs.
 
    // Assume this != rhs
 
    bool Difference(const BigInteger& rhs, BigInteger* out) const {
 
        int cmp = Compare(rhs);
 
        RAPIDJSON_ASSERT(cmp != 0);
 
        const BigInteger *a, *b;  // Makes a > b
 
        bool ret;
 
        if (cmp < 0) { a = &rhs; b = this; ret = true; }
 
        else         { a = this; b = &rhs; ret = false; }
 

	
 
        Type borrow = 0;
 
        for (size_t i = 0; i < a->count_; i++) {
 
            Type d = a->digits_[i] - borrow;
 
            if (i < b->count_)
 
                d -= b->digits_[i];
 
            borrow = (d > a->digits_[i]) ? 1 : 0;
 
            out->digits_[i] = d;
 
            if (d != 0)
 
                out->count_ = i + 1;
 
        }
 

	
 
        return ret;
 
    }
 

	
 
    int Compare(const BigInteger& rhs) const {
 
        if (count_ != rhs.count_)
 
            return count_ < rhs.count_ ? -1 : 1;
 

	
 
        for (size_t i = count_; i-- > 0;)
 
            if (digits_[i] != rhs.digits_[i])
 
                return digits_[i] < rhs.digits_[i] ? -1 : 1;
 

	
 
        return 0;
 
    }
 

	
 
    size_t GetCount() const { return count_; }
 
    Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
 
    bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
 

	
 
private:
 
    void AppendDecimal64(const char* begin, const char* end) {
 
        uint64_t u = ParseUint64(begin, end);
 
        if (IsZero())
 
            *this = u;
 
        else {
 
            unsigned exp = static_cast<unsigned>(end - begin);
 
            (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u
 
        }
 
    }
 

	
 
    void PushBack(Type digit) {
 
        RAPIDJSON_ASSERT(count_ < kCapacity);
 
        digits_[count_++] = digit;
 
    }
 

	
 
    static uint64_t ParseUint64(const char* begin, const char* end) {
 
        uint64_t r = 0;
 
        for (const char* p = begin; p != end; ++p) {
 
            RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
 
            r = r * 10u + static_cast<unsigned>(*p - '0');
 
        }
 
        return r;
 
    }
 

	
 
    // Assume a * b + k < 2^128
 
    static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
 
#if defined(_MSC_VER) && defined(_M_AMD64)
 
        uint64_t low = _umul128(a, b, outHigh) + k;
 
        if (low < k)
 
            (*outHigh)++;
 
        return low;
 
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
 
        __extension__ typedef unsigned __int128 uint128;
 
        uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
 
        p += k;
 
        *outHigh = static_cast<uint64_t>(p >> 64);
 
        return static_cast<uint64_t>(p);
 
#else
 
        const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
 
        uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
 
        x1 += (x0 >> 32); // can't give carry
 
        x1 += x2;
 
        if (x1 < x2)
 
            x3 += (static_cast<uint64_t>(1) << 32);
 
        uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
 
        uint64_t hi = x3 + (x1 >> 32);
 

	
 
        lo += k;
 
        if (lo < k)
 
            hi++;
 
        *outHigh = hi;
 
        return lo;
 
#endif
 
    }
 

	
 
    static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000
 
    static const size_t kCapacity = kBitCount / sizeof(Type);
 
    static const size_t kTypeBit = sizeof(Type) * 8;
 

	
 
    Type digits_[kCapacity];
 
    size_t count_;
 
};
 

	
 
} // namespace internal
 
RAPIDJSON_NAMESPACE_END
 

	
 
#endif // RAPIDJSON_BIGINTEGER_H_
include/rapidjson/internal/diyfp.h
Show inline comments
 
new file 100644
 
// Tencent is pleased to support the open source community by making RapidJSON available.
 
// 
 
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
 
//
 
// Licensed under the MIT License (the "License"); you may not use this file except
 
// in compliance with the License. You may obtain a copy of the License at
 
//
 
// http://opensource.org/licenses/MIT
 
//
 
// Unless required by applicable law or agreed to in writing, software distributed 
 
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 
// specific language governing permissions and limitations under the License.
 

	
 
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
 
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
 
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
 

	
 
#ifndef RAPIDJSON_DIYFP_H_
 
#define RAPIDJSON_DIYFP_H_
 

	
 
#include "../rapidjson.h"
 

	
 
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
 
#include <intrin.h>
 
#pragma intrinsic(_BitScanReverse64)
 
#pragma intrinsic(_umul128)
 
#endif
 

	
 
RAPIDJSON_NAMESPACE_BEGIN
 
namespace internal {
 

	
 
#ifdef __GNUC__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(effc++)
 
#endif
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_PUSH
 
RAPIDJSON_DIAG_OFF(padded)
 
#endif
 

	
 
struct DiyFp {
 
    DiyFp() : f(), e() {}
 

	
 
    DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
 

	
 
    explicit DiyFp(double d) {
 
        union {
 
            double d;
 
            uint64_t u64;
 
        } u = { d };
 

	
 
        int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
 
        uint64_t significand = (u.u64 & kDpSignificandMask);
 
        if (biased_e != 0) {
 
            f = significand + kDpHiddenBit;
 
            e = biased_e - kDpExponentBias;
 
        } 
 
        else {
 
            f = significand;
 
            e = kDpMinExponent + 1;
 
        }
 
    }
 

	
 
    DiyFp operator-(const DiyFp& rhs) const {
 
        return DiyFp(f - rhs.f, e);
 
    }
 

	
 
    DiyFp operator*(const DiyFp& rhs) const {
 
#if defined(_MSC_VER) && defined(_M_AMD64)
 
        uint64_t h;
 
        uint64_t l = _umul128(f, rhs.f, &h);
 
        if (l & (uint64_t(1) << 63)) // rounding
 
            h++;
 
        return DiyFp(h, e + rhs.e + 64);
 
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
 
        __extension__ typedef unsigned __int128 uint128;
 
        uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
 
        uint64_t h = static_cast<uint64_t>(p >> 64);
 
        uint64_t l = static_cast<uint64_t>(p);
 
        if (l & (uint64_t(1) << 63)) // rounding
 
            h++;
 
        return DiyFp(h, e + rhs.e + 64);
 
#else
 
        const uint64_t M32 = 0xFFFFFFFF;
 
        const uint64_t a = f >> 32;
 
        const uint64_t b = f & M32;
 
        const uint64_t c = rhs.f >> 32;
 
        const uint64_t d = rhs.f & M32;
 
        const uint64_t ac = a * c;
 
        const uint64_t bc = b * c;
 
        const uint64_t ad = a * d;
 
        const uint64_t bd = b * d;
 
        uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
 
        tmp += 1U << 31;  /// mult_round
 
        return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
 
#endif
 
    }
 

	
 
    DiyFp Normalize() const {
 
#if defined(_MSC_VER) && defined(_M_AMD64)
 
        unsigned long index;
 
        _BitScanReverse64(&index, f);
 
        return DiyFp(f << (63 - index), e - (63 - index));
 
#elif defined(__GNUC__) && __GNUC__ >= 4
 
        int s = __builtin_clzll(f);
 
        return DiyFp(f << s, e - s);
 
#else
 
        DiyFp res = *this;
 
        while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
 
            res.f <<= 1;
 
            res.e--;
 
        }
 
        return res;
 
#endif
 
    }
 

	
 
    DiyFp NormalizeBoundary() const {
 
        DiyFp res = *this;
 
        while (!(res.f & (kDpHiddenBit << 1))) {
 
            res.f <<= 1;
 
            res.e--;
 
        }
 
        res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
 
        res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
 
        return res;
 
    }
 

	
 
    void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
 
        DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
 
        DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
 
        mi.f <<= mi.e - pl.e;
 
        mi.e = pl.e;
 
        *plus = pl;
 
        *minus = mi;
 
    }
 

	
 
    double ToDouble() const {
 
        union {
 
            double d;
 
            uint64_t u64;
 
        }u;
 
        const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : 
 
            static_cast<uint64_t>(e + kDpExponentBias);
 
        u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
 
        return u.d;
 
    }
 

	
 
    static const int kDiySignificandSize = 64;
 
    static const int kDpSignificandSize = 52;
 
    static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
 
    static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
 
    static const int kDpMinExponent = -kDpExponentBias;
 
    static const int kDpDenormalExponent = -kDpExponentBias + 1;
 
    static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
 
    static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
 
    static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
 

	
 
    uint64_t f;
 
    int e;
 
};
 

	
 
inline DiyFp GetCachedPowerByIndex(size_t index) {
 
    // 10^-348, 10^-340, ..., 10^340
 
    static const uint64_t kCachedPowers_F[] = {
 
        RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
 
        RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
 
        RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
 
        RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
 
        RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
 
        RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
 
        RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
 
        RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
 
        RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
 
        RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
 
        RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
 
        RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
 
        RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
 
        RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
 
        RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
 
        RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
 
        RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
 
        RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
 
        RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
 
        RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
 
        RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
 
        RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
 
        RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
 
        RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
 
        RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
 
        RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
 
        RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
 
        RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
 
        RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
 
        RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
 
        RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
 
        RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
 
        RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
 
        RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
 
        RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
 
        RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
 
        RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
 
        RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
 
        RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
 
        RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
 
        RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
 
        RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
 
        RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
 
        RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
 
    };
 
    static const int16_t kCachedPowers_E[] = {
 
        -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,
 
        -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,
 
        -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,
 
        -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,
 
        -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,
 
        109,   136,   162,   189,   216,   242,   269,   295,   322,   348,
 
        375,   402,   428,   455,   481,   508,   534,   561,   588,   614,
 
        641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
 
        907,   933,   960,   986,  1013,  1039,  1066
 
    };
 
    return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
 
}
 
    
 
inline DiyFp GetCachedPower(int e, int* K) {
 

	
 
    //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
 
    double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
 
    int k = static_cast<int>(dk);
 
    if (dk - k > 0.0)
 
        k++;
 

	
 
    unsigned index = static_cast<unsigned>((k >> 3) + 1);
 
    *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table
 

	
 
    return GetCachedPowerByIndex(index);
 
}
 

	
 
inline DiyFp GetCachedPower10(int exp, int *outExp) {
 
     unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
 
     *outExp = -348 + static_cast<int>(index) * 8;
 
     return GetCachedPowerByIndex(index);
 
 }
 

	
 
#ifdef __GNUC__
 
RAPIDJSON_DIAG_POP
 
#endif
 

	
 
#ifdef __clang__
 
RAPIDJSON_DIAG_POP
 
RAPIDJSON_DIAG_OFF(padded)
 
#endif
 

	
 
} // namespace internal
 
RAPIDJSON_NAMESPACE_END
 

	
 
#endif // RAPIDJSON_DIYFP_H_

Changeset was too big and was cut off... Show full diff anyway

0 comments (0 inline, 0 general)