From 671a48a341c1d02a5c68f6ddd0935d096ccb7d5f Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 17 Apr 2019 16:30:55 +0100 Subject: [PATCH] Add move semantics to Array, Map & Value Change-Id: If1a9cc26637a2bd5a3cc1fa8c5c76f6c744727e1 --- .../src/dali/utc-Dali-PropertyArray.cpp | 99 +++++++++++++++++++++- automated-tests/src/dali/utc-Dali-PropertyMap.cpp | 90 +++++++++++++++++++- .../src/dali/utc-Dali-PropertyValue.cpp | 91 +++++++++++++++++++- dali/public-api/object/property-array.cpp | 35 +++++++- dali/public-api/object/property-array.h | 29 ++++++- dali/public-api/object/property-map.cpp | 85 +++++++++++++++---- dali/public-api/object/property-map.h | 29 ++++++- dali/public-api/object/property-value.cpp | 79 ++++++++++++----- dali/public-api/object/property-value.h | 37 +++++++- 9 files changed, 518 insertions(+), 56 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-PropertyArray.cpp b/automated-tests/src/dali/utc-Dali-PropertyArray.cpp index 4f3cd74..b4e5577 100644 --- a/automated-tests/src/dali/utc-Dali-PropertyArray.cpp +++ b/automated-tests/src/dali/utc-Dali-PropertyArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -278,3 +278,100 @@ int UtcDaliPropertyArrayOstream02(void) END_TEST; } + +int UtcDaliPropertyArrayCopyConstructor(void) +{ + Property::Array array1; + array1.PushBack( 0 ); + array1.PushBack( 1 ); + array1.PushBack( 2 ); + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + + Property::Array array2( array1 ); + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, array2.Size(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyArrayAssignmentOperator(void) +{ + Property::Array array1; + array1.PushBack( 0 ); + array1.PushBack( 1 ); + array1.PushBack( 2 ); + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + + Property::Array array2; + array2.PushBack( 4 ); + DALI_TEST_EQUALS( 1u, array2.Size(), TEST_LOCATION ); + + array2 = array1; + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, array2.Size(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyArrayMoveConstructor(void) +{ + Property::Array array1; + array1.PushBack( 0 ); + array1.PushBack( 1 ); + array1.PushBack( 2 ); + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + + Property::Array array2( std::move( array1 ) ); + DALI_TEST_EQUALS( 3u, array2.Size(), TEST_LOCATION ); + + // Calling any methods on array1 will debug assert + const char * exceptionMessage = "Cannot use an object previously used as an r-value"; + DALI_TEST_ASSERTION( array1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.PushBack( Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Clear(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Reserve( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Resize( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Capacity(), exceptionMessage ); + DALI_TEST_ASSERTION( array1[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Array& >( array1 )[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( Property::Array temp; array1 = temp, exceptionMessage ); + + END_TEST; +} + +int UtcDaliPropertyArrayMoveAssignmentOperator(void) +{ + Property::Array array1; + array1.PushBack( 0 ); + array1.PushBack( 1 ); + array1.PushBack( 2 ); + DALI_TEST_EQUALS( 3u, array1.Size(), TEST_LOCATION ); + + Property::Array array2; + array2.PushBack( 4 ); + DALI_TEST_EQUALS( 1u, array2.Size(), TEST_LOCATION ); + + array2 = std::move( array1 ); + DALI_TEST_EQUALS( 3u, array2.Size(), TEST_LOCATION ); + + // Calling any methods on array1 will debug assert + const char * exceptionMessage = "Cannot use an object previously used as an r-value"; + DALI_TEST_ASSERTION( array1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.PushBack( Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Clear(), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Reserve( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Resize( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( array1.Capacity(), exceptionMessage ); + DALI_TEST_ASSERTION( array1[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Array& >( array1 )[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( Property::Array temp; array1 = temp, exceptionMessage ); + + // Self assignemnt + array2 = std::move( array2 ); + DALI_TEST_EQUALS( 3u, array2.Size(), TEST_LOCATION ); // still works, no debug assert + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-PropertyMap.cpp b/automated-tests/src/dali/utc-Dali-PropertyMap.cpp index 7283e1c..46da84c 100644 --- a/automated-tests/src/dali/utc-Dali-PropertyMap.cpp +++ b/automated-tests/src/dali/utc-Dali-PropertyMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,6 +80,94 @@ int UtcDaliPropertyMapCopyAndAssignment(void) END_TEST; } +int UtcDaliPropertyMapMoveConstructor(void) +{ + Property::Map map1; + map1[ "hello" ] = 1; + map1[ "world" ] = 2; + map1[ 10 ] = "DALi"; + DALI_TEST_EQUALS( 3u, map1.Count(), TEST_LOCATION ); + + Property::Map map2( std::move( map1 ) ); + DALI_TEST_EQUALS( 3u, map2.Count(), TEST_LOCATION ); + + // Calling any methods on map1 will debug assert + const char * exceptionMessage = "Cannot use an object previously used as an r-value"; + DALI_TEST_ASSERTION( map1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Empty(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( (const char *)"key", Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( std::string( "key" ), Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( 0, Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetValue( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKey( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKeyAt( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetPair( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKeyValue( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( (const char *)"key" ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( std::string( "key" ) ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0, "key" ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( "key", Property::INTEGER ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0, Property::INTEGER ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Clear(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Merge( Property::Map() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1[ "key" ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Map& >( map1 )[ "key" ], exceptionMessage ); + DALI_TEST_ASSERTION( map1[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Map& >( map1 )[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( Property::Map temp; map1 = temp, exceptionMessage ); + + END_TEST; +} + +int UtcDaliPropertyMapMoveAssignmentOperator(void) +{ + Property::Map map1; + map1[ "hello" ] = 1; + map1[ "world" ] = 2; + map1[ 10 ] = "DALi"; + DALI_TEST_EQUALS( 3u, map1.Count(), TEST_LOCATION ); + + Property::Map map2; + map2[ 10 ] = "DALi again"; + DALI_TEST_EQUALS( 1u, map2.Count(), TEST_LOCATION ); + + map2 = std::move( map1 ); + DALI_TEST_EQUALS( 3u, map2.Count(), TEST_LOCATION ); + + // Calling any methods on map1 will debug assert + const char * exceptionMessage = "Cannot use an object previously used as an r-value"; + DALI_TEST_ASSERTION( map1.Count(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Empty(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( (const char *)"key", Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( std::string( "key" ), Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Insert( 0, Property::Value() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetValue( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKey( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKeyAt( 1 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetPair( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.GetKeyValue( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( (const char *)"key" ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( std::string( "key" ) ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0 ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0, "key" ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( "key", Property::INTEGER ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Find( 0, Property::INTEGER ), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Clear(), exceptionMessage ); + DALI_TEST_ASSERTION( map1.Merge( Property::Map() ), exceptionMessage ); + DALI_TEST_ASSERTION( map1[ "key" ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Map& >( map1 )[ "key" ], exceptionMessage ); + DALI_TEST_ASSERTION( map1[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( const_cast< const Property::Map& >( map1 )[ 0 ], exceptionMessage ); + DALI_TEST_ASSERTION( Property::Map temp; map1 = temp, exceptionMessage ); + + // Self assignment + map2 = std::move( map2 ); + DALI_TEST_EQUALS( 3u, map2.Count(), TEST_LOCATION ); // No debug assert as nothing should happen + + END_TEST; +} + int UtcDaliPropertyMapConstOperator(void) { Property::Map map; diff --git a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp index 78fbe46..3fd0fc6 100644 --- a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp +++ b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -506,6 +506,61 @@ int UtcDaliPropertyValueCopyConstructorMapP(void) END_TEST; } +int UtcDaliPropertyValueMoveConstructor(void) +{ + Property::Value value1( Vector4::ONE ); + DALI_TEST_EQUALS( Property::VECTOR4, value1.GetType(), TEST_LOCATION ); + + Vector4 valueVector; + DALI_TEST_EQUALS( true, value1.Get( valueVector ), TEST_LOCATION ); // Able to convert + DALI_TEST_EQUALS( valueVector, Vector4::ONE, TEST_LOCATION ); + + Property::Value value2( std::move( value1 ) ); + DALI_TEST_EQUALS( Property::NONE, value1.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value1.Get( valueVector ), TEST_LOCATION ); // Unable to convert, but no crash either + DALI_TEST_EQUALS( Property::VECTOR4, value2.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value2.Get( valueVector ), TEST_LOCATION ); // Able to convert + DALI_TEST_EQUALS( valueVector, Vector4::ONE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueMoveConstructorArray(void) +{ + Property::Array array; + array.PushBack( 1 ); + array.PushBack( 2 ); + array.PushBack( 3 ); + DALI_TEST_EQUALS( 3u, array.Size(), TEST_LOCATION ); + + Property::Value value( std::move( array ) ); + DALI_TEST_ASSERTION( array.Size(), "Cannot use an object previously used as an r-value" ); // Our local variable should become invalid + + Property::Array* arrayPtr = value.GetArray(); + DALI_TEST_CHECK( arrayPtr ); + DALI_TEST_EQUALS( 3u, arrayPtr->Size(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueMoveConstructorMap(void) +{ + Property::Map map; + map[ 1 ] = 1; + map[ 2 ] = 2; + map[ 3 ] = 3; + DALI_TEST_EQUALS( 3u, map.Count(), TEST_LOCATION ); + + Property::Value value( std::move( map ) ); + DALI_TEST_ASSERTION( map.Count(), "Cannot use an object previously used as an r-value" ); // Our local variable should become invalid + + Property::Map* mapPtr = value.GetMap(); + DALI_TEST_CHECK( mapPtr ); + DALI_TEST_EQUALS( 3u, mapPtr->Count(), TEST_LOCATION ); + + END_TEST; +} + int UtcDaliPropertyValueAssignmentSelfP(void) { Property::Value value; @@ -712,6 +767,38 @@ int UtcDaliPropertyValueAssignmentOperatorExtentsP(void) END_TEST; } +int UtcDaliPropertyValueMoveAssignmentOperator(void) +{ + Property::Value value1( Vector4::ONE ); + DALI_TEST_EQUALS( Property::VECTOR4, value1.GetType(), TEST_LOCATION ); + + Vector4 valueVector; + DALI_TEST_EQUALS( true, value1.Get( valueVector ), TEST_LOCATION ); // Able to convert + DALI_TEST_EQUALS( valueVector, Vector4::ONE, TEST_LOCATION ); + + Property::Value value2; + value2 = std::move( value1 ); + DALI_TEST_EQUALS( Property::NONE, value1.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value1.Get( valueVector ), TEST_LOCATION ); // Unable to convert, but no crash either + DALI_TEST_EQUALS( Property::VECTOR4, value2.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value2.Get( valueVector ), TEST_LOCATION ); // Able to convert + DALI_TEST_EQUALS( valueVector, Vector4::ONE, TEST_LOCATION ); + + // Change to another value type + value2 = std::move( Property::Value( 1.0f ) ); + DALI_TEST_EQUALS( false, value2.Get( valueVector ), TEST_LOCATION ); // Should not be able to convert to a Vector4 now + float valueFloat; + DALI_TEST_EQUALS( true, value2.Get( valueFloat ), TEST_LOCATION ); // Should be able to convert to a float now + DALI_TEST_EQUALS( valueFloat, 1.0f, TEST_LOCATION ); + + // Ensure self assignment doesn't do anything silly + value2 = std::move( value2 ); + DALI_TEST_EQUALS( true, value2.Get( valueFloat ), TEST_LOCATION ); + DALI_TEST_EQUALS( valueFloat, 1.0f, TEST_LOCATION ); + + END_TEST; +} + int UtcDaliPropertyValueGetTypeP(void) { Property::Value value; @@ -1177,7 +1264,7 @@ int UtcDaliPropertyValueOutputStream(void) Property::Value empty; std::ostringstream stream; stream << empty; - DALI_TEST_EQUALS( stream.str(), "empty type", TEST_LOCATION ); + DALI_TEST_EQUALS( stream.str(), "undefined type", TEST_LOCATION ); } { diff --git a/dali/public-api/object/property-array.cpp b/dali/public-api/object/property-array.cpp index 7fe8447..bbdeb56 100644 --- a/dali/public-api/object/property-array.cpp +++ b/dali/public-api/object/property-array.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,12 @@ Property::Array::Array( const Property::Array& other ) mImpl->mArray = other.mImpl->mArray; } +Property::Array::Array( Property::Array&& other ) +: mImpl( other.mImpl ) +{ + other.mImpl = nullptr; +} + Property::Array::~Array() { delete mImpl; @@ -53,55 +59,78 @@ Property::Array::~Array() Property::Array::SizeType Property::Array::Count() const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); return mImpl->mArray.size(); } void Property::Array::PushBack( const Value& value ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mArray.push_back( value ); } void Property::Array::Clear() { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mArray.clear(); } void Property::Array::Reserve( SizeType size ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mArray.reserve(size); } void Property::Array::Resize( SizeType size ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mArray.resize(size); } Property::Array::SizeType Property::Array::Capacity() { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); return mImpl->mArray.capacity(); } const Property::Value& Property::Array::operator[]( SizeType index ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + + // Note says no bounds checking is performed so we don't need to verify mImpl as Count() will return 0 anyway return mImpl->mArray[ index ]; } Property::Value& Property::Array::operator[]( SizeType index ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + + // Note says no bounds checking is performed so we don't need to verify mImpl as Count() will return 0 anyway return mImpl->mArray[ index ]; } Property::Array& Property::Array::operator=( const Property::Array& other ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + if( this != &other ) { - delete mImpl; - mImpl = new Impl; mImpl->mArray = other.mImpl->mArray; } return *this; } +Property::Array& Property::Array::operator=( Property::Array&& other ) +{ + if( this != &other ) + { + delete mImpl; + mImpl = other.mImpl; + other.mImpl = nullptr; + } + return *this; +} + std::ostream& operator<<( std::ostream& stream, const Property::Array& array ) { stream << "Array(" << array.Count() << ") = ["; diff --git a/dali/public-api/object/property-array.h b/dali/public-api/object/property-array.h index 331d1e9..e4ac804 100755 --- a/dali/public-api/object/property-array.h +++ b/dali/public-api/object/property-array.h @@ -1,8 +1,8 @@ -#ifndef __DALI_PROPERTY_ARRAY_H__ -#define __DALI_PROPERTY_ARRAY_H__ +#ifndef DALI_PROPERTY_ARRAY_H +#define DALI_PROPERTY_ARRAY_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,6 +58,15 @@ public: Array( const Array& other ); /** + * @brief Move Constructor. + * + * @SINCE_1_4.17 + * @param[in] other The Array to move from + * @note The other array is an r-value so becomes invalid and is no longer usable. + */ + Array( Array&& other ); + + /** * @brief Non-virtual destructor. * @SINCE_1_0.0 */ @@ -197,6 +206,18 @@ public: Array& operator=( const Array& other ); /** + * @brief Move Assignment Operator. + * + * @SINCE_1_4.17 + * @param[in] other The array to copy from + * + * @return The moved array. + * + * @note The other array is an r-value so becomes invalid and is no longer usable. + */ + Array& operator=( Array&& other ); + + /** * @brief Output to stream. * @SINCE_1_1.28 */ @@ -222,4 +243,4 @@ DALI_CORE_API std::ostream& operator<<( std::ostream& stream, const Property::Ar */ } // namespace Dali -#endif // __DALI_PROPERTY_ARRAY_H__ +#endif // DALI_PROPERTY_ARRAY_H diff --git a/dali/public-api/object/property-map.cpp b/dali/public-api/object/property-map.cpp index 675d910..61329a8 100644 --- a/dali/public-api/object/property-map.cpp +++ b/dali/public-api/object/property-map.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,6 +55,12 @@ Property::Map::Map( const Property::Map& other ) mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer; } +Property::Map::Map( Property::Map&& other ) +: mImpl( other.mImpl ) +{ + other.mImpl = nullptr; +} + Property::Map::~Map() { delete mImpl; @@ -62,31 +68,37 @@ Property::Map::~Map() Property::Map::SizeType Property::Map::Count() const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size(); } bool Property::Map::Empty() const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty(); } void Property::Map::Insert( const char* key, const Value& value ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) ); } void Property::Map::Insert( const std::string& key, const Value& value ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) ); } void Property::Map::Insert( Property::Index key, const Value& value ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); mImpl->mIndexValueContainer.push_back( std::make_pair( key, value ) ); } Property::Value& Property::Map::GetValue( SizeType position ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); SizeType numStringKeys = mImpl->mStringValueContainer.size(); SizeType numIndexKeys = mImpl->mIndexValueContainer.size(); DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" ); @@ -105,6 +117,7 @@ const std::string& Property::Map::GetKey( SizeType position ) const { DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n" ); + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); SizeType numStringKeys = mImpl->mStringValueContainer.size(); DALI_ASSERT_ALWAYS( position < numStringKeys && "position out-of-bounds" ); @@ -113,6 +126,8 @@ const std::string& Property::Map::GetKey( SizeType position ) const Property::Key Property::Map::GetKeyAt( SizeType position ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + SizeType numStringKeys = mImpl->mStringValueContainer.size(); SizeType numIndexKeys = mImpl->mIndexValueContainer.size(); DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" ); @@ -133,6 +148,8 @@ StringValuePair& Property::Map::GetPair( SizeType position ) const { DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n" ); + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + SizeType numStringKeys = mImpl->mStringValueContainer.size(); DALI_ASSERT_ALWAYS( position < ( numStringKeys ) && "position out-of-bounds" ); @@ -142,6 +159,8 @@ StringValuePair& Property::Map::GetPair( SizeType position ) const KeyValuePair Property::Map::GetKeyValue( SizeType position ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + SizeType numStringKeys = mImpl->mStringValueContainer.size(); SizeType numIndexKeys = mImpl->mIndexValueContainer.size(); @@ -163,6 +182,8 @@ KeyValuePair Property::Map::GetKeyValue( SizeType position ) const Property::Value* Property::Map::Find( const char* key ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -180,6 +201,8 @@ Property::Value* Property::Map::Find( const std::string& key ) const Property::Value* Property::Map::Find( Property::Index key ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -202,6 +225,8 @@ Property::Value* Property::Map::Find( Property::Index indexKey, const std::strin Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) { if( (iter->second.GetType() == type) && (iter->first == key) ) @@ -214,6 +239,8 @@ Property::Value* Property::Map::Find( const std::string& key, Property::Type typ Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) { if( (iter->second.GetType() == type) && (iter->first == key) ) @@ -226,12 +253,16 @@ Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) void Property::Map::Clear() { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + mImpl->mStringValueContainer.clear(); mImpl->mIndexValueContainer.clear(); } void Property::Map::Merge( const Property::Map& from ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + // Ensure we're not attempting to merge with ourself if ( this != &from ) { @@ -257,6 +288,8 @@ void Property::Map::Merge( const Property::Map& from ) const Property::Value& Property::Map::operator[]( const std::string& key ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( StringValueContainer::const_iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -270,6 +303,8 @@ const Property::Value& Property::Map::operator[]( const std::string& key ) const Property::Value& Property::Map::operator[]( const std::string& key ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -285,6 +320,8 @@ Property::Value& Property::Map::operator[]( const std::string& key ) const Property::Value& Property::Map::operator[]( Property::Index key ) const { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( IndexValueContainer::const_iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -298,6 +335,8 @@ const Property::Value& Property::Map::operator[]( Property::Index key ) const Property::Value& Property::Map::operator[]( Property::Index key ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) { if ( iter->first == key ) @@ -313,39 +352,53 @@ Property::Value& Property::Map::operator[]( Property::Index key ) Property::Map& Property::Map::operator=( const Property::Map& other ) { + DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" ); + if( this != &other ) { - delete mImpl; - mImpl = new Impl; mImpl->mStringValueContainer = other.mImpl->mStringValueContainer; mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer; } return *this; } +Property::Map& Property::Map::operator=( Property::Map&& other ) +{ + if( this != &other ) + { + delete mImpl; + mImpl = other.mImpl; + other.mImpl = nullptr; + } + return *this; +} + std::ostream& operator<<( std::ostream& stream, const Property::Map& map ) { stream << "Map(" << map.Count() << ") = {"; - int32_t count = 0; - // Output the String-Value pairs - for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) + if ( map.mImpl ) { - if( count++ > 0 ) + int32_t count = 0; + // Output the String-Value pairs + for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter ) { - stream<<", "; + if( count++ > 0 ) + { + stream<<", "; + } + stream<< iter->first << ":"<second; } - stream<< iter->first << ":"<second; - } - // Output the Index-Value pairs - for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) - { - if( count++ > 0 ) + // Output the Index-Value pairs + for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter ) { - stream<<", "; + if( count++ > 0 ) + { + stream<<", "; + } + stream<< iter->first << ":"<second; } - stream<< iter->first << ":"<second; } stream << "}"; diff --git a/dali/public-api/object/property-map.h b/dali/public-api/object/property-map.h index 44a132f..f23f2b3 100755 --- a/dali/public-api/object/property-map.h +++ b/dali/public-api/object/property-map.h @@ -1,8 +1,8 @@ -#ifndef __DALI_PROPERTY_MAP_H__ -#define __DALI_PROPERTY_MAP_H__ +#ifndef DALI_PROPERTY_MAP_H +#define DALI_PROPERTY_MAP_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,6 +63,15 @@ public: Map( const Map& other ); /** + * @brief Move Constructor. + * + * @SINCE_1_4.17 + * @param[in] other The Map to move from + * @note The other array is an r-value so becomes invalid and is no longer usable. + */ + Map( Map&& other ); + + /** * @brief Non-virtual destructor. * @SINCE_1_0.0 */ @@ -360,6 +369,18 @@ public: Map& operator=( const Map& other ); /** + * @brief Move Assignment Operator. + * + * @SINCE_1_4.17 + * @param[in] other The map to move from + * + * @return The moved map + * + * @note The other array is an r-value so becomes invalid and is no longer usable. + */ + Map& operator=( Map&& other ); + + /** * @brief Output to stream. * @SINCE_1_1.28 */ @@ -385,4 +406,4 @@ DALI_CORE_API std::ostream& operator<<( std::ostream& stream, const Property::Ma */ } // namespace Dali -#endif // __DALI_PROPERTY_MAP_H__ +#endif // DALI_PROPERTY_MAP_H diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp index cd7ae5a..fbcfc2b 100644 --- a/dali/public-api/object/property-value.cpp +++ b/dali/public-api/object/property-value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,11 +53,6 @@ inline bool IsIntegerType( Property::Type type ) struct Property::Value::Impl { - Impl() - : type( Property::NONE ), - integerValue( 0 ) - { } - Impl( bool booleanValue ) : type( Property::BOOLEAN ), integerValue( booleanValue ) @@ -113,7 +108,7 @@ struct Property::Value::Impl quaternionValue.ToAxisAngle( angleAxisValue->axis, angleAxisValue->angle ); } - Impl(const std::string& stringValue) + Impl( const std::string& stringValue ) : type( Property::STRING ), stringValue( new std::string( stringValue ) ) { @@ -131,12 +126,24 @@ struct Property::Value::Impl { } + Impl( Property::Array&& arrayValue ) + : type( Property::ARRAY ), + arrayValue( new Property::Array( std::move( arrayValue ) ) ) + { + } + Impl( const Property::Map& mapValue ) : type( Property::MAP ), mapValue( new Property::Map( mapValue ) ) { } + Impl( Property::Map&& mapValue ) + : type( Property::MAP ), + mapValue( new Property::Map( std::move( mapValue ) ) ) + { + } + Impl( const Extents& extentsValue ) : type( Property::EXTENTS ), extentsValue( new Extents( extentsValue ) ) @@ -245,7 +252,7 @@ private: }; Property::Value::Value() -: mImpl( NULL ) +: mImpl( nullptr ) { } @@ -310,9 +317,9 @@ Property::Value::Value( const std::string& stringValue ) } Property::Value::Value( const char* stringValue ) -: mImpl( NULL ) +: mImpl( nullptr ) { - if( stringValue ) // string constructor is undefined with NULL pointer + if( stringValue ) // string constructor is undefined with nullptr { mImpl = new Impl( std::string(stringValue) ); } @@ -327,18 +334,28 @@ Property::Value::Value( Property::Array& arrayValue ) { } +Property::Value::Value( Property::Array&& arrayValue ) +: mImpl( new Impl( std::move( arrayValue ) ) ) +{ +} + Property::Value::Value( Property::Map& mapValue ) : mImpl( new Impl( mapValue ) ) { } +Property::Value::Value( Property::Map&& mapValue ) +: mImpl( new Impl( std::move( mapValue ) ) ) +{ +} + Property::Value::Value( const Extents& extentsValue ) : mImpl( new Impl( extentsValue ) ) { } Property::Value::Value( Type type ) -: mImpl( NULL ) +: mImpl( nullptr ) { switch (type) { @@ -414,19 +431,25 @@ Property::Value::Value( Type type ) } case Property::NONE: { - mImpl = new Impl(); + // No need to create an Impl break; } } } Property::Value::Value( const Property::Value& value ) -: mImpl( NULL ) +: mImpl( nullptr ) { // reuse assignment operator operator=( value ); } +Property::Value::Value( Property::Value&& value ) +: mImpl( value.mImpl ) +{ + value.mImpl = nullptr; +} + Property::Value& Property::Value::operator=( const Property::Value& value ) { if ( this == &value ) @@ -438,7 +461,7 @@ Property::Value& Property::Value::operator=( const Property::Value& value ) if( !value.mImpl ) { delete mImpl; - mImpl = NULL; + mImpl = nullptr; return *this; } // first check if the type is the same, no need to change impl, just assign @@ -517,14 +540,14 @@ Property::Value& Property::Value::operator=( const Property::Value& value ) break; } case Property::NONE: - { // mImpl will be NULL, there's no way to get to this case + { // mImpl will be a nullptr, there's no way to get to this case } } } else { // different type, release old impl and create new - Impl* newImpl( NULL ); + Impl* newImpl( nullptr ); switch ( value.mImpl->type ) { case Property::BOOLEAN: @@ -598,7 +621,7 @@ Property::Value& Property::Value::operator=( const Property::Value& value ) break; } case Property::NONE: - { // NULL value will be used for "empty" value + { // nullptr value will be used for "empty" value } } delete mImpl; @@ -608,6 +631,18 @@ Property::Value& Property::Value::operator=( const Property::Value& value ) return *this; } +Property::Value& Property::Value::operator=( Property::Value&& value ) +{ + if( this != &value ) + { + delete mImpl; + mImpl = value.mImpl; + value.mImpl = nullptr; + } + + return *this; +} + Property::Value::~Value() { delete mImpl; @@ -821,7 +856,7 @@ bool Property::Value::Get( Property::Map& mapValue ) const Property::Array* Property::Value::GetArray() const { - Property::Array* array = NULL; + Property::Array* array = nullptr; if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated { array = mImpl->arrayValue; @@ -831,7 +866,7 @@ Property::Array* Property::Value::GetArray() const Property::Map* Property::Value::GetMap() const { - Property::Map* map = NULL; + Property::Map* map = nullptr; if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated { map = mImpl->mapValue; @@ -940,15 +975,13 @@ std::ostream& operator<<( std::ostream& stream, const Property::Value& value ) break; } case Dali::Property::NONE: - { - stream << "undefined type"; - break; + { // mImpl will be a nullptr, there's no way to get to this case } } } else { - stream << "empty type"; + stream << "undefined type"; } return stream; } diff --git a/dali/public-api/object/property-value.h b/dali/public-api/object/property-value.h index b054810..d8f074a 100755 --- a/dali/public-api/object/property-value.h +++ b/dali/public-api/object/property-value.h @@ -2,7 +2,7 @@ #define __DALI_PROPERTY_VALUE_H__ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -170,14 +170,30 @@ public: Value( Property::Array& arrayValue ); /** + * @brief Creates an array property value. + * + * @SINCE_1_4.16 + * @param[in] arrayValue An r-value array + */ + Value( Property::Array&& arrayValue ); + + /** * @brief Creates a map property value. * * @SINCE_1_0.0 - * @param[in] mapValue An array + * @param[in] mapValue A map */ Value( Property::Map& mapValue ); /** + * @brief Creates a map property value. + * + * @SINCE_1_4.16 + * @param[in] mapValue An r-value map + */ + Value( Property::Map&& mapValue ); + + /** * @brief Creates an extents property value. * * @SINCE_1_2.62 @@ -202,6 +218,14 @@ public: Value( const Value& value ); /** + * @brief Move constructor. + * + * @SINCE_1_4.16 + * @param[in] value The property value to move from + */ + Value( Value&& value ); + + /** * @brief Assigns a property value. * * @SINCE_1_0.0 @@ -211,6 +235,15 @@ public: Value& operator=( const Value& value ); /** + * @brief Move assignment operator. + * + * @SINCE_1_4.16 + * @param[in] value The property value to move from + * @return a reference to this + */ + Value& operator=( Value&& value ); + + /** * @brief Non-virtual destructor. * * This class is not a base class. -- 2.7.4