X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fpublic-api%2Fobject%2Fproperty-value.cpp;h=09bb5c7bc7118280275e5393d7bfa0a391d9f2c2;hb=24cf3ec005ffb58f751fe8f1ff41beb52128917d;hp=fbcfc2b608c5a81bc13736c28291697faed457b8;hpb=671a48a341c1d02a5c68f6ddd0935d096ccb7d5f;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp index fbcfc2b..09bb5c7 100644 --- a/dali/public-api/object/property-value.cpp +++ b/dali/public-api/object/property-value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -22,411 +22,686 @@ #include // INTERNAL INCLUDES +#include #include #include +#include +#include +#include #include +#include #include #include #include -#include -#include -#include -#include -#include #include +#include #include -#include namespace Dali { -namespace -{ -/** - * Helper to check if the property value can be read as int/bool - */ -inline bool IsIntegerType( Property::Type type ) -{ - return ( Property::BOOLEAN == type )||( Property::INTEGER == type ); -} -} - struct Property::Value::Impl { - Impl( bool booleanValue ) - : type( Property::BOOLEAN ), - integerValue( booleanValue ) - { } + ~Impl() + { + // Destroy the current object stored in Data union memory. + Destroy(); + } - Impl( float floatValue ) - : type( Property::FLOAT ), - floatValue( floatValue ) - { } + Impl(const Impl&) = delete; - Impl( int32_t integerValue ) - : type( Property::INTEGER ), - integerValue( integerValue ) - { } + Impl(Impl&&) = delete; - Impl( const Vector2& vectorValue ) - : type( Property::VECTOR2 ), - vector2Value( new Vector2( vectorValue ) ) - { } + Impl& operator=(Impl&&) = delete; - Impl( const Vector3& vectorValue ) - : type( Property::VECTOR3 ), - vector3Value( new Vector3( vectorValue ) ) - { } + Impl() + { + static_assert(sizeof(Impl) == 16); + static_assert(alignof(Impl) == alignof(Impl*)); - Impl( const Vector4& vectorValue ) - : type( Property::VECTOR4 ), - vector4Value( new Vector4( vectorValue ) ) - { } + SetType(Property::NONE); + } - Impl( const Matrix3& matrixValue ) - : type( Property::MATRIX3 ), - matrix3Value( new Matrix3( matrixValue ) ) + Impl(bool booleanValue) { + SetType(Property::BOOLEAN); + mData.mBool.member = booleanValue; } - Impl( const Matrix& matrixValue ) - : type( Property::MATRIX ), - matrixValue( new Matrix( matrixValue ) ) + Impl(float floatValue) { + SetType(Property::FLOAT); + mData.mFloat.member = floatValue; } - Impl( const AngleAxis& angleAxisValue ) - : type( Property::ROTATION ), - angleAxisValue( new AngleAxis(angleAxisValue) ) + Impl(int32_t integerValue) { + SetType(Property::INTEGER); + mData.mInt.member = integerValue; } - Impl( const Quaternion& quaternionValue ) - : type( Property::ROTATION ), - angleAxisValue( new AngleAxis() ) + Impl(Vector2 vectorValue) { - quaternionValue.ToAxisAngle( angleAxisValue->axis, angleAxisValue->angle ); + SetType(Property::VECTOR2); + ConstructInplace(mData.mVector2.member, std::move(vectorValue)); } - Impl( const std::string& stringValue ) - : type( Property::STRING ), - stringValue( new std::string( stringValue ) ) + Impl(Vector3 vectorValue) { + SetType(Property::VECTOR3); + ConstructInplace(mData.mVector3.member, std::move(vectorValue)); } - Impl( const Rect& rectValue ) - : type( Property::RECTANGLE ), - rectValue( new Rect( rectValue ) ) + Impl(Extents extentsValue) { + SetType(Property::EXTENTS); + ConstructInplace(mData.mExtents.member, std::move(extentsValue)); } - Impl( const Property::Array& arrayValue ) - : type( Property::ARRAY ), - arrayValue( new Property::Array( arrayValue ) ) + Impl(Property::Map mapValue) { + SetType(Property::MAP); + ConstructInplace(mData.mMap.member, std::move(mapValue)); } - Impl( Property::Array&& arrayValue ) - : type( Property::ARRAY ), - arrayValue( new Property::Array( std::move( arrayValue ) ) ) + Impl(Property::Array arrayValue) { + SetType(Property::ARRAY); + ConstructInplace(mData.mArray.member, std::move(arrayValue)); } - Impl( const Property::Map& mapValue ) - : type( Property::MAP ), - mapValue( new Property::Map( mapValue ) ) + Impl(std::string stringValue) { + SetType(Property::STRING); + mData.mString.member = new std::string(std::move(stringValue)); } - Impl( Property::Map&& mapValue ) - : type( Property::MAP ), - mapValue( new Property::Map( std::move( mapValue ) ) ) + Impl(Rect rectValue) { + SetType(Property::RECTANGLE); + mData.mRect.member = new Rect(std::move(rectValue)); } - Impl( const Extents& extentsValue ) - : type( Property::EXTENTS ), - extentsValue( new Extents( extentsValue ) ) + Impl(Vector4 vectorValue) { + SetType(Property::VECTOR4); + mData.mVector4.member = new Vector4(std::move(vectorValue)); } - /** - * Destructor, takes care of releasing the dynamically allocated types - */ - ~Impl() + Impl(Matrix3 matrixValue) + { + SetType(Property::MATRIX3); + mData.mMatrix3.member = new Matrix3(std::move(matrixValue)); + } + + Impl(Matrix matrixValue) + { + SetType(Property::MATRIX); + mData.mMatrix.member = new Matrix(std::move(matrixValue)); + } + + Impl(AngleAxis angleAxisValue) + { + SetType(Property::ROTATION); + mData.mAngleAxis.member = new AngleAxis(std::move(angleAxisValue)); + } + + Type GetType() const + { + return mData.mType.type; + } + + bool GetBool() const { - switch( type ) + return mData.mBool.member; + } + + int32_t GetInt() const + { + return mData.mInt.member; + } + + float GetFloat() const + { + return mData.mFloat.member; + } + + const Extents& GetExtents() const + { + return mData.mExtents.member; + } + + const Vector2& GetVector2() const + { + return mData.mVector2.member; + } + + const Vector3& GetVector3() const + { + return mData.mVector3.member; + } + + const Property::Map& GetMap() const + { + return mData.mMap.member; + } + + const Property::Array& GetArray() const + { + return mData.mArray.member; + } + + const Vector4& GetVector4() const + { + return *(mData.mVector4.member); + } + + const Matrix3& GetMatrix3() const + { + return *(mData.mMatrix3.member); + } + + const Matrix& GetMatrix() const + { + return *(mData.mMatrix.member); + } + + const AngleAxis& GetAngleAxis() const + { + return *(mData.mAngleAxis.member); + } + + const std::string& GetString() const + { + return *(mData.mString.member); + } + + const Rect& GetRect() const + { + return *(mData.mRect.member); + } + + Property::Map* GetMapPtr() + { + return &(mData.mMap.member); + } + + Property::Array* GetArrayPtr() + { + return &(mData.mArray.member); + } + + Impl& operator=(const Impl& other) + { + const bool isSameType = GetType() == other.GetType(); + + if(!isSameType) { - case Property::NONE : // FALLTHROUGH - case Property::BOOLEAN : // FALLTHROUGH - case Property::FLOAT : // FALLTHROUGH - case Property::INTEGER : + Destroy(); + SetType(other.GetType()); + } + + switch(GetType()) + { + case Property::NONE: { - break; // nothing to do + break; + } + case Property::BOOLEAN: + { + mData.mBool.member = other.GetBool(); + break; + } + case Property::FLOAT: + { + mData.mFloat.member = other.GetFloat(); + break; + } + case Property::INTEGER: + { + mData.mInt.member = other.GetInt(); + break; } - case Property::VECTOR2 : + case Property::EXTENTS: { - delete vector2Value; + auto obj = other.GetExtents(); + ConstructInplace(mData.mExtents.member, std::move(obj)); + break; + } + case Property::VECTOR2: + { + auto obj = other.GetVector2(); + ConstructInplace(mData.mVector2.member, std::move(obj)); break; } case Property::VECTOR3: { - delete vector3Value; + auto obj = other.GetVector3(); + ConstructInplace(mData.mVector3.member, std::move(obj)); + break; + } + case Property::ARRAY: + { + auto obj = other.GetArray(); + ConstructInplace(mData.mArray.member, std::move(obj)); + break; + } + case Property::MAP: + { + auto obj = other.GetMap(); + ConstructInplace(mData.mMap.member, std::move(obj)); break; } case Property::VECTOR4: { - delete vector4Value; + if(isSameType) + { + *mData.mVector4.member = other.GetVector4(); + } + else + { + mData.mVector4.member = new Vector4(other.GetVector4()); + } break; } case Property::MATRIX3: { - delete matrix3Value; + if(isSameType) + { + *mData.mMatrix3.member = other.GetMatrix3(); + } + else + { + mData.mMatrix3.member = new Matrix3(other.GetMatrix3()); + } break; } case Property::MATRIX: { - delete matrixValue; + if(isSameType) + { + *mData.mMatrix.member = other.GetMatrix(); + } + else + { + mData.mMatrix.member = new Matrix(other.GetMatrix()); + } break; } case Property::RECTANGLE: { - delete rectValue; + if(isSameType) + { + *mData.mRect.member = other.GetRect(); + } + else + { + mData.mRect.member = new Rect(other.GetRect()); + } break; } case Property::ROTATION: { - delete angleAxisValue; + if(isSameType) + { + *mData.mAngleAxis.member = other.GetAngleAxis(); + } + else + { + mData.mAngleAxis.member = new AngleAxis(other.GetAngleAxis()); + } break; } case Property::STRING: { - delete stringValue; + if(isSameType) + { + *mData.mString.member = other.GetString(); + } + else + { + mData.mString.member = new std::string(other.GetString()); + } + break; + } + } + return *this; + } + +private: + void SetType(Type typeValue) + { + mData.mType.type = typeValue; + } + + /** + * This helper function takes a typed(Tp) memory location( member) + * and a object of same type( val ) and move constructs a new object of + * same type(Tp) in the memory location( member) using placement new. + * after this function call member location will have a object of type Tp. + */ + template + void ConstructInplace(Tp& member, Tp&& val) + { + new(&member) Tp(std::forward(val)); + } + + /** + * Destroy the object created in the Data union memory by probing the + * type and calling the appropriate destructor. + * and also reset the type and memory location to reflect that . + */ + void Destroy() + { + switch(GetType()) + { + case Property::NONE: + case Property::BOOLEAN: + case Property::FLOAT: + case Property::INTEGER: + { + break; // nothing to do + } + case Property::EXTENTS: + { + mData.mExtents.member.~Extents(); + break; + } + case Property::VECTOR2: + { + mData.mVector2.member.~Vector2(); + break; + } + case Property::VECTOR3: + { + mData.mVector3.member.~Vector3(); break; } case Property::ARRAY: { - delete arrayValue; + using array = Property::Array; + mData.mArray.member.~array(); break; } case Property::MAP: { - delete mapValue; + using map = Property::Map; + mData.mMap.member.~map(); break; } - case Property::EXTENTS: + case Property::VECTOR4: { - delete extentsValue; + delete mData.mVector4.member; + break; + } + case Property::MATRIX3: + { + delete mData.mMatrix3.member; + break; + } + case Property::MATRIX: + { + delete mData.mMatrix.member; + break; + } + case Property::RECTANGLE: + { + delete mData.mRect.member; + break; + } + case Property::ROTATION: + { + delete mData.mAngleAxis.member; + break; + } + case Property::STRING: + { + delete mData.mString.member; break; } } } -public: // Data - - Type type; - union + /* + * This wrapper struct is used for + * storing Type in every union member + * and can acess it from non active member + * of the uninon without invoking UB. this is + * possible because of CIS(common initial sequence) + * http://eel.is/c++draft/class.mem#general-25 + */ + template + struct UnionMember { - int32_t integerValue; - float floatValue; - // must use pointers for any class value pre c++ 11 - Vector2* vector2Value; - Vector3* vector3Value; - Vector4* vector4Value; - Matrix3* matrix3Value; - Matrix* matrixValue; - AngleAxis* angleAxisValue; - std::string* stringValue; - Rect* rectValue; - Property::Array* arrayValue; - Property::Map* mapValue; - Extents* extentsValue; + Type type; + T member; }; -private: + /** + * Tagged union implementation. + * + * This Data union contains non trivial data + * types Map and Array, the default constructor + * and destructors are deleted by the compiler + * so we provided empty constructor and destructor + * just to pacify the compiler. + * The only job of this union to give a typed memory buffer to the + * Impl class which can construct the appropriate object + * using placement new. + * As Impl class explicitly construct the object and keeps track of the + * object it creates and then destroys them in the ~Impl() this will not leak + * any memory. + */ + union Data + { + Data() + { + } + ~Data() + { + } - // non-copyable - Impl( const Impl& ) = delete; - Impl& operator=( const Impl& ) = delete; + UnionMember mBool; + UnionMember mInt; + UnionMember mFloat; + UnionMember mExtents; + UnionMember mVector2; + UnionMember mVector3; + UnionMember mMap; + UnionMember mArray; + UnionMember mVector4; + UnionMember mMatrix3; + UnionMember mMatrix; + UnionMember mAngleAxis; + UnionMember mString; + UnionMember*> mRect; + struct + { + Type type; + } mType; + }; + Data mData; }; Property::Value::Value() -: mImpl( nullptr ) +: mImpl(nullptr) { } -Property::Value::Value( bool booleanValue ) -: mImpl( new Impl( booleanValue ) ) +Property::Value::Value(bool booleanValue) +: mImpl(new Impl(booleanValue)) { } -Property::Value::Value( float floatValue ) -: mImpl( new Impl( floatValue ) ) +Property::Value::Value(float floatValue) +: mImpl(new Impl(floatValue)) { } -Property::Value::Value( int32_t integerValue ) -: mImpl( new Impl( integerValue ) ) +Property::Value::Value(int32_t integerValue) +: mImpl(new Impl(integerValue)) { } -Property::Value::Value( const Vector2& vectorValue ) -: mImpl( new Impl( vectorValue ) ) +Property::Value::Value(const Vector2& vectorValue) +: mImpl(new Impl(vectorValue)) { } -Property::Value::Value( const Vector3& vectorValue ) -: mImpl( new Impl( vectorValue ) ) +Property::Value::Value(const Vector3& vectorValue) +: mImpl(new Impl(vectorValue)) { } -Property::Value::Value( const Vector4& vectorValue ) -: mImpl( new Impl( vectorValue ) ) +Property::Value::Value(const Vector4& vectorValue) +: mImpl(new Impl(vectorValue)) { } -Property::Value::Value( const Matrix3& matrixValue ) -: mImpl( new Impl( matrixValue ) ) +Property::Value::Value(const Matrix3& matrixValue) +: mImpl(new Impl(matrixValue)) { } -Property::Value::Value( const Matrix& matrixValue ) -: mImpl( new Impl( matrixValue ) ) +Property::Value::Value(const Matrix& matrixValue) +: mImpl(new Impl(matrixValue)) { } -Property::Value::Value( const Rect& rectValue ) -: mImpl( new Impl( rectValue ) ) +Property::Value::Value(const Rect& rectValue) +: mImpl(new Impl(rectValue)) { } -Property::Value::Value( const AngleAxis& angleAxisValue ) -: mImpl( new Impl( angleAxisValue ) ) +Property::Value::Value(const Rect& rectValue) +: mImpl(new Impl(Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height))) { } -Property::Value::Value( const Quaternion& quaternionValue ) -: mImpl( new Impl( quaternionValue ) ) +Property::Value::Value(const AngleAxis& angleAxisValue) +: mImpl(new Impl(angleAxisValue)) { } -Property::Value::Value( const std::string& stringValue ) -: mImpl( new Impl( stringValue ) ) +Property::Value::Value(const Quaternion& quaternionValue) { + AngleAxis angleAxisValue; + quaternionValue.ToAxisAngle(angleAxisValue.axis, angleAxisValue.angle); + mImpl = new Impl(std::move(angleAxisValue)); } -Property::Value::Value( const char* stringValue ) -: mImpl( nullptr ) +Property::Value::Value(std::string stringValue) +: mImpl(new Impl(std::move(stringValue))) { - if( stringValue ) // string constructor is undefined with nullptr +} + +Property::Value::Value(const char* stringValue) +: mImpl(nullptr) +{ + if(stringValue) // string constructor is undefined with nullptr { - mImpl = new Impl( std::string(stringValue) ); + mImpl = new Impl(std::string(stringValue)); } else { - mImpl = new Impl( std::string() ); + mImpl = new Impl(std::string()); } } -Property::Value::Value( Property::Array& arrayValue ) -: mImpl( new Impl( arrayValue ) ) -{ -} - -Property::Value::Value( Property::Array&& arrayValue ) -: mImpl( new Impl( std::move( 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( Property::Map&& mapValue ) -: mImpl( new Impl( std::move( mapValue ) ) ) +Property::Value::Value(const Extents& extentsValue) +: mImpl(new Impl(extentsValue)) { } -Property::Value::Value( const Extents& extentsValue ) -: mImpl( new Impl( extentsValue ) ) +Property::Value::Value(const std::initializer_list& values) +: mImpl(new Impl(Property::Map(values))) { } -Property::Value::Value( Type type ) -: mImpl( nullptr ) +Property::Value::Value(Type type) +: mImpl(nullptr) { - switch (type) + switch(type) { case Property::BOOLEAN: { - mImpl = new Impl( false ); + mImpl = new Impl(false); break; } case Property::FLOAT: { - mImpl = new Impl( 0.f ); + mImpl = new Impl(0.f); break; } case Property::INTEGER: { - mImpl = new Impl( 0 ); + mImpl = new Impl(0); break; } case Property::VECTOR2: { - mImpl = new Impl( Vector2::ZERO ); + mImpl = new Impl(Vector2::ZERO); break; } case Property::VECTOR3: { - mImpl = new Impl( Vector3::ZERO ); + mImpl = new Impl(Vector3::ZERO); break; } case Property::VECTOR4: { - mImpl = new Impl( Vector4::ZERO ); + mImpl = new Impl(Vector4::ZERO); break; } case Property::RECTANGLE: { - mImpl = new Impl( Rect(0,0,0,0) ); + mImpl = new Impl(Rect()); break; } case Property::ROTATION: { - mImpl = new Impl( AngleAxis() ); + mImpl = new Impl(AngleAxis()); break; } case Property::STRING: { - mImpl = new Impl( std::string() ); + mImpl = new Impl(std::string()); break; } case Property::MATRIX: { - mImpl = new Impl( Matrix() ); + mImpl = new Impl(Matrix()); break; } case Property::MATRIX3: { - mImpl = new Impl( Matrix3() ); + mImpl = new Impl(Matrix3()); break; } case Property::ARRAY: { - mImpl = new Impl( Property::Array() ); + mImpl = new Impl(Property::Array()); break; } case Property::MAP: { - mImpl = new Impl( Property::Map() ); + mImpl = new Impl(Property::Map()); break; } case Property::EXTENTS: { - mImpl = new Impl( Extents() ); + mImpl = new Impl(Extents()); break; } case Property::NONE: @@ -437,206 +712,51 @@ Property::Value::Value( Type type ) } } -Property::Value::Value( const Property::Value& value ) -: mImpl( nullptr ) +Property::Value::Value(const Property::Value& value) +: mImpl(nullptr) { // reuse assignment operator - operator=( value ); + operator=(value); } -Property::Value::Value( Property::Value&& value ) -: mImpl( value.mImpl ) +Property::Value::Value(Property::Value&& value) noexcept +: mImpl(value.mImpl) { value.mImpl = nullptr; } -Property::Value& Property::Value::operator=( const Property::Value& value ) +Property::Value& Property::Value::operator=(const Property::Value& value) { - if ( this == &value ) + if(this == &value) { // skip self assignment return *this; } - // if we are assigned an empty value, just drop impl - if( !value.mImpl ) - { - delete mImpl; - mImpl = nullptr; - return *this; - } - // first check if the type is the same, no need to change impl, just assign - if( mImpl && ( mImpl->type == value.mImpl->type ) ) + + if(value.mImpl) { - switch( mImpl->type ) + if(!mImpl) { - case Property::BOOLEAN: - { - mImpl->integerValue = value.mImpl->integerValue; - break; - } - case Property::FLOAT: - { - mImpl->floatValue = value.mImpl->floatValue; - break; - } - case Property::INTEGER: - { - mImpl->integerValue = value.mImpl->integerValue; - break; - } - case Property::VECTOR2: - { - *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated - break; - } - case Property::VECTOR3: - { - *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated - break; - } - case Property::VECTOR4: - { - *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated - break; - } - case Property::RECTANGLE: - { - *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated - break; - } - case Property::ROTATION: - { - *mImpl->angleAxisValue = *value.mImpl->angleAxisValue; // type cannot change in mImpl so quaternion is allocated - break; - } - case Property::STRING: - { - *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated - break; - } - case Property::MATRIX: - { - *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated - break; - } - case Property::MATRIX3: - { - *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated - break; - } - case Property::ARRAY: - { - *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated - break; - } - case Property::MAP: - { - *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated - break; - } - case Property::EXTENTS: - { - *mImpl->extentsValue = *value.mImpl->extentsValue; // type cannot change in mImpl so extents is allocated - break; - } - case Property::NONE: - { // mImpl will be a nullptr, there's no way to get to this case - } + mImpl = new Impl(); } + + *mImpl = *(value.mImpl); } else { - // different type, release old impl and create new - Impl* newImpl( nullptr ); - switch ( value.mImpl->type ) - { - case Property::BOOLEAN: - { - newImpl = new Impl( bool( value.mImpl->integerValue ) ); - break; - } - case Property::FLOAT: - { - newImpl = new Impl( value.mImpl->floatValue ); - break; - } - case Property::INTEGER: - { - newImpl = new Impl( value.mImpl->integerValue ); - break; - } - case Property::VECTOR2: - { - newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated - break; - } - case Property::VECTOR3: - { - newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated - break; - } - case Property::VECTOR4: - { - newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated - break; - } - case Property::RECTANGLE: - { - newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated - break; - } - case Property::ROTATION: - { - newImpl = new Impl( *value.mImpl->angleAxisValue ); // type cannot change in mImpl so quaternion is allocated - break; - } - case Property::MATRIX3: - { - newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated - break; - } - case Property::MATRIX: - { - newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated - break; - } - case Property::STRING: - { - newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated - break; - } - case Property::ARRAY: - { - newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated - break; - } - case Property::MAP: - { - newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated - break; - } - case Property::EXTENTS: - { - newImpl = new Impl( *value.mImpl->extentsValue ); // type cannot change in mImpl so extents is allocated - break; - } - case Property::NONE: - { // nullptr value will be used for "empty" value - } - } delete mImpl; - mImpl = newImpl; + mImpl = nullptr; } return *this; } -Property::Value& Property::Value::operator=( Property::Value&& value ) +Property::Value& Property::Value::operator=(Property::Value&& value) noexcept { - if( this != &value ) + if(this != &value) { delete mImpl; - mImpl = value.mImpl; + mImpl = value.mImpl; value.mImpl = nullptr; } @@ -650,328 +770,374 @@ Property::Value::~Value() Property::Type Property::Value::GetType() const { - Property::Type type( Property::NONE ); - if( mImpl ) - { - type = mImpl->type; - } - return type; + return mImpl ? mImpl->GetType() : Property::NONE; } -bool Property::Value::Get( bool& booleanValue ) const +bool Property::Value::Get(bool& booleanValue) const { bool converted = false; - if( mImpl && IsIntegerType( mImpl->type ) ) + if(mImpl) { - booleanValue = mImpl->integerValue; - converted = true; + if(mImpl->GetType() == BOOLEAN) + { + booleanValue = mImpl->GetBool(); + converted = true; + } + else if(mImpl->GetType() == INTEGER) + { + booleanValue = mImpl->GetInt(); + converted = true; + } } return converted; } -bool Property::Value::Get( float& floatValue ) const +bool Property::Value::Get(float& floatValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - if( mImpl->type == FLOAT ) + if(mImpl->GetType() == FLOAT) { - floatValue = mImpl->floatValue; - converted = true; + floatValue = mImpl->GetFloat(); + converted = true; } - else if( IsIntegerType( mImpl->type ) ) + else if(mImpl->GetType() == BOOLEAN) { - floatValue = static_cast< float >( mImpl->integerValue ); - converted = true; + floatValue = static_cast(mImpl->GetBool()); + converted = true; + } + else if(mImpl->GetType() == INTEGER) + { + floatValue = static_cast(mImpl->GetInt()); + converted = true; } } return converted; } -bool Property::Value::Get( int32_t& integerValue ) const +bool Property::Value::Get(int32_t& integerValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - if( IsIntegerType( mImpl->type ) ) + if(mImpl->GetType() == INTEGER) { - integerValue = mImpl->integerValue; - converted = true; + integerValue = mImpl->GetInt(); + converted = true; } - else if( mImpl->type == FLOAT ) + else if(mImpl->GetType() == BOOLEAN) { - integerValue = static_cast< int32_t >( mImpl->floatValue ); - converted = true; + integerValue = mImpl->GetBool(); + converted = true; + } + else if(mImpl->GetType() == FLOAT) + { + integerValue = static_cast(mImpl->GetFloat()); + converted = true; } } return converted; } -bool Property::Value::Get( Vector2& vectorValue ) const +bool Property::Value::Get(Vector2& vectorValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - // type cannot change in mImpl so vector is allocated - if( mImpl->type == VECTOR2 || mImpl->type == VECTOR3 || mImpl->type == VECTOR4 ) + if(mImpl->GetType() == VECTOR4) + { + vectorValue = mImpl->GetVector4(); + converted = true; + } + else if(mImpl->GetType() == VECTOR2) + { + vectorValue = mImpl->GetVector2(); + converted = true; + } + else if(mImpl->GetType() == VECTOR3) { - vectorValue = *(mImpl->vector2Value); // if Vector3 or 4 only x and y are assigned - converted = true; + vectorValue = mImpl->GetVector3(); + converted = true; } } return converted; } -bool Property::Value::Get( Vector3& vectorValue ) const +bool Property::Value::Get(Vector3& vectorValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - // type cannot change in mImpl so vector is allocated - if ( mImpl->type == VECTOR3 || mImpl->type == VECTOR4 ) + if(mImpl->GetType() == VECTOR4) { - vectorValue = *(mImpl->vector3Value); // if Vector4 only x,y,z are assigned - converted = true; + vectorValue = mImpl->GetVector4(); + converted = true; } - else if( mImpl->type == VECTOR2 ) + else if(mImpl->GetType() == VECTOR2) { - vectorValue = *(mImpl->vector2Value); - converted = true; + vectorValue = mImpl->GetVector2(); + converted = true; + } + else if(mImpl->GetType() == VECTOR3) + { + vectorValue = mImpl->GetVector3(); + converted = true; } } return converted; } -bool Property::Value::Get( Vector4& vectorValue ) const +bool Property::Value::Get(Vector4& vectorValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - if( mImpl->type == VECTOR4 ) // type cannot change in mImpl so vector is allocated + if(mImpl->GetType() == VECTOR4) { - vectorValue = *(mImpl->vector4Value); - converted = true; + vectorValue = mImpl->GetVector4(); + converted = true; } - else if( mImpl->type == VECTOR2 ) + else if(mImpl->GetType() == VECTOR2) { - vectorValue = *(mImpl->vector2Value); - converted = true; + vectorValue = mImpl->GetVector2(); + converted = true; } - else if( mImpl->type == VECTOR3 ) + else if(mImpl->GetType() == VECTOR3) { - vectorValue = *(mImpl->vector3Value); - converted = true; + vectorValue = mImpl->GetVector3(); + converted = true; } } return converted; } -bool Property::Value::Get( Matrix3& matrixValue ) const +bool Property::Value::Get(Matrix3& matrixValue) const { bool converted = false; - if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated + if(mImpl && (mImpl->GetType() == MATRIX3)) { - matrixValue = *(mImpl->matrix3Value); - converted = true; + matrixValue = mImpl->GetMatrix3(); + converted = true; } return converted; } -bool Property::Value::Get( Matrix& matrixValue ) const +bool Property::Value::Get(Matrix& matrixValue) const { bool converted = false; - if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated + if(mImpl && (mImpl->GetType() == MATRIX)) { - matrixValue = *(mImpl->matrixValue); - converted = true; + matrixValue = mImpl->GetMatrix(); + converted = true; } return converted; } -bool Property::Value::Get( Rect& rectValue ) const +bool Property::Value::Get(Rect& rectValue) const { bool converted = false; - if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated + if(mImpl && (mImpl->GetType() == RECTANGLE)) { - rectValue = *(mImpl->rectValue); + rectValue = mImpl->GetRect(); converted = true; } return converted; } -bool Property::Value::Get( AngleAxis& angleAxisValue ) const +bool Property::Value::Get(AngleAxis& angleAxisValue) const { bool converted = false; - if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated + if(mImpl && (mImpl->GetType() == ROTATION)) { - angleAxisValue = *(mImpl->angleAxisValue); - converted = true; + angleAxisValue = mImpl->GetAngleAxis(); + converted = true; } return converted; } -bool Property::Value::Get( Quaternion& quaternionValue ) const +bool Property::Value::Get(Quaternion& quaternionValue) const { bool converted = false; - if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so angleAxis is allocated + if(mImpl && (mImpl->GetType() == ROTATION)) { - quaternionValue = Quaternion(mImpl->angleAxisValue->angle, mImpl->angleAxisValue->axis ); - converted = true; + auto& obj = mImpl->GetAngleAxis(); + quaternionValue = Quaternion(obj.angle, obj.axis); + converted = true; } return converted; } -bool Property::Value::Get( std::string& stringValue ) const +bool Property::Value::Get(std::string& stringValue) const { bool converted = false; - if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated + if(mImpl && (mImpl->GetType() == STRING)) { - stringValue.assign( *(mImpl->stringValue) ); + stringValue.assign(mImpl->GetString()); converted = true; } return converted; } -bool Property::Value::Get( Property::Array& arrayValue ) const +bool Property::Value::Get(Property::Array& arrayValue) const { bool converted = false; - if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated + if(mImpl && (mImpl->GetType() == ARRAY)) { - arrayValue = *(mImpl->arrayValue); - converted = true; + arrayValue = mImpl->GetArray(); + converted = true; } return converted; } -bool Property::Value::Get( Property::Map& mapValue ) const +bool Property::Value::Get(Property::Map& mapValue) const { bool converted = false; - if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated + if(mImpl && (mImpl->GetType() == MAP)) { - mapValue = *(mImpl->mapValue); + mapValue = mImpl->GetMap(); converted = true; } return converted; } -Property::Array* Property::Value::GetArray() const +Property::Array const* Property::Value::GetArray() const +{ + if(mImpl && (mImpl->GetType() == ARRAY)) + { + return mImpl->GetArrayPtr(); + } + return nullptr; +} + +Property::Array* Property::Value::GetArray() { Property::Array* array = nullptr; - if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated + if(mImpl && (mImpl->GetType() == ARRAY)) // type cannot change in mImpl so array is allocated { - array = mImpl->arrayValue; + array = mImpl->GetArrayPtr(); } return array; } -Property::Map* Property::Value::GetMap() const +Property::Map const* Property::Value::GetMap() const { Property::Map* map = nullptr; - if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated + if(mImpl && (mImpl->GetType() == MAP)) // type cannot change in mImpl so map is allocated { - map = mImpl->mapValue; + map = mImpl->GetMapPtr(); } return map; } -bool Property::Value::Get( Extents& extentsValue ) const +Property::Map* Property::Value::GetMap() +{ + if(mImpl && (mImpl->GetType() == MAP)) + { + return mImpl->GetMapPtr(); + } + return nullptr; +} + +bool Property::Value::Get(Extents& extentsValue) const { bool converted = false; - if( mImpl ) + if(mImpl) { - if( mImpl->type == EXTENTS ) + if(mImpl->GetType() == EXTENTS) { - extentsValue = *(mImpl->extentsValue); - converted = true; + extentsValue = mImpl->GetExtents(); + converted = true; } - else if( mImpl->type == VECTOR4 ) + else if(mImpl->GetType() == VECTOR4) { - extentsValue.start = static_cast< uint16_t >( mImpl->vector4Value->x ); - extentsValue.end = static_cast< uint16_t >( mImpl->vector4Value->y ); - extentsValue.top = static_cast< uint16_t >( mImpl->vector4Value->z ); - extentsValue.bottom = static_cast< uint16_t >( mImpl->vector4Value->w ); - converted = true; + auto& obj = mImpl->GetVector4(); + extentsValue.start = static_cast(obj.x); + extentsValue.end = static_cast(obj.y); + extentsValue.top = static_cast(obj.z); + extentsValue.bottom = static_cast(obj.w); + converted = true; } } return converted; } -std::ostream& operator<<( std::ostream& stream, const Property::Value& value ) +std::ostream& operator<<(std::ostream& stream, const Property::Value& value) { - if( value.mImpl ) + if(value.mImpl) { - const Property::Value::Impl& impl( *value.mImpl ); + auto obj = value.mImpl; - switch( impl.type ) + switch(obj->GetType()) { case Dali::Property::BOOLEAN: { - stream << impl.integerValue; + stream << obj->GetBool(); break; } case Dali::Property::FLOAT: { - stream << impl.floatValue; + stream << obj->GetFloat(); break; } case Dali::Property::INTEGER: { - stream << impl.integerValue; - break; + stream << obj->GetInt(); + break; } case Dali::Property::VECTOR2: { - stream << *impl.vector2Value; + stream << obj->GetVector2(); break; } case Dali::Property::VECTOR3: { - stream << *impl.vector3Value; + stream << obj->GetVector3(); break; } case Dali::Property::VECTOR4: { - stream << *impl.vector4Value; + stream << obj->GetVector4(); break; } case Dali::Property::MATRIX3: { - stream << *impl.matrix3Value; + stream << obj->GetMatrix3(); break; } case Dali::Property::MATRIX: { - stream << *impl.matrixValue; + stream << obj->GetMatrix(); break; } case Dali::Property::RECTANGLE: { - stream << *impl.rectValue; + stream << obj->GetRect(); break; } case Dali::Property::ROTATION: { - stream << *impl.angleAxisValue; + stream << obj->GetAngleAxis(); break; } case Dali::Property::STRING: { - stream << *impl.stringValue; + stream << obj->GetString(); break; } case Dali::Property::ARRAY: { - stream << *(value.GetArray()); + stream << obj->GetArray(); break; } case Dali::Property::MAP: { - stream << *(value.GetMap()); + stream << obj->GetMap(); break; } case Dali::Property::EXTENTS: { - stream << *impl.extentsValue; + stream << obj->GetExtents(); break; } case Dali::Property::NONE: @@ -986,5 +1152,4 @@ std::ostream& operator<<( std::ostream& stream, const Property::Value& value ) return stream; } - } // namespace Dali