/*
- * Copyright (c) 2014 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.
// CLASS HEADER
#include <dali/public-api/object/property-value.h>
+// EXTERNAL INCLUDES
+#include <ostream>
+
// INTERNAL INCLUDES
-#include <dali/public-api/object/any.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
#include <dali/public-api/math/angle-axis.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/quaternion.h>
#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/rect.h>
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/math/vector3.h>
#include <dali/public-api/math/vector4.h>
-#include <dali/public-api/math/matrix3.h>
-#include <dali/public-api/math/matrix.h>
-#include <dali/public-api/math/rect.h>
-#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/object/property-array.h>
#include <dali/public-api/object/property-map.h>
#include <dali/public-api/object/property-types.h>
-#include <dali/integration-api/debug.h>
namespace Dali
{
struct Property::Value::Impl
{
+ ~Impl()
+ {
+ // Destroy the current object stored in Data union memory.
+ Destroy();
+ }
+
+ Impl(const Impl&) = delete;
+
+ Impl(Impl&&) = delete;
+
+ Impl& operator=(Impl&&) = delete;
+
Impl()
- : mType( Property::NONE )
{
+ static_assert(sizeof(Impl) == 16);
+ static_assert(alignof(Impl) == alignof(Impl*));
+
+ SetType(Property::NONE);
}
- Impl(bool boolValue)
- : mType( PropertyTypes::Get<bool>() ),
- mValue( boolValue )
+ Impl(bool booleanValue)
{
+ SetType(Property::BOOLEAN);
+ mData.mBool.member = booleanValue;
}
Impl(float floatValue)
- : mType( PropertyTypes::Get<float>() ),
- mValue( floatValue )
{
+ SetType(Property::FLOAT);
+ mData.mFloat.member = floatValue;
+ }
+
+ Impl(int32_t integerValue)
+ {
+ SetType(Property::INTEGER);
+ mData.mInt.member = integerValue;
+ }
+
+ Impl(Vector2 vectorValue)
+ {
+ SetType(Property::VECTOR2);
+ ConstructInplace(mData.mVector2.member, std::move(vectorValue));
+ }
+
+ Impl(Vector3 vectorValue)
+ {
+ SetType(Property::VECTOR3);
+ ConstructInplace(mData.mVector3.member, std::move(vectorValue));
+ }
+
+ Impl(Extents extentsValue)
+ {
+ SetType(Property::EXTENTS);
+ ConstructInplace(mData.mExtents.member, std::move(extentsValue));
+ }
+
+ Impl(Property::Map mapValue)
+ {
+ SetType(Property::MAP);
+ ConstructInplace(mData.mMap.member, std::move(mapValue));
+ }
+
+ Impl(Property::Array arrayValue)
+ {
+ SetType(Property::ARRAY);
+ ConstructInplace(mData.mArray.member, std::move(arrayValue));
+ }
+
+ Impl(std::string stringValue)
+ {
+ SetType(Property::STRING);
+ mData.mString.member = new std::string(std::move(stringValue));
+ }
+
+ Impl(Rect<int32_t> rectValue)
+ {
+ SetType(Property::RECTANGLE);
+ mData.mRect.member = new Rect<int32_t>(std::move(rectValue));
+ }
+
+ Impl(Vector4 vectorValue)
+ {
+ SetType(Property::VECTOR4);
+ mData.mVector4.member = new Vector4(std::move(vectorValue));
+ }
+
+ 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
+ {
+ 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;
}
- Impl(int integerValue)
- : mType( PropertyTypes::Get<int>() ),
- mValue( integerValue )
+ const Vector3& GetVector3() const
{
+ return mData.mVector3.member;
}
- Impl(unsigned int unsignedIntegerValue)
- : mType( PropertyTypes::Get<unsigned int>() ),
- mValue( unsignedIntegerValue )
+ const Property::Map& GetMap() const
{
+ return mData.mMap.member;
}
- Impl(const Vector2& vectorValue)
- : mType( PropertyTypes::Get<Vector2>() ),
- mValue( vectorValue )
+ const Property::Array& GetArray() const
{
+ return mData.mArray.member;
}
- Impl(const Vector3& vectorValue)
- : mType( PropertyTypes::Get<Vector3>() ),
- mValue( vectorValue )
+ const Vector4& GetVector4() const
{
+ return *(mData.mVector4.member);
}
- Impl(const Vector4& vectorValue)
- : mType( PropertyTypes::Get<Vector4>() ),
- mValue( vectorValue )
+ const Matrix3& GetMatrix3() const
{
+ return *(mData.mMatrix3.member);
}
- Impl(const Matrix3& matrixValue)
- : mType(PropertyTypes::Get<Matrix3>()),
- mValue(matrixValue)
+ const Matrix& GetMatrix() const
{
+ return *(mData.mMatrix.member);
}
- Impl(const Matrix& matrixValue)
- : mType(PropertyTypes::Get<Matrix>()),
- mValue(matrixValue)
+ const AngleAxis& GetAngleAxis() const
{
+ return *(mData.mAngleAxis.member);
}
- Impl(const AngleAxis& angleAxisValue)
- : mType( PropertyTypes::Get<AngleAxis>() ),
- mValue( angleAxisValue )
+ const std::string& GetString() const
{
+ return *(mData.mString.member);
}
- Impl(const Quaternion& quaternionValue)
- : mType( PropertyTypes::Get<Quaternion>() ),
- mValue( quaternionValue )
+ const Rect<int32_t>& GetRect() const
{
+ return *(mData.mRect.member);
}
- Impl(const std::string& stringValue)
- : mType( PropertyTypes::Get<std::string>() ),
- mValue( stringValue )
+ 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)
+ {
+ Destroy();
+ SetType(other.GetType());
+ }
+
+ switch(GetType())
+ {
+ case Property::NONE:
+ {
+ 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::EXTENTS:
+ {
+ 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:
+ {
+ 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:
+ {
+ if(isSameType)
+ {
+ *mData.mVector4.member = other.GetVector4();
+ }
+ else
+ {
+ mData.mVector4.member = new Vector4(other.GetVector4());
+ }
+ break;
+ }
+ case Property::MATRIX3:
+ {
+ if(isSameType)
+ {
+ *mData.mMatrix3.member = other.GetMatrix3();
+ }
+ else
+ {
+ mData.mMatrix3.member = new Matrix3(other.GetMatrix3());
+ }
+ break;
+ }
+ case Property::MATRIX:
+ {
+ if(isSameType)
+ {
+ *mData.mMatrix.member = other.GetMatrix();
+ }
+ else
+ {
+ mData.mMatrix.member = new Matrix(other.GetMatrix());
+ }
+ break;
+ }
+ case Property::RECTANGLE:
+ {
+ if(isSameType)
+ {
+ *mData.mRect.member = other.GetRect();
+ }
+ else
+ {
+ mData.mRect.member = new Rect<int32_t>(other.GetRect());
+ }
+ break;
+ }
+ case Property::ROTATION:
+ {
+ if(isSameType)
+ {
+ *mData.mAngleAxis.member = other.GetAngleAxis();
+ }
+ else
+ {
+ mData.mAngleAxis.member = new AngleAxis(other.GetAngleAxis());
+ }
+ break;
+ }
+ case Property::STRING:
+ {
+ if(isSameType)
+ {
+ *mData.mString.member = other.GetString();
+ }
+ else
+ {
+ mData.mString.member = new std::string(other.GetString());
+ }
+ break;
+ }
+ }
+ return *this;
}
- Impl(const Rect<int>& rect)
- : mType( PropertyTypes::Get<Rect<int> >() ),
- mValue( rect )
+private:
+ void SetType(Type typeValue)
{
+ mData.mType.type = typeValue;
}
- Impl(Property::Map container)
- : mType( PropertyTypes::Get<Property::Map >() ),
- mValue( container )
+ /**
+ * 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<typename Tp>
+ void ConstructInplace(Tp& member, Tp&& val)
{
+ new(&member) Tp(std::forward<Tp>(val));
}
- Impl(Property::Array container)
- : mType( PropertyTypes::Get<Property::Array >() ),
- mValue( container )
+ /**
+ * 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:
+ {
+ using array = Property::Array;
+ mData.mArray.member.~array();
+ break;
+ }
+ case Property::MAP:
+ {
+ using map = Property::Map;
+ mData.mMap.member.~map();
+ break;
+ }
+ case Property::VECTOR4:
+ {
+ 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;
+ }
+ }
}
- Type mType;
+ /*
+ * 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<typename T>
+ struct UnionMember
+ {
+ Type type;
+ T member;
+ };
+
+ /**
+ * 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()
+ {
+ }
+
+ UnionMember<bool> mBool;
+ UnionMember<int32_t> mInt;
+ UnionMember<float> mFloat;
+ UnionMember<Extents> mExtents;
+ UnionMember<Vector2> mVector2;
+ UnionMember<Vector3> mVector3;
+ UnionMember<Property::Map> mMap;
+ UnionMember<Property::Array> mArray;
+ UnionMember<Vector4*> mVector4;
+ UnionMember<Matrix3*> mMatrix3;
+ UnionMember<Matrix*> mMatrix;
+ UnionMember<AngleAxis*> mAngleAxis;
+ UnionMember<std::string*> mString;
+ UnionMember<Rect<int32_t>*> mRect;
+ struct
+ {
+ Type type;
+ } mType;
+ };
- typedef Any AnyValue;
- AnyValue mValue;
+ Data mData;
};
Property::Value::Value()
-: mImpl( NULL )
+: mImpl(nullptr)
{
- mImpl = new Impl();
}
-Property::Value::Value(bool boolValue)
-: mImpl( NULL )
+Property::Value::Value(bool booleanValue)
+: mImpl(new Impl(booleanValue))
{
- mImpl = new Impl( boolValue );
}
Property::Value::Value(float floatValue)
-: mImpl( NULL )
-{
- mImpl = new Impl( floatValue );
-}
-
-Property::Value::Value(int integerValue)
-: mImpl( NULL )
+: mImpl(new Impl(floatValue))
{
- mImpl = new Impl( integerValue );
}
-Property::Value::Value(unsigned int unsignedIntegerValue)
-: mImpl( NULL )
+Property::Value::Value(int32_t integerValue)
+: mImpl(new Impl(integerValue))
{
- mImpl = new Impl( unsignedIntegerValue );
}
Property::Value::Value(const Vector2& vectorValue)
-: mImpl( NULL )
+: mImpl(new Impl(vectorValue))
{
- mImpl = new Impl( vectorValue );
}
Property::Value::Value(const Vector3& vectorValue)
-: mImpl( NULL )
+: mImpl(new Impl(vectorValue))
{
- mImpl = new Impl( vectorValue );
}
Property::Value::Value(const Vector4& vectorValue)
-: mImpl( NULL )
+: mImpl(new Impl(vectorValue))
{
- mImpl = new Impl( vectorValue );
}
Property::Value::Value(const Matrix3& matrixValue)
-: mImpl( NULL )
+: mImpl(new Impl(matrixValue))
{
- mImpl = new Impl( matrixValue );
}
Property::Value::Value(const Matrix& matrixValue)
-: mImpl( NULL )
+: mImpl(new Impl(matrixValue))
{
- mImpl = new Impl( matrixValue );
}
-Property::Value::Value(const Rect<int>& rect)
-: mImpl( NULL )
+Property::Value::Value(const Rect<int32_t>& rectValue)
+: mImpl(new Impl(rectValue))
+{
+}
+
+Property::Value::Value(const Rect<float>& rectValue)
+: mImpl(new Impl(Vector4(rectValue.x, rectValue.y, rectValue.width, rectValue.height)))
{
- mImpl = new Impl( rect );
}
Property::Value::Value(const AngleAxis& angleAxisValue)
-: mImpl( NULL )
+: mImpl(new Impl(angleAxisValue))
{
- mImpl = new Impl( angleAxisValue );
}
Property::Value::Value(const Quaternion& quaternionValue)
{
- mImpl = new Impl( quaternionValue );
+ AngleAxis angleAxisValue;
+ quaternionValue.ToAxisAngle(angleAxisValue.axis, angleAxisValue.angle);
+ mImpl = new Impl(std::move(angleAxisValue));
}
-Property::Value::Value(const std::string& stringValue)
+Property::Value::Value(std::string stringValue)
+: mImpl(new Impl(std::move(stringValue)))
{
- mImpl = new Impl( stringValue );
}
-Property::Value::Value(const char *stringValue)
+Property::Value::Value(const char* stringValue)
+: mImpl(nullptr)
{
- mImpl = new Impl( std::string(stringValue) );
+ if(stringValue) // string constructor is undefined with nullptr
+ {
+ mImpl = new Impl(std::string(stringValue));
+ }
+ else
+ {
+ mImpl = new Impl(std::string());
+ }
}
-Property::Value::Value(Property::Array &arrayValue)
+Property::Value::Value(Property::Array arrayValue)
+: mImpl(new Impl(std::move(arrayValue)))
{
- mImpl = new Impl( arrayValue );
}
-Property::Value::Value(Property::Map &mapValue)
+Property::Value::Value(Property::Map mapValue)
+: mImpl(new Impl(std::move(mapValue)))
{
- mImpl = new Impl( mapValue );
}
+Property::Value::Value(const Extents& extentsValue)
+: mImpl(new Impl(extentsValue))
+{
+}
-Property::Value::~Value()
+Property::Value::Value(const std::initializer_list<KeyValuePair>& values)
+: mImpl(new Impl(Property::Map(values)))
{
- delete mImpl;
}
-Property::Value::Value(const Value& value)
+Property::Value::Value(Type type)
+: mImpl(nullptr)
{
- switch (value.GetType())
+ switch(type)
{
case Property::BOOLEAN:
{
- mImpl = new Impl( value.Get<bool>() );
+ mImpl = new Impl(false);
break;
}
-
case Property::FLOAT:
{
- mImpl = new Impl( value.Get<float>() );
+ mImpl = new Impl(0.f);
break;
}
-
case Property::INTEGER:
{
- mImpl = new Impl( value.Get<int>() );
- break;
- }
-
- case Property::UNSIGNED_INTEGER:
- {
- mImpl = new Impl( value.Get<unsigned int>() );
+ mImpl = new Impl(0);
break;
}
-
case Property::VECTOR2:
{
- mImpl = new Impl( value.Get<Vector2>() );
+ mImpl = new Impl(Vector2::ZERO);
break;
}
-
case Property::VECTOR3:
{
- mImpl = new Impl( value.Get<Vector3>() );
+ mImpl = new Impl(Vector3::ZERO);
break;
}
-
case Property::VECTOR4:
{
- mImpl = new Impl( value.Get<Vector4>() );
+ mImpl = new Impl(Vector4::ZERO);
break;
}
-
case Property::RECTANGLE:
{
- mImpl = new Impl( value.Get<Rect<int> >() );
+ mImpl = new Impl(Rect<int32_t>());
break;
}
-
case Property::ROTATION:
{
- mImpl = new Impl( value.Get<Quaternion>() );
+ mImpl = new Impl(AngleAxis());
break;
}
-
- case Property::MATRIX3:
+ case Property::STRING:
{
- mImpl = new Impl( value.Get<Matrix3>());
+ mImpl = new Impl(std::string());
break;
}
-
case Property::MATRIX:
{
- mImpl = new Impl( value.Get<Matrix>());
+ mImpl = new Impl(Matrix());
break;
}
-
- case Property::STRING:
+ case Property::MATRIX3:
{
- mImpl = new Impl( value.Get<std::string>() );
+ mImpl = new Impl(Matrix3());
+ break;
+ }
+ case Property::ARRAY:
+ {
+ mImpl = new Impl(Property::Array());
break;
}
-
case Property::MAP:
{
- mImpl = new Impl( value.Get<Property::Map>() );
+ mImpl = new Impl(Property::Map());
break;
}
-
- case Property::ARRAY:
+ case Property::EXTENTS:
{
- mImpl = new Impl( value.Get<Property::Array>() );
+ mImpl = new Impl(Extents());
break;
}
-
- case Property::NONE: // fall
- default:
+ case Property::NONE:
{
- mImpl = new Impl();
+ // No need to create an Impl
break;
}
}
}
-Property::Value::Value(Type type)
+Property::Value::Value(const Property::Value& value)
+: mImpl(nullptr)
+{
+ // reuse assignment operator
+ operator=(value);
+}
+
+Property::Value::Value(Property::Value&& value) noexcept
+: mImpl(value.mImpl)
+{
+ value.mImpl = nullptr;
+}
+
+Property::Value& Property::Value::operator=(const Property::Value& value)
{
- switch (type)
+ if(this == &value)
{
- case Property::BOOLEAN:
- {
- mImpl = new Impl( false );
- break;
- }
+ // skip self assignment
+ return *this;
+ }
- case Property::FLOAT:
+ if(value.mImpl)
+ {
+ if(!mImpl)
{
- mImpl = new Impl( 0.f );
- break;
+ mImpl = new Impl();
}
- case Property::INTEGER:
- {
- mImpl = new Impl( 0 );
- break;
- }
+ *mImpl = *(value.mImpl);
+ }
+ else
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
- case Property::UNSIGNED_INTEGER:
- {
- mImpl = new Impl( 0U );
- break;
- }
+ return *this;
+}
- case Property::VECTOR2:
- {
- mImpl = new Impl( Vector2::ZERO );
- break;
- }
+Property::Value& Property::Value::operator=(Property::Value&& value) noexcept
+{
+ if(this != &value)
+ {
+ delete mImpl;
+ mImpl = value.mImpl;
+ value.mImpl = nullptr;
+ }
- case Property::VECTOR3:
- {
- mImpl = new Impl( Vector3::ZERO );
- break;
- }
+ return *this;
+}
- case Property::VECTOR4:
- {
- mImpl = new Impl( Vector4::ZERO );
- break;
- }
+Property::Value::~Value()
+{
+ delete mImpl;
+}
- case Property::RECTANGLE:
- {
- mImpl = new Impl( Rect<int>(0,0,0,0) );
- break;
- }
+Property::Type Property::Value::GetType() const
+{
+ return mImpl ? mImpl->GetType() : Property::NONE;
+}
- case Property::ROTATION:
+bool Property::Value::Get(bool& booleanValue) const
+{
+ bool converted = false;
+ if(mImpl)
+ {
+ if(mImpl->GetType() == BOOLEAN)
{
- mImpl = new Impl( Quaternion(0.f, Vector4::YAXIS) );
- break;
+ booleanValue = mImpl->GetBool();
+ converted = true;
}
-
- case Property::STRING:
+ else if(mImpl->GetType() == INTEGER)
{
- mImpl = new Impl( std::string() );
- break;
+ booleanValue = mImpl->GetInt();
+ converted = true;
}
+ }
+ return converted;
+}
- case Property::MAP:
+bool Property::Value::Get(float& floatValue) const
+{
+ bool converted = false;
+ if(mImpl)
+ {
+ if(mImpl->GetType() == FLOAT)
{
- mImpl = new Impl( Property::Map() );
- break;
+ floatValue = mImpl->GetFloat();
+ converted = true;
}
-
- case Property::MATRIX:
+ else if(mImpl->GetType() == BOOLEAN)
{
- mImpl = new Impl( Matrix() );
- break;
+ floatValue = static_cast<float>(mImpl->GetBool());
+ converted = true;
}
-
- case Property::MATRIX3:
+ else if(mImpl->GetType() == INTEGER)
{
- mImpl = new Impl( Matrix3() );
- break;
- }
-
- case Property::ARRAY:
- {
- mImpl = new Impl( Property::Array() );
- break;
- }
-
- case Property::NONE: // fall
- default:
- {
- mImpl = new Impl();
- break;
+ floatValue = static_cast<float>(mImpl->GetInt());
+ converted = true;
}
}
+ return converted;
}
-Property::Value& Property::Value::operator=(const Property::Value& value)
+bool Property::Value::Get(int32_t& integerValue) const
{
- if (this == &value)
- {
- // skip self assignment
- return *this;
- }
-
- mImpl->mType = value.GetType();
-
- switch (mImpl->mType)
+ bool converted = false;
+ if(mImpl)
{
- case Property::BOOLEAN:
+ if(mImpl->GetType() == INTEGER)
{
- mImpl->mValue = value.Get<bool>();
- break;
+ integerValue = mImpl->GetInt();
+ converted = true;
}
-
- case Property::FLOAT:
+ else if(mImpl->GetType() == BOOLEAN)
{
- mImpl->mValue = value.Get<float>();
- break;
+ integerValue = mImpl->GetBool();
+ converted = true;
}
-
- case Property::INTEGER:
+ else if(mImpl->GetType() == FLOAT)
{
- mImpl->mValue = value.Get<int>();
- break;
- }
-
- case Property::UNSIGNED_INTEGER:
- {
- mImpl->mValue = value.Get<unsigned int>();
- break;
- }
-
- case Property::VECTOR2:
- {
- mImpl->mValue = value.Get<Vector2>();
- break;
+ integerValue = static_cast<int32_t>(mImpl->GetFloat());
+ converted = true;
}
+ }
+ return converted;
+}
- case Property::VECTOR3:
+bool Property::Value::Get(Vector2& vectorValue) const
+{
+ bool converted = false;
+ if(mImpl)
+ {
+ if(mImpl->GetType() == VECTOR4)
{
- mImpl->mValue = value.Get<Vector3>();
- break;
+ vectorValue = mImpl->GetVector4();
+ converted = true;
}
-
- case Property::VECTOR4:
+ else if(mImpl->GetType() == VECTOR2)
{
- mImpl->mValue = value.Get<Vector4>();
- break;
+ vectorValue = mImpl->GetVector2();
+ converted = true;
}
-
- case Property::RECTANGLE:
+ else if(mImpl->GetType() == VECTOR3)
{
- mImpl->mValue = value.Get<Rect<int> >();
- break;
- }
-
- case Property::ROTATION:
- {
- mImpl->mValue = value.Get<Quaternion>();
- break;
+ vectorValue = mImpl->GetVector3();
+ converted = true;
}
+ }
+ return converted;
+}
- case Property::STRING:
+bool Property::Value::Get(Vector3& vectorValue) const
+{
+ bool converted = false;
+ if(mImpl)
+ {
+ if(mImpl->GetType() == VECTOR4)
{
- mImpl->mValue = value.Get<std::string>();
- break;
+ vectorValue = mImpl->GetVector4();
+ converted = true;
}
-
- case Property::MATRIX:
+ else if(mImpl->GetType() == VECTOR2)
{
- mImpl->mValue = value.Get<Matrix>();
- break;
+ vectorValue = mImpl->GetVector2();
+ converted = true;
}
-
- case Property::MATRIX3:
+ else if(mImpl->GetType() == VECTOR3)
{
- mImpl->mValue = value.Get<Matrix3>();
- break;
+ vectorValue = mImpl->GetVector3();
+ converted = true;
}
+ }
+ return converted;
+}
- case Property::MAP:
+bool Property::Value::Get(Vector4& vectorValue) const
+{
+ bool converted = false;
+ if(mImpl)
+ {
+ if(mImpl->GetType() == VECTOR4)
{
- mImpl->mValue = value.Get<Property::Map>();
- break;
+ vectorValue = mImpl->GetVector4();
+ converted = true;
}
-
- case Property::ARRAY:
+ else if(mImpl->GetType() == VECTOR2)
{
- mImpl->mValue = value.Get<Property::Array>();
- break;
+ vectorValue = mImpl->GetVector2();
+ converted = true;
}
-
- case Property::NONE: // fall
- default:
+ else if(mImpl->GetType() == VECTOR3)
{
- mImpl->mValue = Impl::AnyValue(0);
- break;
+ vectorValue = mImpl->GetVector3();
+ converted = true;
}
}
-
- return *this;
-}
-
-Property::Type Property::Value::GetType() const
-{
- return mImpl->mType;
-}
-
-void Property::Value::Get(bool& boolValue) const
-{
- DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking
-
- boolValue = AnyCast<bool>(mImpl->mValue);
-}
-
-void Property::Value::Get(float& floatValue) const
-{
- DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" );
-
- floatValue = AnyCast<float>(mImpl->mValue);
-}
-
-void Property::Value::Get(int& integerValue) const
-{
- DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" );
-
- integerValue = AnyCast<int>(mImpl->mValue);
-}
-
-void Property::Value::Get(unsigned int& unsignedIntegerValue) const
-{
- DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" );
-
- unsignedIntegerValue = AnyCast<unsigned int>(mImpl->mValue);
+ return converted;
}
-void Property::Value::Get(Vector2& vectorValue) const
+bool Property::Value::Get(Matrix3& matrixValue) const
{
- DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" );
-
- vectorValue = AnyCast<Vector2>(mImpl->mValue);
-}
-
-void Property::Value::Get(Vector3& vectorValue) const
-{
- DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" );
-
- vectorValue = AnyCast<Vector3>(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == MATRIX3))
+ {
+ matrixValue = mImpl->GetMatrix3();
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(Vector4& vectorValue) const
+bool Property::Value::Get(Matrix& matrixValue) const
{
- DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" );
-
- vectorValue = AnyCast<Vector4>(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == MATRIX))
+ {
+ matrixValue = mImpl->GetMatrix();
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(Matrix3& matrixValue) const
+bool Property::Value::Get(Rect<int32_t>& rectValue) const
{
- DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" );
- matrixValue = AnyCast<Matrix3>(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == RECTANGLE))
+ {
+ rectValue = mImpl->GetRect();
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(Matrix& matrixValue) const
+bool Property::Value::Get(AngleAxis& angleAxisValue) const
{
- DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" );
- matrixValue = AnyCast<Matrix>(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == ROTATION))
+ {
+ angleAxisValue = mImpl->GetAngleAxis();
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(Rect<int>& rect) const
+bool Property::Value::Get(Quaternion& quaternionValue) const
{
- DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" );
-
- rect = AnyCast<Rect<int> >(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == ROTATION))
+ {
+ auto& obj = mImpl->GetAngleAxis();
+ quaternionValue = Quaternion(obj.angle, obj.axis);
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(AngleAxis& angleAxisValue) const
+bool Property::Value::Get(std::string& stringValue) const
{
- DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" );
-
- // Orientations have two representations
- DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
- typeid(AngleAxis) == mImpl->mValue.GetType() );
-
- if ( typeid(Quaternion) == mImpl->mValue.GetType() )
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == STRING))
{
- Quaternion quaternion = AnyCast<Quaternion>(mImpl->mValue);
-
- Radian angleRadians(0.0f);
- quaternion.ToAxisAngle( angleAxisValue.axis, angleRadians );
- angleAxisValue.angle = angleRadians;
- }
- else
- {
- angleAxisValue = AnyCast<AngleAxis>(mImpl->mValue);
+ stringValue.assign(mImpl->GetString());
+ converted = true;
}
+ return converted;
}
-void Property::Value::Get(Quaternion& quaternionValue) const
+bool Property::Value::Get(Property::Array& arrayValue) const
{
- DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" );
-
- // Orientations have two representations
- DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() ||
- typeid(AngleAxis) == mImpl->mValue.GetType() );
-
- if ( typeid(Quaternion) == mImpl->mValue.GetType() )
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == ARRAY))
{
- quaternionValue = AnyCast<Quaternion>(mImpl->mValue);
- }
- else
- {
- AngleAxis angleAxis = AnyCast<AngleAxis>(mImpl->mValue);
-
- quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis );
+ arrayValue = mImpl->GetArray();
+ converted = true;
}
+ return converted;
}
-void Property::Value::Get(std::string &out) const
+bool Property::Value::Get(Property::Map& mapValue) const
{
- DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid");
-
- out = AnyCast<std::string>(mImpl->mValue);
+ bool converted = false;
+ if(mImpl && (mImpl->GetType() == MAP))
+ {
+ mapValue = mImpl->GetMap();
+ converted = true;
+ }
+ return converted;
}
-void Property::Value::Get(Property::Array &out) const
+Property::Array const* Property::Value::GetArray() const
{
- DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
-
- out = AnyCast<Property::Array>(mImpl->mValue);
+ if(mImpl && (mImpl->GetType() == ARRAY))
+ {
+ return mImpl->GetArrayPtr();
+ }
+ return nullptr;
}
-void Property::Value::Get(Property::Map &out) const
+Property::Array* Property::Value::GetArray()
{
- DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
-
- out = AnyCast<Property::Map>(mImpl->mValue);
+ Property::Array* array = nullptr;
+ if(mImpl && (mImpl->GetType() == ARRAY)) // type cannot change in mImpl so array is allocated
+ {
+ array = mImpl->GetArrayPtr();
+ }
+ return array;
}
-Property::Value& Property::Value::GetValue(const std::string& key) const
+Property::Map const* Property::Value::GetMap() const
{
- DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
-
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
-
- DALI_ASSERT_DEBUG(container);
-
- if(container)
+ Property::Map* map = nullptr;
+ if(mImpl && (mImpl->GetType() == MAP)) // type cannot change in mImpl so map is allocated
{
- Property::Value* value = container->Find( key );
- if ( value )
- {
- return *value;
- }
+ map = mImpl->GetMapPtr();
}
-
- DALI_LOG_WARNING("Cannot find property map key %s", key.c_str());
- DALI_ASSERT_ALWAYS(!"Cannot find property map key");
+ return map;
}
-bool Property::Value::HasKey(const std::string& key) const
+Property::Map* Property::Value::GetMap()
{
- bool has = false;
-
- if( Property::MAP == GetType() )
+ if(mImpl && (mImpl->GetType() == MAP))
{
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
-
- DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
-
- if(container)
- {
- Property::Value* value = container->Find( key );
- if ( value )
- {
- has = true;
- }
- }
+ return mImpl->GetMapPtr();
}
-
- return has;
+ return nullptr;
}
-
-const std::string& Property::Value::GetKey(const int index) const
+bool Property::Value::Get(Extents& extentsValue) const
{
- switch( GetType() )
+ bool converted = false;
+ if(mImpl)
{
- case Property::MAP:
+ if(mImpl->GetType() == EXTENTS)
{
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
- DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
- if(container)
- {
- if(0 <= index && index < static_cast<int>(container->Count()))
- {
- return container->GetKey( index );
- }
- }
+ extentsValue = mImpl->GetExtents();
+ converted = true;
}
- break;
- case Property::NONE:
- case Property::ARRAY:
- case Property::BOOLEAN:
- case Property::FLOAT:
- case Property::UNSIGNED_INTEGER:
- case Property::INTEGER:
- case Property::VECTOR2:
- case Property::VECTOR3:
- case Property::VECTOR4:
- case Property::MATRIX:
- case Property::MATRIX3:
- case Property::RECTANGLE:
- case Property::ROTATION:
- case Property::STRING:
- case Property::TYPE_COUNT:
+ else if(mImpl->GetType() == VECTOR4)
{
- break;
+ auto& obj = mImpl->GetVector4();
+ extentsValue.start = static_cast<uint16_t>(obj.x);
+ extentsValue.end = static_cast<uint16_t>(obj.y);
+ extentsValue.top = static_cast<uint16_t>(obj.z);
+ extentsValue.bottom = static_cast<uint16_t>(obj.w);
+ converted = true;
}
}
-
-
- // should never return this
- static std::string null;
- return null;
+ return converted;
}
-
-void Property::Value::SetValue(const std::string& key, const Property::Value &value)
+std::ostream& operator<<(std::ostream& stream, const Property::Value& value)
{
- DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid");
-
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
-
- if(container)
+ if(value.mImpl)
{
- (*container)[ key ] = value;
- }
-}
+ auto obj = value.mImpl;
-Property::Value& Property::Value::GetItem(const int index) const
-{
- switch( GetType() )
- {
- case Property::MAP:
+ switch(obj->GetType())
{
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
-
- DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
- if(container)
+ case Dali::Property::BOOLEAN:
{
- DALI_ASSERT_ALWAYS(index < static_cast<int>(container->Count()) && "Property array index invalid");
- DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
-
- return container->GetValue( index );
+ stream << obj->GetBool();
+ break;
}
- }
- break;
-
- case Property::ARRAY:
- {
- int i = 0;
- Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
-
- DALI_ASSERT_DEBUG(container && "Property::Map has no container?");
- if(container)
+ case Dali::Property::FLOAT:
{
- DALI_ASSERT_ALWAYS(index < static_cast<int>(container->size()) && "Property array index invalid");
- DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid");
-
- for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter)
- {
- if(i++ == index)
- {
- return *iter;
- }
- }
+ stream << obj->GetFloat();
+ break;
}
- }
- break;
-
- case Property::NONE:
- case Property::BOOLEAN:
- case Property::FLOAT:
- case Property::INTEGER:
- case Property::UNSIGNED_INTEGER:
- case Property::VECTOR2:
- case Property::VECTOR3:
- case Property::VECTOR4:
- case Property::MATRIX3:
- case Property::MATRIX:
- case Property::RECTANGLE:
- case Property::ROTATION:
- case Property::STRING:
- case Property::TYPE_COUNT:
- {
- DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container");
- break;
- }
-
- } // switch GetType()
-
-
- DALI_ASSERT_ALWAYS(!"Property value index not valid");
-}
-
-Property::Value& Property::Value::GetItem(const int index, std::string& key) const
-{
- Property::Value& ret( GetItem(index) );
-
- if( Property::MAP == GetType() )
- {
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
- if( index < static_cast<int>(container->Count()) )
- {
- key = container->GetKey( index );
- }
- }
-
- return ret;
-}
-
-void Property::Value::SetItem(const int index, const Property::Value &value)
-{
- switch( GetType() )
- {
- case Property::MAP:
- {
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
- if( container && index < static_cast<int>(container->Count()) )
+ case Dali::Property::INTEGER:
{
- Property::Value& indexValue = container->GetValue( index );
- indexValue = value;
+ stream << obj->GetInt();
+ break;
}
- }
- break;
-
- case Property::ARRAY:
- {
- Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
- if( container && index < static_cast<int>(container->size()) )
+ case Dali::Property::VECTOR2:
{
- (*container)[index] = value;
+ stream << obj->GetVector2();
+ break;
}
- }
- break;
-
- case Property::NONE:
- case Property::BOOLEAN:
- case Property::FLOAT:
- case Property::INTEGER:
- case Property::UNSIGNED_INTEGER:
- case Property::VECTOR2:
- case Property::VECTOR3:
- case Property::VECTOR4:
- case Property::MATRIX3:
- case Property::MATRIX:
- case Property::RECTANGLE:
- case Property::ROTATION:
- case Property::STRING:
- case Property::TYPE_COUNT:
- {
- DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container");
- break;
- }
- }
-}
-
-int Property::Value::AppendItem(const Property::Value &value)
-{
- DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid");
-
- Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
-
- if(container)
- {
- container->push_back(value);
- return container->size() - 1;
- }
- else
- {
- return -1;
- }
-
-}
-
-int Property::Value::GetSize() const
-{
- int ret = 0;
-
- switch(GetType())
- {
- case Property::MAP:
- {
- Property::Map *container = AnyCast<Property::Map>(&(mImpl->mValue));
- if(container)
+ case Dali::Property::VECTOR3:
{
- ret = container->Count();
+ stream << obj->GetVector3();
+ break;
}
- }
- break;
-
- case Property::ARRAY:
- {
- Property::Array *container = AnyCast<Property::Array>(&(mImpl->mValue));
- if(container)
+ case Dali::Property::VECTOR4:
{
- ret = container->size();
+ stream << obj->GetVector4();
+ break;
+ }
+ case Dali::Property::MATRIX3:
+ {
+ stream << obj->GetMatrix3();
+ break;
+ }
+ case Dali::Property::MATRIX:
+ {
+ stream << obj->GetMatrix();
+ break;
+ }
+ case Dali::Property::RECTANGLE:
+ {
+ stream << obj->GetRect();
+ break;
+ }
+ case Dali::Property::ROTATION:
+ {
+ stream << obj->GetAngleAxis();
+ break;
+ }
+ case Dali::Property::STRING:
+ {
+ stream << obj->GetString();
+ break;
+ }
+ case Dali::Property::ARRAY:
+ {
+ stream << obj->GetArray();
+ break;
+ }
+ case Dali::Property::MAP:
+ {
+ stream << obj->GetMap();
+ break;
+ }
+ case Dali::Property::EXTENTS:
+ {
+ stream << obj->GetExtents();
+ break;
+ }
+ case Dali::Property::NONE:
+ { // mImpl will be a nullptr, there's no way to get to this case
}
}
- break;
-
- case Property::NONE:
- case Property::BOOLEAN:
- case Property::FLOAT:
- case Property::INTEGER:
- case Property::UNSIGNED_INTEGER:
- case Property::VECTOR2:
- case Property::VECTOR3:
- case Property::VECTOR4:
- case Property::MATRIX3:
- case Property::MATRIX:
- case Property::RECTANGLE:
- case Property::ROTATION:
- case Property::STRING:
- case Property::TYPE_COUNT:
- {
- break;
- }
-
}
-
- return ret;
+ else
+ {
+ stream << "undefined type";
+ }
+ return stream;
}
-
} // namespace Dali