Merge pull request #127 from pah/feature/value-different-allocators
GenericValue: accept values with different allocators for read-only access
This commit is contained in:
commit
15d70d6a7b
@ -382,6 +382,22 @@ inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& s
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GenericValue
|
// GenericValue
|
||||||
|
|
||||||
@ -444,7 +460,7 @@ public:
|
|||||||
\see CopyFrom()
|
\see CopyFrom()
|
||||||
*/
|
*/
|
||||||
template< typename SourceAllocator >
|
template< typename SourceAllocator >
|
||||||
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator & allocator);
|
GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
|
||||||
|
|
||||||
//! Constructor for boolean value.
|
//! Constructor for boolean value.
|
||||||
/*! \param b Boolean value
|
/*! \param b Boolean value
|
||||||
@ -603,10 +619,10 @@ public:
|
|||||||
\param allocator Allocator to use for copying
|
\param allocator Allocator to use for copying
|
||||||
*/
|
*/
|
||||||
template <typename SourceAllocator>
|
template <typename SourceAllocator>
|
||||||
GenericValue& CopyFrom(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator) {
|
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
|
||||||
RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
|
RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
|
||||||
this->~GenericValue();
|
this->~GenericValue();
|
||||||
new (this) GenericValue(rhs,allocator);
|
new (this) GenericValue(rhs, allocator);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,7 +651,9 @@ public:
|
|||||||
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
|
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
|
||||||
\note Linear time complexity (number of all values in the subtree and total lengths of all strings).
|
\note Linear time complexity (number of all values in the subtree and total lengths of all strings).
|
||||||
*/
|
*/
|
||||||
bool operator==(const GenericValue& rhs) const {
|
template <typename SourceAllocator>
|
||||||
|
bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
|
||||||
|
typedef GenericValue<Encoding, SourceAllocator> RhsType;
|
||||||
if (GetType() != rhs.GetType())
|
if (GetType() != rhs.GetType())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -644,7 +662,7 @@ public:
|
|||||||
if (data_.o.size != rhs.data_.o.size)
|
if (data_.o.size != rhs.data_.o.size)
|
||||||
return false;
|
return false;
|
||||||
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
|
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
|
||||||
ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
|
typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
|
||||||
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
|
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -685,27 +703,31 @@ public:
|
|||||||
//! Equal-to operator with primitive types
|
//! 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
|
/*! \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::IsBaseOf<GenericValue,T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
|
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
|
//! Not-equal-to operator
|
||||||
/*! \return !(*this == rhs)
|
/*! \return !(*this == rhs)
|
||||||
*/
|
*/
|
||||||
bool operator!=(const GenericValue& rhs) const { 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
|
//! Not-equal-to operator with arbitrary types
|
||||||
/*! \return !(*this == rhs)
|
/*! \return !(*this == rhs)
|
||||||
*/
|
*/
|
||||||
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsBaseOf<GenericValue,T>), (bool)) operator!=(const T& rhs) const { 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)
|
//! Equal-to operator with arbitrary types (symmetric version)
|
||||||
/*! \return (rhs == lhs)
|
/*! \return (rhs == lhs)
|
||||||
*/
|
*/
|
||||||
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsBaseOf<GenericValue,T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { 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)
|
//! Not-Equal-to operator with arbitrary types (symmetric version)
|
||||||
/*! \return !(rhs == lhs)
|
/*! \return !(rhs == lhs)
|
||||||
*/
|
*/
|
||||||
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsBaseOf<GenericValue,T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { 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
|
//!@name Type
|
||||||
@ -774,7 +796,8 @@ public:
|
|||||||
|
|
||||||
// This version is faster because it does not need a StrLen().
|
// This version is faster because it does not need a StrLen().
|
||||||
// It can also handle string with null character.
|
// It can also handle string with null character.
|
||||||
GenericValue& operator[](const GenericValue& name) {
|
template <typename SourceAllocator>
|
||||||
|
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
MemberIterator member = FindMember(name);
|
MemberIterator member = FindMember(name);
|
||||||
if (member != MemberEnd())
|
if (member != MemberEnd())
|
||||||
return member->value;
|
return member->value;
|
||||||
@ -784,7 +807,8 @@ public:
|
|||||||
return NullValue;
|
return NullValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const GenericValue& operator[](const GenericValue& name) const { return const_cast<GenericValue&>(*this)[name]; }
|
template <typename SourceAllocator>
|
||||||
|
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||||
|
|
||||||
//! Const member iterator
|
//! Const member iterator
|
||||||
/*! \pre IsObject() == true */
|
/*! \pre IsObject() == true */
|
||||||
@ -818,7 +842,8 @@ public:
|
|||||||
\note It is better to use FindMember() directly if you need the obtain the value as well.
|
\note It is better to use FindMember() directly if you need the obtain the value as well.
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); }
|
template <typename SourceAllocator>
|
||||||
|
bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
|
||||||
|
|
||||||
//! Find member by name.
|
//! Find member by name.
|
||||||
/*!
|
/*!
|
||||||
@ -852,7 +877,8 @@ public:
|
|||||||
\c std::map, this has been changed to MemberEnd() now.
|
\c std::map, this has been changed to MemberEnd() now.
|
||||||
\note Linear time complexity.
|
\note Linear time complexity.
|
||||||
*/
|
*/
|
||||||
MemberIterator FindMember(const GenericValue& name) {
|
template <typename SourceAllocator>
|
||||||
|
MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
RAPIDJSON_ASSERT(IsObject());
|
RAPIDJSON_ASSERT(IsObject());
|
||||||
RAPIDJSON_ASSERT(name.IsString());
|
RAPIDJSON_ASSERT(name.IsString());
|
||||||
MemberIterator member = MemberBegin();
|
MemberIterator member = MemberBegin();
|
||||||
@ -861,7 +887,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
||||||
|
|
||||||
//! Add a member (name-value pair) to the object.
|
//! Add a member (name-value pair) to the object.
|
||||||
/*! \param name A string value as name of member.
|
/*! \param name A string value as name of member.
|
||||||
@ -942,7 +968,7 @@ public:
|
|||||||
\note Amortized Constant time complexity.
|
\note Amortized Constant time complexity.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
||||||
AddMember(StringRefType name, T value, Allocator& allocator) {
|
AddMember(StringRefType name, T value, Allocator& allocator) {
|
||||||
GenericValue n(name);
|
GenericValue n(name);
|
||||||
GenericValue v(value);
|
GenericValue v(value);
|
||||||
@ -971,7 +997,8 @@ public:
|
|||||||
return RemoveMember(n);
|
return RemoveMember(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveMember(const GenericValue& name) {
|
template <typename SourceAllocator>
|
||||||
|
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||||
MemberIterator m = FindMember(name);
|
MemberIterator m = FindMember(name);
|
||||||
if (m != MemberEnd()) {
|
if (m != MemberEnd()) {
|
||||||
RemoveMember(m);
|
RemoveMember(m);
|
||||||
@ -1166,7 +1193,7 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
\note Amortized constant time complexity.
|
\note Amortized constant time complexity.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
|
||||||
PushBack(T value, Allocator& allocator) {
|
PushBack(T value, Allocator& allocator) {
|
||||||
GenericValue v(value);
|
GenericValue v(value);
|
||||||
return PushBack(v, allocator);
|
return PushBack(v, allocator);
|
||||||
@ -1352,8 +1379,8 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename, typename, typename>
|
template <typename, typename> friend class GenericValue;
|
||||||
friend class GenericDocument;
|
template <typename, typename, typename> friend class GenericDocument;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kBoolFlag = 0x100,
|
kBoolFlag = 0x100,
|
||||||
@ -1505,7 +1532,8 @@ private:
|
|||||||
rhs.flags_ = kNullFlag;
|
rhs.flags_ = kNullFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringEqual(const GenericValue& rhs) const {
|
template <typename SourceAllocator>
|
||||||
|
bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
|
||||||
RAPIDJSON_ASSERT(IsString());
|
RAPIDJSON_ASSERT(IsString());
|
||||||
RAPIDJSON_ASSERT(rhs.IsString());
|
RAPIDJSON_ASSERT(rhs.IsString());
|
||||||
|
|
||||||
@ -1706,7 +1734,7 @@ private:
|
|||||||
|
|
||||||
// callers of the following private Handler functions
|
// callers of the following private Handler functions
|
||||||
template <typename,typename,typename> friend class GenericReader; // for parsing
|
template <typename,typename,typename> friend class GenericReader; // for parsing
|
||||||
friend class GenericValue<Encoding,Allocator>; // for deep copying
|
template <typename, typename> friend class GenericValue; // for deep copying
|
||||||
|
|
||||||
// Implementation of Handler
|
// Implementation of Handler
|
||||||
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
|
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
|
||||||
|
@ -38,6 +38,8 @@ RAPIDJSON_DIAG_OFF(6334)
|
|||||||
namespace rapidjson {
|
namespace rapidjson {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||||
|
template <typename T> struct Void { typedef void Type; };
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// BoolType, TrueType, FalseType
|
// BoolType, TrueType, FalseType
|
||||||
|
@ -89,15 +89,9 @@ inline FILE* TempFile(char *filename) {
|
|||||||
#pragma warning(disable : 4127)
|
#pragma warning(disable : 4127)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class AssertException : public std::exception {
|
class AssertException : public std::logic_error {
|
||||||
public:
|
public:
|
||||||
AssertException(const char* w) : what_(w) {}
|
AssertException(const char* w) : std::logic_error(w) {}
|
||||||
AssertException(const AssertException& other) : what_(other.what_) {}
|
|
||||||
AssertException& operator=(const AssertException& rhs) { what_ = rhs.what_; return *this; }
|
|
||||||
virtual const char* what() const throw() { return what_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char* what_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x))
|
#define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x))
|
||||||
|
@ -105,20 +105,12 @@ TEST(Value, equalto_operator) {
|
|||||||
TestEqual(x["i"], 123);
|
TestEqual(x["i"], 123);
|
||||||
TestEqual(x["pi"], 3.14);
|
TestEqual(x["pi"], 3.14);
|
||||||
|
|
||||||
// Test operator==()
|
// Test operator==() (including different allocators)
|
||||||
#ifdef RAPIDJSON_COMPARE_DIFFERENT_ALLOCATORS
|
|
||||||
CrtAllocator crtAllocator;
|
CrtAllocator crtAllocator;
|
||||||
GenericValue<UTF8<>, CrtAllocator> y;
|
GenericValue<UTF8<>, CrtAllocator> y;
|
||||||
GenericDocument<UTF8<>, CrtAllocator> z(&crtAllocator);
|
GenericDocument<UTF8<>, CrtAllocator> z(&crtAllocator);
|
||||||
CrtAllocator& yAllocator = crtAllocator;
|
y.CopyFrom(x, crtAllocator);
|
||||||
#else
|
|
||||||
Value::AllocatorType& yAllocator = allocator;
|
|
||||||
Value y;
|
|
||||||
Document z;
|
|
||||||
#endif // RAPIDJSON_COMPARE_DIFFERENT_ALLOCATORS
|
|
||||||
y.CopyFrom(x, yAllocator);
|
|
||||||
z.CopyFrom(y, z.GetAllocator());
|
z.CopyFrom(y, z.GetAllocator());
|
||||||
|
|
||||||
TestEqual(x, y);
|
TestEqual(x, y);
|
||||||
TestEqual(y, z);
|
TestEqual(y, z);
|
||||||
TestEqual(z, x);
|
TestEqual(z, x);
|
||||||
@ -130,7 +122,7 @@ TEST(Value, equalto_operator) {
|
|||||||
EXPECT_TRUE(z.RemoveMember("t"));
|
EXPECT_TRUE(z.RemoveMember("t"));
|
||||||
TestUnequal(x, z);
|
TestUnequal(x, z);
|
||||||
TestEqual(y, z);
|
TestEqual(y, z);
|
||||||
y.AddMember("t", true, yAllocator);
|
y.AddMember("t", true, crtAllocator);
|
||||||
z.AddMember("t", true, z.GetAllocator());
|
z.AddMember("t", true, z.GetAllocator());
|
||||||
TestEqual(x, y);
|
TestEqual(x, y);
|
||||||
TestEqual(y, z);
|
TestEqual(y, z);
|
||||||
@ -843,10 +835,18 @@ TEST(Value, Object) {
|
|||||||
EXPECT_TRUE(x.HasMember(name));
|
EXPECT_TRUE(x.HasMember(name));
|
||||||
EXPECT_TRUE(y.HasMember(name));
|
EXPECT_TRUE(y.HasMember(name));
|
||||||
|
|
||||||
|
GenericValue<UTF8<>, CrtAllocator> othername("A");
|
||||||
|
EXPECT_TRUE(x.HasMember(othername));
|
||||||
|
EXPECT_TRUE(y.HasMember(othername));
|
||||||
|
othername.SetString("C\0D");
|
||||||
|
EXPECT_TRUE(x.HasMember(othername));
|
||||||
|
EXPECT_TRUE(y.HasMember(othername));
|
||||||
|
|
||||||
// operator[]
|
// operator[]
|
||||||
EXPECT_STREQ("Apple", x["A"].GetString());
|
EXPECT_STREQ("Apple", x["A"].GetString());
|
||||||
EXPECT_STREQ("Banana", x["B"].GetString());
|
EXPECT_STREQ("Banana", x["B"].GetString());
|
||||||
EXPECT_STREQ("CherryD", x[C0D].GetString());
|
EXPECT_STREQ("CherryD", x[C0D].GetString());
|
||||||
|
EXPECT_STREQ("CherryD", x[othername].GetString());
|
||||||
|
|
||||||
// const operator[]
|
// const operator[]
|
||||||
EXPECT_STREQ("Apple", y["A"].GetString());
|
EXPECT_STREQ("Apple", y["A"].GetString());
|
||||||
@ -917,7 +917,7 @@ TEST(Value, Object) {
|
|||||||
x.RemoveMember("B");
|
x.RemoveMember("B");
|
||||||
EXPECT_FALSE(x.HasMember("B"));
|
EXPECT_FALSE(x.HasMember("B"));
|
||||||
|
|
||||||
x.RemoveMember(name);
|
x.RemoveMember(othername);
|
||||||
EXPECT_FALSE(x.HasMember(name));
|
EXPECT_FALSE(x.HasMember(name));
|
||||||
|
|
||||||
EXPECT_TRUE(x.MemberBegin() == x.MemberEnd());
|
EXPECT_TRUE(x.MemberBegin() == x.MemberEnd());
|
||||||
@ -930,11 +930,14 @@ TEST(Value, Object) {
|
|||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator);
|
x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator);
|
||||||
|
|
||||||
|
// MemberCount, iterator difference
|
||||||
|
EXPECT_EQ(x.MemberCount(), SizeType(x.MemberEnd() - x.MemberBegin()));
|
||||||
|
|
||||||
// Erase the first
|
// Erase the first
|
||||||
itr = x.EraseMember(x.MemberBegin());
|
itr = x.EraseMember(x.MemberBegin());
|
||||||
EXPECT_FALSE(x.HasMember(keys[0]));
|
EXPECT_FALSE(x.HasMember(keys[0]));
|
||||||
EXPECT_EQ(x.MemberBegin(), itr);
|
EXPECT_EQ(x.MemberBegin(), itr);
|
||||||
EXPECT_EQ(9, x.MemberEnd() - x.MemberBegin());
|
EXPECT_EQ(9u, x.MemberCount());
|
||||||
for (; itr != x.MemberEnd(); ++itr) {
|
for (; itr != x.MemberEnd(); ++itr) {
|
||||||
int i = (itr - x.MemberBegin()) + 1;
|
int i = (itr - x.MemberBegin()) + 1;
|
||||||
EXPECT_STREQ(itr->name.GetString(), keys[i]);
|
EXPECT_STREQ(itr->name.GetString(), keys[i]);
|
||||||
@ -945,7 +948,7 @@ TEST(Value, Object) {
|
|||||||
itr = x.EraseMember(x.MemberEnd() - 1);
|
itr = x.EraseMember(x.MemberEnd() - 1);
|
||||||
EXPECT_FALSE(x.HasMember(keys[9]));
|
EXPECT_FALSE(x.HasMember(keys[9]));
|
||||||
EXPECT_EQ(x.MemberEnd(), itr);
|
EXPECT_EQ(x.MemberEnd(), itr);
|
||||||
EXPECT_EQ(8, x.MemberEnd() - x.MemberBegin());
|
EXPECT_EQ(8u, x.MemberCount());
|
||||||
for (; itr != x.MemberEnd(); ++itr) {
|
for (; itr != x.MemberEnd(); ++itr) {
|
||||||
int i = (itr - x.MemberBegin()) + 1;
|
int i = (itr - x.MemberBegin()) + 1;
|
||||||
EXPECT_STREQ(itr->name.GetString(), keys[i]);
|
EXPECT_STREQ(itr->name.GetString(), keys[i]);
|
||||||
@ -956,7 +959,7 @@ TEST(Value, Object) {
|
|||||||
itr = x.EraseMember(x.MemberBegin() + 4);
|
itr = x.EraseMember(x.MemberBegin() + 4);
|
||||||
EXPECT_FALSE(x.HasMember(keys[5]));
|
EXPECT_FALSE(x.HasMember(keys[5]));
|
||||||
EXPECT_EQ(x.MemberBegin() + 4, itr);
|
EXPECT_EQ(x.MemberBegin() + 4, itr);
|
||||||
EXPECT_EQ(7, x.MemberEnd() - x.MemberBegin());
|
EXPECT_EQ(7u, x.MemberCount());
|
||||||
for (; itr != x.MemberEnd(); ++itr) {
|
for (; itr != x.MemberEnd(); ++itr) {
|
||||||
int i = (itr - x.MemberBegin());
|
int i = (itr - x.MemberBegin());
|
||||||
i += (i<4) ? 1 : 2;
|
i += (i<4) ? 1 : 2;
|
||||||
@ -980,7 +983,7 @@ TEST(Value, Object) {
|
|||||||
EXPECT_EQ(x.MemberBegin() + first, itr);
|
EXPECT_EQ(x.MemberBegin() + first, itr);
|
||||||
|
|
||||||
size_t removeCount = last - first;
|
size_t removeCount = last - first;
|
||||||
EXPECT_EQ(n - removeCount, size_t(x.MemberEnd() - x.MemberBegin()));
|
EXPECT_EQ(n - removeCount, x.MemberCount());
|
||||||
for (unsigned i = 0; i < first; i++)
|
for (unsigned i = 0; i < first; i++)
|
||||||
EXPECT_EQ(i, x[keys[i]][0u].GetUint());
|
EXPECT_EQ(i, x[keys[i]][0u].GetUint());
|
||||||
for (unsigned i = first; i < n - removeCount; i++)
|
for (unsigned i = first; i < n - removeCount; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user