mirror of
https://github.com/monero-project/monero.git
synced 2025-06-23 12:44:12 -04:00
no longer need to pass the size to rapidjson
This commit is contained in:
parent
bd8e0fd2a1
commit
32a26332f8
31 changed files with 3763 additions and 1143 deletions
531
external/rapidjson/document.h
vendored
531
external/rapidjson/document.h
vendored
|
@ -1,22 +1,16 @@
|
|||
// Copyright (C) 2011 Milo Yip
|
||||
// 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.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
// 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
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
// 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_
|
||||
|
@ -26,50 +20,41 @@
|
|||
#include "reader.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/strfunc.h"
|
||||
#include "memorystream.h"
|
||||
#include "encodedstream.h"
|
||||
#include <new> // placement new
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
#elif defined(__GNUC__)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_HAS_STDSTRING
|
||||
|
||||
#ifndef RAPIDJSON_HAS_STDSTRING
|
||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
|
||||
#else
|
||||
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
|
||||
#endif
|
||||
/*! \def RAPIDJSON_HAS_STDSTRING
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Enable RapidJSON support for \c std::string
|
||||
|
||||
By defining this preprocessor symbol to \c 1, several convenience functions for using
|
||||
\ref rapidjson::GenericValue with \c std::string are enabled, especially
|
||||
for construction and comparison.
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#include <string>
|
||||
#endif // RAPIDJSON_HAS_STDSTRING
|
||||
|
||||
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
|
||||
#include <iterator> // std::iterator, std::random_access_iterator_tag
|
||||
#endif
|
||||
|
||||
namespace rapidjson {
|
||||
#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.
|
||||
|
@ -258,6 +243,7 @@ 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
|
||||
|
@ -280,11 +266,13 @@ struct GenericStringRef {
|
|||
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.
|
||||
|
@ -303,16 +291,19 @@ struct GenericStringRef {
|
|||
In such cases, the referenced string should be \b copied to the
|
||||
GenericValue instead.
|
||||
*/
|
||||
#endif
|
||||
explicit GenericStringRef(const CharType* str)
|
||||
: s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
|
||||
|
||||
//! 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(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
|
||||
|
||||
|
@ -428,6 +419,7 @@ public:
|
|||
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.
|
||||
|
||||
//!@name Constructors and destructor.
|
||||
//@{
|
||||
|
@ -446,6 +438,16 @@ private:
|
|||
//! 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.
|
||||
|
@ -453,13 +455,17 @@ public:
|
|||
\param type Type of the value.
|
||||
\note Default content for number is zero.
|
||||
*/
|
||||
GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
|
||||
explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
|
||||
static const unsigned defaultFlags[7] = {
|
||||
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
|
||||
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
|
||||
kNumberAnyFlag
|
||||
};
|
||||
RAPIDJSON_ASSERT(type <= kNumberType);
|
||||
flags_ = defaultFlags[type];
|
||||
|
||||
// Use ShortString to store empty string.
|
||||
if (type == kStringType)
|
||||
data_.ss.SetLength(0);
|
||||
}
|
||||
|
||||
//! Explicit copy constructor (with allocator)
|
||||
|
@ -637,7 +643,7 @@ public:
|
|||
*/
|
||||
template <typename SourceAllocator>
|
||||
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
|
||||
RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
|
||||
RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
|
||||
this->~GenericValue();
|
||||
new (this) GenericValue(rhs, allocator);
|
||||
return *this;
|
||||
|
@ -656,6 +662,20 @@ public:
|
|||
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; }
|
||||
|
@ -697,12 +717,15 @@ public:
|
|||
return StringEqual(rhs);
|
||||
|
||||
case kNumberType:
|
||||
if (IsDouble() || rhs.IsDouble())
|
||||
return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
|
||||
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: // kTrueType, kFalseType, kNullType
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -797,22 +820,32 @@ public:
|
|||
//! Check whether the object is empty.
|
||||
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
|
||||
|
||||
//! Get the value associated with the name.
|
||||
/*!
|
||||
//! 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.
|
||||
*/
|
||||
GenericValue& operator[](const Ch* name) {
|
||||
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];
|
||||
}
|
||||
const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||
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]; }
|
||||
|
||||
// This version is faster because it does not need a StrLen().
|
||||
// It can also handle string with null character.
|
||||
//! 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);
|
||||
|
@ -820,13 +853,25 @@ public:
|
|||
return member->value;
|
||||
else {
|
||||
RAPIDJSON_ASSERT(false); // see above note
|
||||
static GenericValue NullValue;
|
||||
return NullValue;
|
||||
|
||||
// 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(data_.o.members); }
|
||||
|
@ -850,6 +895,18 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
@ -906,6 +963,18 @@ public:
|
|||
}
|
||||
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(StringRef(name)); }
|
||||
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(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.
|
||||
|
@ -938,6 +1007,60 @@ public:
|
|||
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);
|
||||
|
@ -1005,8 +1128,7 @@ public:
|
|||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
||||
AddMember(StringRefType name, T value, Allocator& allocator) {
|
||||
GenericValue n(name);
|
||||
GenericValue v(value);
|
||||
return AddMember(n, v, allocator);
|
||||
return AddMember(n, value, allocator);
|
||||
}
|
||||
|
||||
//! Remove all members in the object.
|
||||
|
@ -1023,7 +1145,9 @@ public:
|
|||
//! 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.
|
||||
\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) {
|
||||
|
@ -1031,6 +1155,10 @@ public:
|
|||
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);
|
||||
|
@ -1045,8 +1173,9 @@ public:
|
|||
//! Remove a member in object by iterator.
|
||||
/*! \param m member iterator (obtained by FindMember() or MemberBegin()).
|
||||
\return the new iterator after removal.
|
||||
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
||||
\note Use \ref EraseMember(ConstMemberIterator) instead, if you need to rely on a stable member ordering.
|
||||
\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) {
|
||||
|
@ -1073,7 +1202,8 @@ public:
|
|||
\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 Other than \ref RemoveMember(MemberIterator), this function preserves the ordering of the members.
|
||||
\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) {
|
||||
|
@ -1085,7 +1215,8 @@ public:
|
|||
\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 Other than \ref RemoveMember(MemberIterator), this function preserves the ordering of the members.
|
||||
\note This function preserves the relative order of the remaining object
|
||||
members.
|
||||
\note Linear time complexity.
|
||||
*/
|
||||
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
|
||||
|
@ -1099,11 +1230,36 @@ public:
|
|||
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
||||
for (MemberIterator itr = pos; itr != last; ++itr)
|
||||
itr->~Member();
|
||||
std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
|
||||
data_.o.size -= (last - first);
|
||||
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;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Array
|
||||
|
@ -1134,14 +1290,9 @@ public:
|
|||
}
|
||||
|
||||
//! Get an element from array by index.
|
||||
/*! \param index Zero-based index of element.
|
||||
\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
|
||||
/*! \pre IsArray() == true
|
||||
\param index Zero-based index of element.
|
||||
\see operator[](T*)
|
||||
*/
|
||||
GenericValue& operator[](SizeType index) {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
|
@ -1172,7 +1323,7 @@ int z = a[0u].GetInt(); // This works too.
|
|||
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.elements = static_cast<GenericValue*>(allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)));
|
||||
data_.a.capacity = newCapacity;
|
||||
}
|
||||
return *this;
|
||||
|
@ -1279,8 +1430,8 @@ int z = a[0u].GetInt(); // This works too.
|
|||
ValueIterator pos = Begin() + (first - Begin());
|
||||
for (ValueIterator itr = pos; itr != last; ++itr)
|
||||
itr->~GenericValue();
|
||||
std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
|
||||
data_.a.size -= (last - first);
|
||||
std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
||||
data_.a.size -= static_cast<SizeType>(last - first);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -1299,8 +1450,8 @@ int z = a[0u].GetInt(); // This works too.
|
|||
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)
|
||||
if ((flags_ & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
|
||||
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
|
||||
}
|
||||
|
||||
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
|
||||
|
@ -1364,7 +1515,7 @@ int z = a[0u].GetInt(); // This works too.
|
|||
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
|
||||
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
|
||||
*/
|
||||
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
|
||||
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
@ -1387,6 +1538,7 @@ int z = a[0u].GetInt(); // This works too.
|
|||
if (!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 (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
|
||||
return false;
|
||||
if (!m->value.Accept(handler))
|
||||
|
@ -1405,17 +1557,14 @@ int z = a[0u].GetInt(); // This works too.
|
|||
case kStringType:
|
||||
return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
|
||||
|
||||
case kNumberType:
|
||||
default:
|
||||
RAPIDJSON_ASSERT(GetType() == kNumberType);
|
||||
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 if (IsUint64()) return handler.Uint64(data_.n.u64);
|
||||
else return handler.Double(data_.n.d);
|
||||
|
||||
default:
|
||||
RAPIDJSON_ASSERT(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1474,9 +1623,9 @@ private:
|
|||
enum { MaxChars = sizeof(String) / 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] = (Ch)(MaxSize - len); }
|
||||
inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
|
||||
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.
|
||||
|
@ -1528,16 +1677,24 @@ private:
|
|||
// Initialize this value as array with initial data, without calling destructor.
|
||||
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
|
||||
flags_ = kArrayFlag;
|
||||
data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
|
||||
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
||||
if (count) {
|
||||
data_.a.elements = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
|
||||
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
||||
}
|
||||
else
|
||||
data_.a.elements = NULL;
|
||||
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) {
|
||||
flags_ = kObjectFlag;
|
||||
data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
|
||||
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
||||
if (count) {
|
||||
data_.o.members = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
||||
std::memcpy(data_.o.members, members, count * sizeof(Member));
|
||||
}
|
||||
else
|
||||
data_.o.members = NULL;
|
||||
data_.o.size = data_.o.capacity = count;
|
||||
}
|
||||
|
||||
|
@ -1558,7 +1715,7 @@ private:
|
|||
} else {
|
||||
flags_ = kCopyStringFlag;
|
||||
data_.s.length = s.length;
|
||||
str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
|
||||
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
|
||||
data_.s.str = str;
|
||||
}
|
||||
std::memcpy(str, s, s.length * sizeof(Ch));
|
||||
|
@ -1614,7 +1771,22 @@ public:
|
|||
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
|
||||
|
||||
//! Constructor
|
||||
/*! \param allocator Optional allocator for allocating memory.
|
||||
/*! 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.
|
||||
*/
|
||||
|
@ -1622,12 +1794,80 @@ public:
|
|||
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
|
||||
{
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = new Allocator();
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||
}
|
||||
|
||||
~GenericDocument() {
|
||||
delete ownAllocator_;
|
||||
#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;
|
||||
}
|
||||
|
||||
//! 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); }
|
||||
|
||||
//!@name Parse from stream
|
||||
//!@{
|
||||
|
@ -1641,13 +1881,13 @@ public:
|
|||
*/
|
||||
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
|
||||
GenericDocument& ParseStream(InputStream& is) {
|
||||
ValueType::SetNull(); // Remove existing root if exist
|
||||
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
|
||||
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
|
||||
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
|
||||
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -1660,7 +1900,7 @@ public:
|
|||
*/
|
||||
template <unsigned parseFlags, typename InputStream>
|
||||
GenericDocument& ParseStream(InputStream& is) {
|
||||
return ParseStream<parseFlags,Encoding,InputStream>(is);
|
||||
return ParseStream<parseFlags, Encoding, InputStream>(is);
|
||||
}
|
||||
|
||||
//! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
|
||||
|
@ -1677,18 +1917,6 @@ public:
|
|||
//!@name Parse in-place from mutable string
|
||||
//!@{
|
||||
|
||||
//! Parse JSON text from a mutable string (with Encoding conversion)
|
||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||
\tparam SourceEncoding Transcoding from input Encoding
|
||||
\param str Mutable zero-terminated string to be parsed.
|
||||
\return The document itself for fluent API.
|
||||
*/
|
||||
template <unsigned parseFlags, typename SourceEncoding>
|
||||
GenericDocument& ParseInsitu(Ch* str) {
|
||||
GenericInsituStringStream<Encoding> s(str);
|
||||
return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
|
||||
}
|
||||
|
||||
//! Parse JSON text from a mutable string
|
||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||
\param str Mutable zero-terminated string to be parsed.
|
||||
|
@ -1696,7 +1924,8 @@ public:
|
|||
*/
|
||||
template <unsigned parseFlags>
|
||||
GenericDocument& ParseInsitu(Ch* str) {
|
||||
return ParseInsitu<parseFlags, Encoding>(str);
|
||||
GenericInsituStringStream<Encoding> s(str);
|
||||
return ParseStream<parseFlags | kParseInsituFlag>(s);
|
||||
}
|
||||
|
||||
//! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
|
||||
|
@ -1704,7 +1933,7 @@ public:
|
|||
\return The document itself for fluent API.
|
||||
*/
|
||||
GenericDocument& ParseInsitu(Ch* str) {
|
||||
return ParseInsitu<kParseDefaultFlags, Encoding>(str);
|
||||
return ParseInsitu<kParseDefaultFlags>(str);
|
||||
}
|
||||
//!@}
|
||||
|
||||
|
@ -1717,7 +1946,7 @@ public:
|
|||
\param str Read-only zero-terminated string to be parsed.
|
||||
*/
|
||||
template <unsigned parseFlags, typename SourceEncoding>
|
||||
GenericDocument& Parse(const Ch* str) {
|
||||
GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
|
||||
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
|
||||
GenericStringStream<SourceEncoding> s(str);
|
||||
return ParseStream<parseFlags, SourceEncoding>(s);
|
||||
|
@ -1738,16 +1967,6 @@ public:
|
|||
GenericDocument& Parse(const Ch* str) {
|
||||
return Parse<kParseDefaultFlags>(str);
|
||||
}
|
||||
|
||||
GenericDocument& Parse(const Ch * str, size_t sz) {
|
||||
const char* buf = (const char*) str;
|
||||
size_t bufsz = sz * sizeof(Ch);
|
||||
MemoryStream ms(buf, bufsz);
|
||||
EncodedInputStream<Encoding, MemoryStream> is(ms);
|
||||
ParseStream(is);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!@}
|
||||
|
||||
//!@name Handling parse errors
|
||||
|
@ -1762,10 +1981,26 @@ public:
|
|||
//! 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() { return *allocator_; }
|
||||
Allocator& GetAllocator() {
|
||||
RAPIDJSON_ASSERT(allocator_);
|
||||
return *allocator_;
|
||||
}
|
||||
|
||||
//! Get the capacity of stack in bytes.
|
||||
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
|
||||
|
@ -1808,7 +2043,7 @@ private:
|
|||
|
||||
bool EndObject(SizeType memberCount) {
|
||||
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
|
||||
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
|
||||
stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1821,6 +2056,8 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
//! Prohibit copying
|
||||
GenericDocument(const GenericDocument&);
|
||||
//! Prohibit assignment
|
||||
GenericDocument& operator=(const GenericDocument&);
|
||||
|
||||
|
@ -1833,6 +2070,10 @@ private:
|
|||
stack_.ShrinkToFit();
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
static const size_t kDefaultStackCapacity = 1024;
|
||||
Allocator* allocator_;
|
||||
Allocator* ownAllocator_;
|
||||
|
@ -1849,14 +2090,40 @@ template <typename SourceAllocator>
|
|||
inline
|
||||
GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
|
||||
{
|
||||
GenericDocument<Encoding,Allocator> d(&allocator);
|
||||
rhs.Accept(d);
|
||||
RawAssign(*d.stack_.template Pop<GenericValue>(1));
|
||||
switch (rhs.GetType()) {
|
||||
case kObjectType:
|
||||
case kArrayType: { // perform deep copy via SAX Handler
|
||||
GenericDocument<Encoding,Allocator> d(&allocator);
|
||||
rhs.Accept(d);
|
||||
RawAssign(*d.stack_.template Pop<GenericValue>(1));
|
||||
}
|
||||
break;
|
||||
case kStringType:
|
||||
if (rhs.flags_ == kConstStringFlag) {
|
||||
flags_ = rhs.flags_;
|
||||
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
|
||||
} else {
|
||||
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
flags_ = rhs.flags_;
|
||||
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rapidjson
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(_MSC_VER) || defined(__GNUC__)
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue