From 0b098eb38d57c35741a62883340cf2b2af7e4634 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 13 Feb 2016 22:09:14 +0800 Subject: [PATCH] Rectify constness of Array --- include/rapidjson/document.h | 54 ++++++++++++++++++++++++++---------- test/unittest/valuetest.cpp | 38 +++++++++++++++++++------ 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 59eb59f..1339c5b 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -481,9 +481,25 @@ struct TypeHelper > { }; #endif +template +struct TypeHelper { + 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 +struct TypeHelper { + 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 -template +template class GenericArray; /////////////////////////////////////////////////////////////////////////////// @@ -513,7 +529,8 @@ public: typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. typedef GenericValue ValueType; //!< Value type of itself. - typedef GenericArray ArrayType; + typedef GenericArray Array; + typedef GenericArray ConstArray; //!@name Constructors and destructor. //@{ @@ -1114,7 +1131,7 @@ public: RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(name.IsString()); - Object& o = data_.o; + ObjectData& o = data_.o; if (o.size >= o.capacity) { if (o.capacity == 0) { o.capacity = kDefaultObjectCapacity; @@ -1392,7 +1409,10 @@ public: //! Set this value as an empty array. /*! \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. SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } @@ -1560,8 +1580,8 @@ public: return pos; } - ArrayType GetArray() { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); } - const ArrayType GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ArrayType(*this); } + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } //@} @@ -1673,6 +1693,9 @@ public: template T Get() const { return internal::TypeHelper::Get(*this); } + template + T Get() { return internal::TypeHelper::Get(*this); } + template ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } @@ -1815,13 +1838,13 @@ private: double d; }; // 8 bytes - struct Object { + struct ObjectData { Member* members; SizeType size; SizeType capacity; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - struct Array { + struct ArrayData { GenericValue* elements; SizeType size; SizeType capacity; @@ -1831,8 +1854,8 @@ private: String s; ShortString ss; Number n; - Object o; - Array a; + ObjectData o; + ArrayData a; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode // Initialize this value as array with initial data, without calling destructor. @@ -2295,9 +2318,13 @@ GenericValue::GenericValue(const GenericValue +template class GenericArray { public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; typedef typename ValueType::ValueIterator ValueIterator; typedef typename ValueType::ConstValueIterator ConstValueIterator; typedef typename ValueType::AllocatorType AllocatorType; @@ -2308,7 +2335,7 @@ public: GenericArray() : 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() {} SizeType Size() const { return ptr_->Size(); } @@ -2343,12 +2370,9 @@ public: private: GenericArray(ValueType& value) : ptr_(&value) {} - GenericArray(const ValueType& value) : ptr_(const_cast(&value)) {} ValueType* ptr_; }; -typedef GenericArray Array; - RAPIDJSON_NAMESPACE_END #ifdef _MSC_VER diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 4f2d9df..9af1e1c 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -1028,20 +1028,40 @@ TEST(Value, ArrayHelper) { Value::AllocatorType allocator; { Value x(kArrayType); - Array a = x.GetArray(); + Value::Array a = x.GetArray(); TestArray(a, allocator); } - Value x(kArrayType); - Array a = x.GetArray(); - a.PushBack(1, allocator); + { + Value x(kArrayType); + Value::Array a = x.GetArray(); + a.PushBack(1, allocator); - Array a2(a); // copy constructor - EXPECT_EQ(1, a2.Size()); + Value::Array a2(a); // copy constructor + EXPECT_EQ(1, a2.Size()); - Array a3; // default constructor - a3 = a; // assignment operator - EXPECT_EQ(1, a3.Size()); + Value::Array a3; // default constructor + a3 = a; // assignment operator + EXPECT_EQ(1, a3.Size()); + + Value::ConstArray y = static_cast(x).GetArray(); + (void)y; + // y.PushBack(1, allocator); // should not compile + + // Templated functions + x.Clear(); + EXPECT_TRUE(x.Is()); + EXPECT_TRUE(x.Is()); + a.PushBack(1, allocator); + a = x.Get(); + EXPECT_EQ(1, a[0].GetInt()); + EXPECT_EQ(1, x.Get()[0].GetInt()); + + Value x2; + x2.Set(a); + EXPECT_TRUE(x.IsNull()); + EXPECT_EQ(1, x2.Get()[0].GetInt()); + } } #if RAPIDJSON_HAS_CXX11_RANGE_FOR