Commit 0b098eb3 authored by Milo Yip's avatar Milo Yip

Rectify constness of Array

parent 59309b5d
...@@ -481,9 +481,25 @@ struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { ...@@ -481,9 +481,25 @@ struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
}; };
#endif #endif
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Array> {
typedef typename ValueType::Array ArratType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArratType Get(ValueType& v) { return v.GetArray(); }
static ValueType& Set(ValueType& v, ArratType data) { return v.SetArray(data); }
static ValueType& Set(ValueType& v, ArratType data, typename ValueType::AllocatorType&) { return v.SetArray(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
typedef typename ValueType::ConstArray ArratType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArratType Get(const ValueType& v) { return v.GetArray(); }
};
} // namespace internal } // namespace internal
template <typename ValueType> template <bool, typename>
class GenericArray; class GenericArray;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -513,7 +529,8 @@ public: ...@@ -513,7 +529,8 @@ 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; typedef GenericArray<false, ValueType> Array;
typedef GenericArray<true, ValueType> ConstArray;
//!@name Constructors and destructor. //!@name Constructors and destructor.
//@{ //@{
...@@ -1114,7 +1131,7 @@ public: ...@@ -1114,7 +1131,7 @@ public:
RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString()); RAPIDJSON_ASSERT(name.IsString());
Object& o = data_.o; ObjectData& o = data_.o;
if (o.size >= o.capacity) { if (o.size >= o.capacity) {
if (o.capacity == 0) { if (o.capacity == 0) {
o.capacity = kDefaultObjectCapacity; o.capacity = kDefaultObjectCapacity;
...@@ -1394,6 +1411,9 @@ public: ...@@ -1394,6 +1411,9 @@ public:
/*! \post IsArray == true */ /*! \post IsArray == true */
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
//! Set this value with an array.
GenericValue& SetArray(Array& a) { return *this = *a.ptr_; }
//! Get the number of elements in array. //! Get the number of elements in array.
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
...@@ -1560,8 +1580,8 @@ public: ...@@ -1560,8 +1580,8 @@ public:
return pos; return pos;
} }
ArrayType GetArray() { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); } Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
const ArrayType GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); } ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
//@} //@}
...@@ -1673,6 +1693,9 @@ public: ...@@ -1673,6 +1693,9 @@ public:
template <typename T> template <typename T>
T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } 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> template<typename T>
ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
...@@ -1815,13 +1838,13 @@ private: ...@@ -1815,13 +1838,13 @@ private:
double d; double d;
}; // 8 bytes }; // 8 bytes
struct Object { struct ObjectData {
Member* members; Member* members;
SizeType size; SizeType size;
SizeType capacity; SizeType capacity;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct Array { struct ArrayData {
GenericValue* elements; GenericValue* elements;
SizeType size; SizeType size;
SizeType capacity; SizeType capacity;
...@@ -1831,8 +1854,8 @@ private: ...@@ -1831,8 +1854,8 @@ private:
String s; String s;
ShortString ss; ShortString ss;
Number n; Number n;
Object o; ObjectData o;
Array a; ArrayData a;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// Initialize this value as array with initial data, without calling destructor. // Initialize this value as array with initial data, without calling destructor.
...@@ -2295,9 +2318,13 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc ...@@ -2295,9 +2318,13 @@ GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,Sourc
Instance of this helper class is obtained by \c GenericValue::GetArray(). 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. 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> template <bool Const, typename ValueT>
class GenericArray { class GenericArray {
public: public:
typedef GenericArray<true, ValueT> ConstArray;
typedef GenericArray<false, ValueT> Array;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef typename ValueType::ValueIterator ValueIterator; typedef typename ValueType::ValueIterator ValueIterator;
typedef typename ValueType::ConstValueIterator ConstValueIterator; typedef typename ValueType::ConstValueIterator ConstValueIterator;
typedef typename ValueType::AllocatorType AllocatorType; typedef typename ValueType::AllocatorType AllocatorType;
...@@ -2308,7 +2335,7 @@ public: ...@@ -2308,7 +2335,7 @@ public:
GenericArray() : ptr_() {} GenericArray() : ptr_() {}
GenericArray(const GenericArray& rhs) : ptr_(rhs.ptr_) {} GenericArray(const GenericArray& rhs) : ptr_(rhs.ptr_) {}
GenericArray& operator=(GenericArray& rhs) { ptr_ = rhs.ptr_; return *this; } GenericArray& operator=(const GenericArray& rhs) { ptr_ = rhs.ptr_; return *this; }
~GenericArray() {} ~GenericArray() {}
SizeType Size() const { return ptr_->Size(); } SizeType Size() const { return ptr_->Size(); }
...@@ -2343,12 +2370,9 @@ public: ...@@ -2343,12 +2370,9 @@ public:
private: private:
GenericArray(ValueType& value) : ptr_(&value) {} GenericArray(ValueType& value) : ptr_(&value) {}
GenericArray(const ValueType& value) : ptr_(const_cast<ValueType*>(&value)) {}
ValueType* ptr_; ValueType* ptr_;
}; };
typedef GenericArray<Value> Array;
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#ifdef _MSC_VER #ifdef _MSC_VER
......
...@@ -1028,20 +1028,40 @@ TEST(Value, ArrayHelper) { ...@@ -1028,20 +1028,40 @@ TEST(Value, ArrayHelper) {
Value::AllocatorType allocator; Value::AllocatorType allocator;
{ {
Value x(kArrayType); Value x(kArrayType);
Array a = x.GetArray(); Value::Array a = x.GetArray();
TestArray(a, allocator); TestArray(a, allocator);
} }
{
Value x(kArrayType); Value x(kArrayType);
Array a = x.GetArray(); Value::Array a = x.GetArray();
a.PushBack(1, allocator); a.PushBack(1, allocator);
Array a2(a); // copy constructor Value::Array a2(a); // copy constructor
EXPECT_EQ(1, a2.Size()); EXPECT_EQ(1, a2.Size());
Array a3; // default constructor Value::Array a3; // default constructor
a3 = a; // assignment operator a3 = a; // assignment operator
EXPECT_EQ(1, a3.Size()); EXPECT_EQ(1, a3.Size());
Value::ConstArray y = static_cast<const Value&>(x).GetArray();
(void)y;
// y.PushBack(1, allocator); // should not compile
// Templated functions
x.Clear();
EXPECT_TRUE(x.Is<Value::Array>());
EXPECT_TRUE(x.Is<Value::ConstArray>());
a.PushBack(1, allocator);
a = x.Get<Value::Array>();
EXPECT_EQ(1, a[0].GetInt());
EXPECT_EQ(1, x.Get<Value::ConstArray>()[0].GetInt());
Value x2;
x2.Set<Value::Array>(a);
EXPECT_TRUE(x.IsNull());
EXPECT_EQ(1, x2.Get<Value::Array>()[0].GetInt());
}
} }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR #if RAPIDJSON_HAS_CXX11_RANGE_FOR
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment