// Tencent is pleased to support the open source community by making RapidJSON available. // // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. // // Licensed under the MIT License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://opensource.org/licenses/MIT // // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_DOCUMENT_H_ #define RAPIDJSON_DOCUMENT_H_ /*! \file document.h */ #include "reader.h" #include "internal/meta.h" #include "internal/strfunc.h" #include "memorystream.h" #include "encodedstream.h" #include <new> // placement new #include <limits> #ifdef __cpp_lib_three_way_comparison #include <compare> #endif RAPIDJSON_DIAG_PUSH #ifdef __clang__ RAPIDJSON_DIAG_OFF(…) RAPIDJSON_DIAG_OFF(…) RAPIDJSON_DIAG_OFF(…) #elif defined(_MSC_VER) RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data #endif #ifdef __GNUC__ RAPIDJSON_DIAG_OFF(…) #endif // __GNUC__ #ifdef GetObject // see https://github.com/Tencent/rapidjson/issues/1448 // a former included windows.h might have defined a macro called GetObject, which affects // GetObject defined here. This ensures the macro does not get applied #pragma push_macro("GetObject") #define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED #undef GetObject #endif #ifndef RAPIDJSON_NOMEMBERITERATORCLASS #include <iterator> // std::random_access_iterator_tag #endif #if RAPIDJSON_USE_MEMBERSMAP #include <map> // std::multimap #endif RAPIDJSON_NAMESPACE_BEGIN // Forward declaration. template <typename Encoding, typename Allocator> class GenericValue; template <typename Encoding, typename Allocator, typename StackAllocator> class GenericDocument; /*! \def RAPIDJSON_DEFAULT_ALLOCATOR \ingroup RAPIDJSON_CONFIG \brief Allows to choose default allocator. User can define this to use CrtAllocator or MemoryPoolAllocator. */ #ifndef RAPIDJSON_DEFAULT_ALLOCATOR #define RAPIDJSON_DEFAULT_ALLOCATOR … #endif /*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR \ingroup RAPIDJSON_CONFIG \brief Allows to choose default stack allocator for Document. User can define this to use CrtAllocator or MemoryPoolAllocator. */ #ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR #define RAPIDJSON_DEFAULT_STACK_ALLOCATOR … #endif /*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY \ingroup RAPIDJSON_CONFIG \brief User defined kDefaultObjectCapacity value. User can define this as any natural number. */ #ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY // number of objects that rapidjson::Value allocates memory for by default #define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY … #endif /*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY \ingroup RAPIDJSON_CONFIG \brief User defined kDefaultArrayCapacity value. User can define this as any natural number. */ #ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY // number of array elements that rapidjson::Value allocates memory for by default #define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY … #endif //! 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> class GenericMember { … }; /////////////////////////////////////////////////////////////////////////////// // 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 { … }; #else // RAPIDJSON_NOMEMBERITERATORCLASS // class-based member iterator implementation disabled, use plain pointers template <bool Const, typename Encoding, typename Allocator> class GenericMemberIterator; //! non-const GenericMemberIterator template <typename Encoding, typename Allocator> class GenericMemberIterator<false,Encoding,Allocator> { public: //! use plain pointer as iterator type typedef GenericMember<Encoding,Allocator>* Iterator; }; //! const GenericMemberIterator template <typename Encoding, typename Allocator> class GenericMemberIterator<true,Encoding,Allocator> { public: //! 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 { … }; template<typename CharType> const CharType GenericStringRef<CharType>::emptyString[] = …; //! 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) { … } //! 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) { … } #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) { … } #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 IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::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 { … }; TypeHelper<ValueType, bool>; TypeHelper<ValueType, int>; TypeHelper<ValueType, unsigned int>; #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 TypeHelper<ValueType, int64_t>; TypeHelper<ValueType, uint64_t>; TypeHelper<ValueType, double>; TypeHelper<ValueType, float>; TypeHelper<ValueType, const typename ValueType::Ch *>; #if RAPIDJSON_HAS_STDSTRING TypeHelper<ValueType, std::basic_string<typename ValueType::Ch>>; #endif TypeHelper<ValueType, typename ValueType::Array>; TypeHelper<ValueType, typename ValueType::ConstArray>; TypeHelper<ValueType, typename ValueType::Object>; TypeHelper<ValueType, typename ValueType::ConstObject>; } // 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. 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. */ template <typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR > class GenericValue { … }; //! GenericValue with UTF8 encoding Value; /////////////////////////////////////////////////////////////////////////////// // GenericDocument //! A document for parsing JSON text as DOM. /*! \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 = RAPIDJSON_DEFAULT_ALLOCATOR, typename StackAllocator = RAPIDJSON_DEFAULT_STACK_ALLOCATOR > class GenericDocument : public GenericValue<Encoding, Allocator> { … }; //! GenericDocument with UTF8 encoding Document; //! 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 { … }; //! 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 { … }; RAPIDJSON_NAMESPACE_END RAPIDJSON_DIAG_POP #ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED #pragma pop_macro("GetObject") #undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED #endif #endif // RAPIDJSON_DOCUMENT_H_