Add GenericArray helper class with range-based for
This commit is contained in:
parent
c6946fd2c1
commit
59309b5dd2
@ -483,6 +483,9 @@ struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
template <typename ValueType>
|
||||||
|
class GenericArray;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GenericValue
|
// GenericValue
|
||||||
|
|
||||||
@ -510,6 +513,7 @@ public:
|
|||||||
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
||||||
typedef const GenericValue* ConstValueIterator; //!< Constant 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 GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
|
||||||
|
typedef GenericArray<ValueType> ArrayType;
|
||||||
|
|
||||||
//!@name Constructors and destructor.
|
//!@name Constructors and destructor.
|
||||||
//@{
|
//@{
|
||||||
@ -1556,6 +1560,9 @@ public:
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayType GetArray() { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); }
|
||||||
|
const ArrayType GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
//!@name Number
|
//!@name Number
|
||||||
@ -1653,9 +1660,12 @@ public:
|
|||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
//!@name Array
|
||||||
|
//@{
|
||||||
|
|
||||||
//! Templated version for checking whether this value is type T.
|
//! 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 std::basic_string<Ch>
|
\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>
|
template <typename T>
|
||||||
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
|
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
|
||||||
@ -1669,6 +1679,8 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
|
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
//! Generate events of this value to a Handler.
|
//! Generate events of this value to a Handler.
|
||||||
/*! This function adopts the GoF visitor pattern.
|
/*! This function adopts the GoF visitor pattern.
|
||||||
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
|
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
|
||||||
@ -2278,6 +2290,65 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! 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 <typename ValueType>
|
||||||
|
class GenericArray {
|
||||||
|
public:
|
||||||
|
typedef typename ValueType::ValueIterator ValueIterator;
|
||||||
|
typedef typename ValueType::ConstValueIterator ConstValueIterator;
|
||||||
|
typedef typename ValueType::AllocatorType AllocatorType;
|
||||||
|
typedef typename ValueType::StringRefType StringRefType;
|
||||||
|
|
||||||
|
template <typename, typename>
|
||||||
|
friend class GenericValue;
|
||||||
|
|
||||||
|
GenericArray() : ptr_() {}
|
||||||
|
GenericArray(const GenericArray& rhs) : ptr_(rhs.ptr_) {}
|
||||||
|
GenericArray& operator=(GenericArray& rhs) { ptr_ = rhs.ptr_; return *this; }
|
||||||
|
~GenericArray() {}
|
||||||
|
|
||||||
|
SizeType Size() const { return ptr_->Size(); }
|
||||||
|
SizeType Capacity() const { return ptr_->Capacity(); }
|
||||||
|
bool Empty() const { return ptr_->Empty(); }
|
||||||
|
void Clear() { ptr_->Clear(); }
|
||||||
|
ValueType& operator[](SizeType index) { return (*ptr_)[index]; }
|
||||||
|
const ValueType& operator[](SizeType index) const { return (*ptr_)[index]; }
|
||||||
|
ValueIterator Begin() { return ptr_->Begin(); }
|
||||||
|
ValueIterator End() { return ptr_->End(); }
|
||||||
|
ConstValueIterator Begin() const { return ptr_->Begin(); }
|
||||||
|
ConstValueIterator End() const { return ptr_->End(); }
|
||||||
|
GenericArray& Reserve(SizeType newCapacity, AllocatorType &allocator) { ptr_->Reserve(newCapacity, allocator); return *this; }
|
||||||
|
GenericArray& PushBack(ValueType& value, AllocatorType& allocator) { ptr_->PushBack(value, allocator); return *this; }
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
GenericArray& PushBack(ValueType&& value, AllocatorType& allocator) { ptr_->PushBack(value, allocator); return *this; }
|
||||||
|
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
GenericArray& PushBack(StringRefType value, AllocatorType& allocator) { ptr_->PushBack(value, allocator); return *this; }
|
||||||
|
template <typename T>
|
||||||
|
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericArray&))
|
||||||
|
PushBack(T value, AllocatorType& allocator) { ptr_->PushBack(value, allocator); return *this; }
|
||||||
|
GenericArray& PopBack() { ptr_->PopBack(); return *this; }
|
||||||
|
ValueIterator Erase(ConstValueIterator pos) { return ptr_->Erase(pos); }
|
||||||
|
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { return ptr_->Erase(first, last); }
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
ValueIterator begin() { return ptr_->Begin(); }
|
||||||
|
ValueIterator end() { return ptr_->End(); }
|
||||||
|
ConstValueIterator begin() const { return ptr_->Begin(); }
|
||||||
|
ConstValueIterator end() const { return ptr_->End(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
GenericArray(ValueType& value) : ptr_(&value) {}
|
||||||
|
GenericArray(const ValueType& value) : ptr_(const_cast<ValueType*>(&value)) {}
|
||||||
|
ValueType* ptr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef GenericArray<Value> Array;
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -530,6 +530,17 @@ RAPIDJSON_NAMESPACE_END
|
|||||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
|
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
#if defined(__clang)
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||||
|
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||||
|
(defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||||
|
#endif
|
||||||
|
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -824,25 +824,9 @@ TEST(Value, SetStringNullException) {
|
|||||||
EXPECT_THROW(v.SetString(0, 0), AssertException);
|
EXPECT_THROW(v.SetString(0, 0), AssertException);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Value, Array) {
|
template <typename T, typename Allocator>
|
||||||
Value x(kArrayType);
|
void TestArray(T& x, Allocator& allocator) {
|
||||||
const Value& y = x;
|
const T& y = x;
|
||||||
Value::AllocatorType allocator;
|
|
||||||
|
|
||||||
EXPECT_EQ(kArrayType, x.GetType());
|
|
||||||
EXPECT_TRUE(x.IsArray());
|
|
||||||
EXPECT_TRUE(x.Empty());
|
|
||||||
EXPECT_EQ(0u, x.Size());
|
|
||||||
EXPECT_TRUE(y.IsArray());
|
|
||||||
EXPECT_TRUE(y.Empty());
|
|
||||||
EXPECT_EQ(0u, y.Size());
|
|
||||||
|
|
||||||
EXPECT_FALSE(x.IsNull());
|
|
||||||
EXPECT_FALSE(x.IsBool());
|
|
||||||
EXPECT_FALSE(x.IsFalse());
|
|
||||||
EXPECT_FALSE(x.IsTrue());
|
|
||||||
EXPECT_FALSE(x.IsString());
|
|
||||||
EXPECT_FALSE(x.IsObject());
|
|
||||||
|
|
||||||
// PushBack()
|
// PushBack()
|
||||||
Value v;
|
Value v;
|
||||||
@ -889,7 +873,7 @@ TEST(Value, Array) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// iterator
|
// iterator
|
||||||
Value::ValueIterator itr = x.Begin();
|
typename T::ValueIterator itr = x.Begin();
|
||||||
EXPECT_TRUE(itr != x.End());
|
EXPECT_TRUE(itr != x.End());
|
||||||
EXPECT_TRUE(itr->IsNull());
|
EXPECT_TRUE(itr->IsNull());
|
||||||
++itr;
|
++itr;
|
||||||
@ -908,7 +892,7 @@ TEST(Value, Array) {
|
|||||||
EXPECT_STREQ("foo", itr->GetString());
|
EXPECT_STREQ("foo", itr->GetString());
|
||||||
|
|
||||||
// const iterator
|
// const iterator
|
||||||
Value::ConstValueIterator citr = y.Begin();
|
typename T::ConstValueIterator citr = y.Begin();
|
||||||
EXPECT_TRUE(citr != y.End());
|
EXPECT_TRUE(citr != y.End());
|
||||||
EXPECT_TRUE(citr->IsNull());
|
EXPECT_TRUE(citr->IsNull());
|
||||||
++citr;
|
++citr;
|
||||||
@ -994,6 +978,29 @@ TEST(Value, Array) {
|
|||||||
EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUint());
|
EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Value, Array) {
|
||||||
|
Value x(kArrayType);
|
||||||
|
const Value& y = x;
|
||||||
|
Value::AllocatorType allocator;
|
||||||
|
|
||||||
|
EXPECT_EQ(kArrayType, x.GetType());
|
||||||
|
EXPECT_TRUE(x.IsArray());
|
||||||
|
EXPECT_TRUE(x.Empty());
|
||||||
|
EXPECT_EQ(0u, x.Size());
|
||||||
|
EXPECT_TRUE(y.IsArray());
|
||||||
|
EXPECT_TRUE(y.Empty());
|
||||||
|
EXPECT_EQ(0u, y.Size());
|
||||||
|
|
||||||
|
EXPECT_FALSE(x.IsNull());
|
||||||
|
EXPECT_FALSE(x.IsBool());
|
||||||
|
EXPECT_FALSE(x.IsFalse());
|
||||||
|
EXPECT_FALSE(x.IsTrue());
|
||||||
|
EXPECT_FALSE(x.IsString());
|
||||||
|
EXPECT_FALSE(x.IsObject());
|
||||||
|
|
||||||
|
TestArray(x, allocator);
|
||||||
|
|
||||||
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
|
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
|
||||||
// http://en.wikipedia.org/wiki/Erase-remove_idiom
|
// http://en.wikipedia.org/wiki/Erase-remove_idiom
|
||||||
@ -1017,6 +1024,52 @@ TEST(Value, Array) {
|
|||||||
EXPECT_TRUE(z.Empty());
|
EXPECT_TRUE(z.Empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Value, ArrayHelper) {
|
||||||
|
Value::AllocatorType allocator;
|
||||||
|
{
|
||||||
|
Value x(kArrayType);
|
||||||
|
Array a = x.GetArray();
|
||||||
|
TestArray(a, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value x(kArrayType);
|
||||||
|
Array a = x.GetArray();
|
||||||
|
a.PushBack(1, allocator);
|
||||||
|
|
||||||
|
Array a2(a); // copy constructor
|
||||||
|
EXPECT_EQ(1, a2.Size());
|
||||||
|
|
||||||
|
Array a3; // default constructor
|
||||||
|
a3 = a; // assignment operator
|
||||||
|
EXPECT_EQ(1, a3.Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
TEST(Value, ArrayHelperRangeFor) {
|
||||||
|
Value::AllocatorType allocator;
|
||||||
|
Value x(kArrayType);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
x.PushBack(i, allocator);
|
||||||
|
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto& v : x.GetArray())
|
||||||
|
EXPECT_EQ(i++, v.GetInt());
|
||||||
|
EXPECT_EQ(i, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto& v : const_cast<const Value&>(x).GetArray())
|
||||||
|
EXPECT_EQ(i++, v.GetInt());
|
||||||
|
EXPECT_EQ(i, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array a = x.GetArray();
|
||||||
|
// Array ca = const_cast<const Value&>(x).GetArray();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST(Value, Object) {
|
TEST(Value, Object) {
|
||||||
Value x(kObjectType);
|
Value x(kObjectType);
|
||||||
const Value& y = x; // const version
|
const Value& y = x; // const version
|
||||||
|
Loading…
x
Reference in New Issue
Block a user